changeset 33377:d7e4a4e1a8fb

maint: Merge stable to default.
author Markus Mützel <markus.muetzel@gmx.de>
date Fri, 12 Apr 2024 15:10:26 +0200
parents a45ccf01d41b (diff) a8ce25c80695 (current diff)
children 7e7d52c1e03a
files libgui/graphics/Figure.cc libinterp/corefcn/graphics.cc
diffstat 775 files changed, 17763 insertions(+), 15083 deletions(-) [+]
line wrap: on
line diff
--- a/.github/workflows/make.yaml	Sat Apr 06 14:43:10 2024 +0200
+++ b/.github/workflows/make.yaml	Fri Apr 12 15:10:26 2024 +0200
@@ -636,7 +636,7 @@
       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, UCRT64]
+        msystem: [MINGW64, CLANG64]
         include:
           - msystem: MINGW64
             mingw-prefix: mingw64
@@ -646,14 +646,23 @@
             f77: gfortran
             extra-config-flags: ""
             ccache-max: 0.9G
-          - msystem: UCRT64
-            mingw-prefix: ucrt64
-            target-prefix: mingw-w64-ucrt-x86_64
-            cc: gcc
-            cxx: g++
-            f77: gfortran
-            extra-config-flags: ""
-            ccache-max: 0.9G
+            allow-error: false
+          - 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
+              ac_cv_f77_compiler_gnu=yes
+              lt_cv_prog_gnu_ld=yes
+            ccache-max: 400M
+            # This configuration is not fully supported yet
+            allow-error: true
 
     env:
       CHERE_INVOKING: 1
@@ -849,6 +858,7 @@
           make -C ./.build DESTDIR=/c/octave/pkg install
 
       - name: test stand-alone executable
+        continue-on-error: ${{ matrix.allow-error }}
         run: |
           unset CC
           unset CXX
@@ -861,10 +871,26 @@
       - name: analyze test suite results
         # Make sure the test summary lists 0 "FAIL"s and no "REGRESSION"
         run: |
-          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || (echo "::warning::At least one test failed" && exit 1)
-          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || (echo "::warning::At least one regression in test suite" && exit 1)
+          [ -n "$(grep -e "FAIL\s*0" ./test-suite.log)" ] || echo "::warning::At least one test failed"
+          [ -z "$(grep -e "REGRESSION" ./test-suite.log)" ] || echo "::warning::At least one regression in test suite"
           echo Finished analyzing test suite results.
 
+      - name: compress build artifact
+        if: matrix.msystem == 'MINGW64'
+        continue-on-error: true
+        run: |
+          cd /c/octave/pkg
+          tar -cvzf octave.tar.gz *
+
+      - name: upload build artifact
+        if: matrix.msystem == 'MINGW64'
+        continue-on-error: true
+        uses: actions/upload-artifact@v4
+        with:
+          name: ${{ matrix.target-prefix }}-octave-${{ steps.ccache-prepare.outputs.timestamp }}
+          path: C:\octave\pkg\octave.tar.gz
+          retention-days: 7
+
 
   cygwin:
     runs-on: ${{ matrix.os }}
@@ -1020,6 +1046,7 @@
       - name: configure
         # FIXME: Fix building with Java support.  Override JAVA_HOME for now.
         # FIXME: How do we get a working TeX environment in Cygwin?  Disable building the documentation for now.
+        # FIXME: Exporting symbols for instantiated template classes doesn't work currently. Maybe, test again when Cygwin updated to a newer compiler than GCC 11.4.0?
         run: |
           echo $PATH
           which $CC
@@ -1037,6 +1064,7 @@
             --enable-shared \
             --disable-java \
             --disable-docs \
+            --disable-lib-visibility-flags \
             JAVA_HOME="" \
             EGREP="grep -E" \
             FLIBS="-lgfortran -lquadmath"
--- a/bootstrap.conf	Sat Apr 06 14:43:10 2024 +0200
+++ b/bootstrap.conf	Fri Apr 12 15:10:26 2024 +0200
@@ -43,6 +43,7 @@
   crypto/sha512-buffer
   dup2
   fcntl
+  fflush
   filemode
   fnmatch
   fpucw
--- a/build-aux/mk-octave-config-h.sh	Sat Apr 06 14:43:10 2024 +0200
+++ b/build-aux/mk-octave-config-h.sh	Fri Apr 12 15:10:26 2024 +0200
@@ -104,7 +104,6 @@
 
 $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
--- a/configure.ac	Sat Apr 06 14:43:10 2024 +0200
+++ b/configure.ac	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,7 @@
 
 ### Initialize Autoconf
 AC_PREREQ([2.65])
-AC_INIT([GNU Octave], [9.1.1], [https://octave.org/bugs.html], [octave],
+AC_INIT([GNU Octave], [10.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=9
-OCTAVE_MINOR_VERSION=1
-OCTAVE_PATCH_VERSION=1
+OCTAVE_MAJOR_VERSION=10
+OCTAVE_MINOR_VERSION=0
+OCTAVE_PATCH_VERSION=0
 
 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument.
 OCTAVE_VERSION="$PACKAGE_VERSION"
@@ -313,10 +313,14 @@
 AC_PROG_CXX
 AC_PROG_CXXCPP
 
-ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=no
+## Ensure that the C++ compiler fully supports C++17.
+## Preferably with GNU extensions if flags are required.
+AX_CXX_COMPILE_STDCXX(17, [], mandatory)
+
+ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=yes
 AC_ARG_ENABLE(std-pmr-polymorphic-allocator,
-  [AS_HELP_STRING([--enable-std-pmr-polymorphic-allocator],
-    [build libraries requiring std::pmr::polymorphic_allocator if possible.  This allows more efficient transfer of arrays at the .mex file interface.  That also means that all libraries including Octave headers (e.g., .oct files) must be able to compile with that C++17 feature.])],
+  [AS_HELP_STRING([--disable-std-pmr-polymorphic-allocator],
+    [build libraries that do not require support for std::pmr::polymorphic_allocator.  This prevents more efficient transfer of arrays at the .mex file interface.])],
   [case $enableval in
      yes) ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=yes ;;
      no) ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR=no ;;
@@ -340,34 +344,6 @@
 
 ### Determine C++ compiler capabilities.
 
-if test "$QT_VERSIONS" = 6; then
-  ## If QT_VERSIONS is set to 6, require that the C++ compiler fully
-  ## supports C++17.  Preferably with GNU extensions if flags are required.
-  ## We could use "AX_CXX_COMPILE_STDCXX(17, [], mandatory)" in this case.
-  ## But prefer to emit a more helpful error message.
-  AX_CXX_COMPILE_STDCXX(17, [], [])
-  if test "$HAVE_CXX17" = 0; then
-    ## The user explicitly requested Qt6.  But the C++ compiler lacks
-    ## support for C++17.
-    AC_MSG_ERROR([Qt6 requires a compiler that supports C++17.  Configure with "--with-qt=5" or "--without-qt", or use a compiler that supports C++17.])
-  fi
-elif test -z "${QT_VERSIONS+x}" || test $ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR = yes; then
-  ## If QT_VERSIONS is not explicitly set, check if the C++ compiler fully
-  ## supports C++17 (but don't require it).
-  ## The defaults for the Qt version will depend on the result of this check.
-  AX_CXX_COMPILE_STDCXX(17, [], [])
-else
-  ## Set HAVE_CXX17 to 0 because we don't require it (even if the used
-  ## C++ compiler might technically support C++17).
-  HAVE_CXX17=0
-fi
-
-if test "$HAVE_CXX17" = 0; then
-  ## Ensure that the C++ compiler fully supports C++11.
-  ## Preferably with GNU extensions if flags are required.
-  AX_CXX_COMPILE_STDCXX(11, [], mandatory)
-fi
-
 if test $ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR = yes; then
   OCTAVE_CHECK_STD_PMR_POLYMORPHIC_ALLOCATOR
 fi
@@ -952,28 +928,6 @@
 AC_SUBST(MKOCTFILE_F77)
 AC_SUBST(MKOCTFILE_RANLIB)
 
-### Enable float truncation to work around issues with x87 co-processors
-
-dnl When compiling math for x87, problems may arise in some code comparing
-dnl floating-point intermediate results.  The root cause is the extra precision
-dnl (~80 bits) of x87 co-processor registers versus the IEEE standard 64 bits.
-dnl Generally, storing the result in a local volatile variable forces a
-dnl truncation back to 64 bits, but it also degrades performance.
-dnl However, this performance degradation is very minimal, if indeed measurable.
-dnl Therefore, it has been enabled for all platforms and compilers.
-dnl Reported bugs indicate that --enable-float-truncate is required for MinGW
-dnl and Cygwin platforms and for GCC compilers >= 5.0.  It should not be
-dnl necessary for non-x87 targets or when using modern SSE math.
-ENABLE_FLOAT_TRUNCATE=yes
-AC_ARG_ENABLE([float-truncate],
-  [AS_HELP_STRING([--disable-float-truncate],
-    [truncate intermediate FP results])],
-  [if test "$enableval" = no; then ENABLE_FLOAT_TRUNCATE=no; fi], [])
-if test $ENABLE_FLOAT_TRUNCATE = yes; then
-  AC_DEFINE(OCTAVE_ENABLE_FLOAT_TRUNCATE, 1,
-    [Define to 1 to truncate intermediate FP results.])
-fi
-
 ### Enable internal checks
 
 ## The checks slow down the execution and are redundant,
@@ -2803,10 +2757,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 ;;
@@ -3410,7 +3364,6 @@
   64-bit BLAS array dims and indexing:  $HAVE_64_BIT_BLAS
   Use std::pmr::polymorphic_allocator:  $ENABLE_STD_PMR_POLYMORPHIC_ALLOCATOR
   OpenMP SMP multithreading:            $ENABLE_OPENMP
-  Truncate intermediate FP results:     $ENABLE_FLOAT_TRUNCATE
   Include support for GNU readline:     $USE_READLINE
   Use push parser in command line REPL: $ENABLE_COMMAND_LINE_PUSH_PARSER
   Build cross tools:                    $cross_tools
--- a/doc/interpreter/basics.txi	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/basics.txi	Fri Apr 12 15:10:26 2024 +0200
@@ -73,13 +73,14 @@
 built-in functions of Octave.  This value is normally correct and should
 only need to be specified in extraordinary situations.
 
-@item  --debug
-@itemx -d
-@cindex @sortas{options, Octave command --debug} @ @ @code{--debug}
-@cindex @sortas{options, Octave command -d} @ @ @code{-d}
-Enter parser debugging mode.  Using this option will cause Octave's
-parser to print a lot of information about the commands it reads, and is
-probably only useful if you are actually trying to debug the parser.
+@c FIXME: Disabled debug option for parser 2023-12-29.
+@c Uncomment and restore code if Octave adds capability to
+@c immediately enter debug mode for a script.
+@c @item  --debug
+@c @itemx -d
+@c @cindex @sortas{options, Octave command --debug} @ @ @code{--debug}
+@c @cindex @sortas{options, Octave command -d} @ @ @code{-d}
+@c Enter debugging mode.
 
 @item --doc-cache-file @var{filename}
 @cindex @sortas{options, Octave command --doc-cache-file} @ @ @code{--doc-cache-file @var{filename}}
@@ -95,7 +96,8 @@
 @cindex @sortas{options, Octave command -x} @ @ @code{-x}
 Echo commands as they are executed.
 
-@item --eval @var{code}
+@item  --eval @var{code}
+@itemx -e @var{code}
 @cindex @sortas{options, Octave command --eval} @ @ @code{--eval @var{code}}
 Evaluate @var{code} and exit when finished unless @option{--persist} is also
 specified.
@@ -108,7 +110,8 @@
 in the system or user startup files that call the
 @w{@env{EXEC_PATH}}@ function.
 
-@item --gui
+@item  --gui
+@itemx -g
 @cindex @sortas{options, Octave command --gui} @ @ @code{--gui}
 Start the graphical user interface (GUI).
 
@@ -142,6 +145,11 @@
 commands in the system or user startup files that use the
 @code{info_program} function.
 
+@item  --init-trace
+@cindex @sortas{options, Octave command --init-trace} @ @ @code{--init-trace}
+Print the name of each configuration as it is read and executed during
+initialization.
+
 @item  --interactive
 @itemx -i
 @cindex @sortas{options, Octave command --interactive} @ @ @code{--interactive}
@@ -153,7 +161,8 @@
 @cindex @sortas{options, Octave command --line-editing} @ @ @code{--line-editing}
 Force readline use for command-line editing.
 
-@item --no-gui
+@item  --no-gui
+@itemx -G
 @cindex @sortas{options, Octave command --no-gui} @ @ @code{--no-gui}
 Disable the graphical user interface (GUI) and use the command line
 interface (CLI) instead.  This is the default behavior, but this option
@@ -165,26 +174,37 @@
 @cindex @sortas{options, Octave command -H} @ @ @code{-H}
 Disable recording of command-line history.
 
-@item --no-init-file
-@cindex @sortas{options, Octave command --no-init-file} @ @ @code{--no-init-file}
-@cindex @sortas{octaverc ~/.octaverc} @code{~/.octaverc}
-@cindex @sortas{octaverc .octaverc} @code{.octaverc}
-Don't read the initialization files @file{~/.octaverc} and @file{.octaverc}.
+@item  --no-init-all
+@itemx --norc
+@itemx -f
+@cindex @sortas{options, Octave command --no-init-all} @ @ @code{--no-init-all}
+@cindex @sortas{options, Octave command --norc} @ @ @code{--norc}
+@cindex @sortas{options, Octave command -f} @ @ @code{-f}
+Don't read any of the system or user initialization files at startup.
+This is equivalent to using both of the options @option{--no-site-file}
+and @option{--no-init-user}.
 
 @item --no-init-path
 @cindex @sortas{options, Octave command --no-init-path} @ @ @code{--no-init-path}
 Don't initialize the search path for function files to include default
 locations.
 
+@item --no-init-site
+@cindex @sortas{options, Octave command --no-init-site} @ @ @code{--no-init-site}
+@cindex site startup file
+Don't read the site-wide @file{octaverc} initialization files.
+
+@item --no-init-user
+@cindex @sortas{options, Octave command --no-init-user} @ @ @code{--no-init-user}
+@cindex @sortas{octaverc ~/.octaverc} @code{~/.octaverc}
+@cindex @sortas{octaverc .octaverc} @code{.octaverc}
+Don't read the user initialization files @file{~/.octaverc} and
+@file{.octaverc}.
+
 @item --no-line-editing
 @cindex @sortas{options, Octave command --no-line-editing} @ @ @code{--no-line-editing}
 Disable command-line editing.
 
-@item --no-site-file
-@cindex @sortas{options, Octave command --no-site-file} @ @ @code{--no-site-file}
-@cindex site startup file
-Don't read the site-wide @file{octaverc} initialization files.
-
 @item  --no-window-system
 @itemx -W
 @cindex @sortas{options, Octave command --no-window-system} @ @ @code{--no-window-system}
@@ -192,14 +212,6 @@
 Disable use of a windowing system including graphics.  This forces a
 strictly terminal-only environment.
 
-@item  --norc
-@itemx -f
-@cindex @sortas{options, Octave command --norc} @ @ @code{--norc}
-@cindex @sortas{options, Octave command -f} @ @ @code{-f}
-Don't read any of the system or user initialization files at startup.
-This is equivalent to using both of the options @option{--no-init-file}
-and @option{--no-site-file}.
-
 @item  --path @var{path}
 @itemx -p @var{path}
 @cindex @sortas{options, Octave command --path} @ @ @code{--path @var{path}}
@@ -215,11 +227,11 @@
 Go to interactive mode after @option{--eval} or reading from a file
 named on the command line.
 
-@item  --silent
-@itemx --quiet
+@item  --quiet
+@itemx --silent
 @itemx -q
+@cindex @sortas{options, Octave command --quiet} @ @ @code{--quiet}
 @cindex @sortas{options, Octave command --silent} @ @ @code{--silent}
-@cindex @sortas{options, Octave command --quiet} @ @ @code{--quiet}
 @cindex @sortas{options, Octave command -q} @ @ @code{-q}
 Don't print the usual greeting and version message at startup.
 
@@ -273,12 +285,6 @@
 that works in Octave but not @sc{matlab} (@pxref{XREFwarning,,warning},
 @ref{XREFwarning_ids,,warning_ids}).
 
-@item  --verbose
-@itemx -V
-@cindex @sortas{options, Octave command --verbose} @ @ @code{--verbose}
-@cindex @sortas{options, Octave command -V} @ @ @code{-V}
-Turn on verbose output.
-
 @item  --version
 @itemx -v
 @cindex @sortas{options, Octave command --version} @ @ @code{--version}
@@ -384,7 +390,7 @@
 
 A message will be displayed as each of the startup files is read if you
 invoke Octave with the @option{--verbose} option but without the
-@option{--silent} option.
+@option{--quiet} option.
 
 The startup files are always processed in the system's locale charset
 (independent of the m-file encoding that is set, for example, in the GUI
--- a/doc/interpreter/doccheck/mk_undocumented_list	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/doccheck/mk_undocumented_list	Fri Apr 12 15:10:26 2024 +0200
@@ -34,7 +34,7 @@
 ################################################################################
 # Get a list from Octave of all visible functions
 @octave_output = <<`_END_OCT_SCRIPT_`;
-../../run-octave --norc --silent --no-history --eval '\
+../../run-octave --norc --quiet --no-history --eval '\
   funclist = vertcat (__list_functions__ , __builtins__); \
   funclist = funclist(! strncmp (funclist, \"meta.\", 5)) \
   disp ("#!-separator-!#") \
--- a/doc/interpreter/expr.txi	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/expr.txi	Fri Apr 12 15:10:26 2024 +0200
@@ -52,7 +52,7 @@
 An @dfn{index expression} allows you to reference or extract selected
 elements of a vector, a matrix (2-D), or a higher-dimensional array.  Arrays
 may be indexed in one of three ways:
-@ref{XREFComponentIndexing,,Component Indexing}, 
+@ref{XREFComponentIndexing,,Component Indexing},
 @ref{XREFLinearIndexing,,Linear Indexing}, and
 @ref{XREFLogicalIndexing,,Logical Indexing}.
 
@@ -309,7 +309,7 @@
 @cindex Chained indexing
 Octave permits the use of repeated (chained) index expressions to extract
 subsets of an array in a single command without the need to use intermediate
-variables.  This can make it easier to write code with either complicated 
+variables.  This can make it easier to write code with either complicated
 indexing operations or using multiple indexing methods. The following example
 shows two equivalent index extraction operations:
 
--- a/doc/interpreter/external.txi	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/external.txi	Fri Apr 12 15:10:26 2024 +0200
@@ -310,7 +310,7 @@
 
 Note that these functions do significant error checking and so in some
 circumstances the user might prefer to access the data of the array or matrix
-directly through the @code{fortran_vec} method discussed below.
+directly through the @code{rwdata} method discussed below.
 
 @deftypefn {Method} {octave_idx_type} numel () const
 The total number of elements in the matrix or array.
@@ -336,7 +336,7 @@
 of rows and columns in the matrix.
 @end deftypefn
 
-@deftypefn {Method} {T *} fortran_vec ()
+@deftypefn {Method} {T *} rwdata ()
 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.
@@ -646,7 +646,7 @@
 @end example
 
 Finally, because the sparse types aren't represented by a contiguous block of
-memory, the @nospell{@code{fortran_vec}} method of @code{Array<T>} is not
+memory, the @nospell{@code{rwdata}} method of @code{Array<T>} is not
 available.  It is, however, replaced by three separate methods @code{ridx},
 @code{cidx}, and @code{data}, that access the raw compressed column format that
 Octave sparse matrices are stored in.  These methods can be used in a manner
@@ -1010,7 +1010,7 @@
 macros to allow writing code that can be used with different Fortran calling
 conventions.
 
-Note that we don't attempt to handle Fortran functions, we always use 
+Note that we don't attempt to handle Fortran functions, we always use
 subroutine wrappers for them and pass the return value as an extra argument.
 
 Use the following macros to pass character strings from C to Fortran:
@@ -1220,7 +1220,7 @@
 The disadvantage of this is that if the foreign code allocates any memory
 internally, then this memory might be lost during an interrupt, without being
 deallocated.  Therefore, ideally Octave itself should allocate any memory that
-is needed by the foreign code, with either the @nospell{@code{fortran_vec}}
+is needed by the foreign code, with either the @nospell{@code{rwdata}}
 method or the @w{@code{OCTAVE_LOCAL_BUFFER}}@ macro.
 
 The Octave @code{unwind_protect} mechanism (@ref{The unwind_protect Statement})
--- a/doc/interpreter/graphics_properties.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/graphics_properties.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -11,7 +11,7 @@
 
 define gen-propdoc-texi
   rm -f $@-t $@ && \
-  $(top_builddir)/run-octave -disable-asan --norc --silent --no-history --path $(srcdir)/interpreter --eval "genpropdoc ('$(1)');" > $@-t && \
+  $(top_builddir)/run-octave -disable-asan --norc --quiet --no-history --path $(srcdir)/interpreter --eval "genpropdoc ('$(1)');" > $@-t && \
   mv $@-t $@
 endef
 
--- a/doc/interpreter/images.awk	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/images.awk	Fri Apr 12 15:10:26 2024 +0200
@@ -54,7 +54,7 @@
 
     for (j = 2; j <= NF; j++) {
       printf ("%s%s.%s: %s%s\n", dir, $j, ext, dir, script);
-      printf ("\t$(AM_V_GEN)$(SHELL) run-octave -disable-asan --norc --silent --no-history --path $(abs_top_srcdir)/%s --eval \"%s ('%s', '%s', '%s');\"\n",
+      printf ("\t$(AM_V_GEN)$(SHELL) run-octave -disable-asan --norc --quiet --no-history --path $(abs_top_srcdir)/%s --eval \"%s ('%s', '%s', '%s');\"\n",
               dir, basename, dir, $j, ext);
     }
   }
--- a/doc/interpreter/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 
 define gen-propdoc-texi
   rm -f $@-t $@ && \
-  $(SHELL) run-octave -disable-asan --norc --silent --no-history --path $(srcdir)/doc/interpreter --eval "genpropdoc ('$(1)');" > $@-t && \
+  $(SHELL) run-octave -disable-asan --norc --quiet --no-history --path $(srcdir)/doc/interpreter --eval "genpropdoc ('$(1)');" > $@-t && \
   mv $@-t $@
 endef
 
--- a/doc/interpreter/numbers.txi	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/numbers.txi	Fri Apr 12 15:10:26 2024 +0200
@@ -752,7 +752,7 @@
 
 Logical values can also be used to index matrices and cell arrays.
 When indexing with a logical array the result will be a vector containing
-the values corresponding to @code{true} parts of the logical array. 
+the values corresponding to @code{true} parts of the logical array.
 @xref{XREFLogicalIndexing, , Logical Indexing}.
 
 Logical values can also be constructed by
--- a/doc/interpreter/octave.1	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/octave.1	Fri Apr 12 15:10:26 2024 +0200
@@ -70,7 +70,7 @@
 .UR https://\:docs.octave.org/\:latest
 .UE .
 .SH BUGS
-The Octave project maintains a bug tracker at 
+The Octave project maintains a bug tracker at
 .UR https://\:bugs.octave.org
 .UE .
 Before submitting a new item please read the instructions at
--- a/doc/interpreter/plot.txi	Sat Apr 06 14:43:10 2024 +0200
+++ b/doc/interpreter/plot.txi	Fri Apr 12 15:10:26 2024 +0200
@@ -299,10 +299,10 @@
 
 @DOCSTRING(axis)
 
-Similarly the axis limits of the colormap can be changed with the caxis
+Similarly the axis limits of the colormap can be changed with the @code{clim}
 function.
 
-@DOCSTRING(caxis)
+@DOCSTRING(clim)
 
 The @code{xlim}, @code{ylim}, and @code{zlim} functions may be used to
 get or set individual axis limits.  Each has the same form.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/NEWS.10.md	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,146 @@
+Summary of important user-visible changes for version 10 (yyyy-mm-dd):
+---------------------------------------------------------------------
+
+### General improvements
+
+- Three short form aliases have been added for long form options when starting
+`octave`.
+  * `-e CODE` for `--eval CODE`
+  * `-g` for `--gui`
+  * `-G` for `--no-gui`
+
+- Three long form options have been introduced for clarity.
+  * `--no-init-user` : Don't read user configuration files ~/.octaverc or
+    .octaverc files at startup.
+  * `--no-init-site` : Don't read site-wide configuration files at startup.
+  * `--no-init-all` : Don't read any configuration files at startup.
+
+- `nchoosek` algorithm is now ~2x faster and provides greater precision.
+
+- `nextpow2` algorithm is now more accurate for inputs very close to a power
+of 2.  The output class now matches the input class for Matlab compatibility.
+The function no longer accepts complex inputs and will emit an error for these
+inputs.
+
+- `jsonencode` now outputs integers and floating point integers without ".0"
+  suffix.
+  
+- `hist` now accepts N-dimensional array inputs for input `Y` which is
+  processed in columns as if the array was flattened to a 2-dimensional
+  array.
+
+### Graphical User Interface
+
+### Graphics backend
+
+- `polar` plots now include the center tick mark value, typically 0, in
+the 'rtick' parameter when the plot is created.  Subsequent modifications
+to 'rtick' by the function `rticks` will only include the center tick mark
+value if it is specified.
+
+### Matlab compatibility
+
+- `height` and `width` are now aliases for the `rows` and `columns` functions.
+
+- All colormaps now default to a size of 256 colors. (The previous default
+size was 64.
+
+- `griddata` output size more consistently matches the input interpolation
+points when they are input as vectors.  When they are same-orientation vectors,
+the outputs will be the same size as those vectors.  When either is a row
+vector and the other is a column vector, the interpolating points are processed
+through meshgrid and the output is a matrix the same size as the meshgrid.
+
+- Enable the third output for `unique` with the `stable` sort option.
+
+- `iqr` now provides compatible output for empty inputs.
+
+- `cross` now produces row vector outputs when the inputs are a mix of row
+and column vectors. (bug #61295)
+
+- Octave functions whose Matlab equivalents give errors when passed non-integer
+values as sizes or dimensions now also give similar errors.
+E.g., `cell (e, pi)` now gives an error in Octave about requiring integer
+sizes for the cell array, matching Matlab behavior.
+Previously, Octave's conversion from non-integers to integers was more lenient.
+
+### Alphabetical list of new functions added in Octave 10
+
+* `clim`
+* `rticklabels`
+* `tticklabels`
+
+### Deprecated functions, properties, and operators
+
+The following functions and properties have been deprecated in Octave 10
+and will be removed from Octave 12 (or whatever version is the second
+major release after 10):
+
+- Functions
+
+        Function               | Replacement
+        -----------------------|------------------
+
+- Core
+
+        Function                              | Replacement
+        --------------------------------------|------------------
+        symbol_record_rep::mark_as_variable   | symbol_record_rep::mark_variable
+        symbol_record_rep::unmark_as_variable | symbol_record_rep::unmark_variable
+        symbol_record::mark_as_variable       | symbol_record::mark_variable
+        symbol_record::unmark_as_variable     | symbol_record::unmark_variable
+        interpreter::verbose                  | interpreter::init_trace
+        cmdline_options::verbose              | cmdline_options::init_trace
+
+  - A new method `rwdata ()` provides direct read/write access (a pointer) to the
+data in a liboctave `Array` object (or its derived classes such as `Matrix`).
+Historically, the method `fortran_vec ()` provided this access, but the name
+is unclear, and it is recommended to use `rwdata ()` in any new code.  There
+are no plans to deprecate `fortran_vec`.
+
+  - The `--verbose`,`-V` command-line option has been deprecated.  Use
+`--init-trace` to print the configuration files executed during initialization.
+
+The following features were deprecated in Octave 8 and have been removed
+from Octave 10.
+
+- Functions
+
+        Function               | Replacement
+        -----------------------|------------------
+        shift                  | circshift
+        sparse_auto_mutate     | none (see below)
+
+- `fminsearch` parameter passing:  A legacy, undocumented, and only partially
+  supported syntax for passing parameters to the minimized function `fcn`
+  called by `fminsearch` by appending them to the input argument list has
+  functioned intermittently since Octave 4.4.0.  Due to conflicts with other
+  compatibility-required input methods the documentation of this syntax was
+  removed in Octave 5.1.0, and the remaining functionality has been completely
+  removed in Octave 10, and attempts to call `fminsearch` with that syntax
+  will result in an error. The preferred, cross-platform compatible method of
+  passing parameters to any of the minimization functions (including
+  `fminsearch`, `fminbnd`, and `fminunc`) is through the use of Anonymous
+  Functions.  Specific examples of this can be found in the @ref{Minimizers}
+  section of the GNU Octave manual.
+
+### Build system
+
+- Octave now requires a C++ compiler that is compliant with C++17 (preferably
+with GNU extensions).
+
+
+Summary of bugs fixed for version 10.1.0 (yyyy-mm-dd):
+----------------------------------------------------
+
+### Old release news
+
+- [Octave 9.x](etc/NEWS.9.md)
+- [Octave 8.x](etc/NEWS.8.md)
+- [Octave 7.x](etc/NEWS.7.md)
+- [Octave 6.x](etc/NEWS.6.md)
+- [Octave 5.x](etc/NEWS.5.md)
+- [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/RELEASE_CHECKLIST.md	Sat Apr 06 14:43:10 2024 +0200
+++ b/etc/RELEASE_CHECKLIST.md	Fri Apr 12 15:10:26 2024 +0200
@@ -24,6 +24,9 @@
   `etc/HACKING.md`).
 * Bump version numbers in `configure.ac` on default branch (see
   `etc/HACKING.md`).
+* Create new `etc/NEWS.VERSION+1.md` file on default branch by copying
+  `etc/NEWS.VERSION.md` and then removing text so that it is a template file
+  with headings only.
 
 ### ⚙️ Update gnulib to latest version ###
 
@@ -37,10 +40,13 @@
 
 Completion Date:
 
-* Put out a general call for reports on [Octave Discourse](https://octave.discourse.group/) for all outstanding unreported known bugs.
-* Create Savannah tag `VERSION.0.90` on bug tracker for 1st release candidate.
+* Put out a general call for reports on [Octave Discourse](https://octave.discourse.group/) for all outstanding, but unreported, known bugs.
+* Create Savannah `Release` tag `VERSION.0.90` on bug tracker for 1st release
+  candidate.
 * Mark items that should be fixed for the release with this tag.
-* Bug overview at <https://octave.space/savannah/>.
+* Update Savannah `Planned Release` and `Fixed Release` tags by adding
+  `VERSION.1.0 (current stable)` and `VERSION+1.1.0 (current default)`.
+* Review bug overview at <https://octave.space/savannah/>.
 
 ### 📢 Update GUI translation files ###
 
@@ -50,7 +56,7 @@
   might change GUI strings.
 * String freeze date:
 * Update language translation files (`*.ts`).  See instructions in
-  `libgui/languages/build_ts/README.md`).
+  `libgui/languages/build_ts/README.md`.
 * Create bug report on Savannah as a centralized location for uploading files
   and tracking status of translations.
 * Call for translations of GUI strings on [Octave Discourse Maintainers](https://octave.discourse.group/c/maintainers/7), CC-ing the translators (see [list of translators](https://hg.savannah.gnu.org/hgweb/octave/file/tip/libgui/languages/translators)).
@@ -61,8 +67,16 @@
 Completion Date:
 
 * Update copyright statements for all source controlled files.
-* Update dates in any other locations (launch message, citation, MXE files,
-  etc.).
+
+    Command to update copyright notifications
+
+    `hg locate | xargs sed -i 's/Copyright (C) \([0-9][0-9][0-9][0-9]\)-2023 The Octave Project Developers/Copyright (C) \1-2024 The Octave Project Developers/; s/Copyright (C) 2023 The Octave Project Developers/Copyright (C) 2023-2024 The Octave Project Developers/'`
+
+    Command to check results before checking in
+
+    `hg diff | grep ^[-+][^-+] | sed 's/[0-9][0-9][0-9][0-9]-/YYYY-/' | sort -u`
+
+* Update dates in any other locations (`CITATION`, MXE `README.html` file).
 * Add any new contributors to `doc/interpreter/contributors.in` who wish to be
   mentioned (don't add them without permission).
 
@@ -110,8 +124,11 @@
 * Use software tools to check quality of Octave code.
   * Check for memory leaks by configuring with
     `--enable-address-sanitizer-flags` and compiling with
-    `-fsanitize=undefined`, `-fno-omit-frame-pointer` in `CFLAGS`, `CXXFLAGS`,
-    and `LDFLAGS`.
+    `-g -O0 -fno-optimize-sibling-calls` in `CFLAGS`, `CXXFLAGS`, and
+    `LDFLAGS`.
+  * Check for bad memory accesses by compiling with
+    `-g -O0 -fsanitize=undefined -fno-omit-frame-pointer
+    -fno-optimize-sibling-calls` in `CFLAGS`, `CXXFLAGS`, and `LDFLAGS`.
   * Update static code analysis results.
       * For `clang`, do `scan-build make -j<N> all` and then `scan-view`.
       * See [PVS static analyzer - 5.0 Release](https://wiki.octave.org/PVS_static_analyzer_-_5.0_Release).
@@ -150,17 +167,18 @@
 * Create `hg tag` in repository with release candidate version number
   (`release-VERSION-1-0`).
 * Update `etc/NEWS.VERSION.md` (final release date in Summary header).
-* Update `CITATION` (version, year, URL).
+* Update `CITATION` (version, year, URL) if not already done as part of "GPL
+  License activities.
 * Update `etc/icons/org.octave.Octave.appdata.xml` (version number and release
   date).
 * Upload all tarballs to <https://ftp.gnu.org/gnu/octave/>.
 * Update web site files: `NEWS-VERSION.html`, `index.in`, `news.in`, and
   `download.in`.
 * Update <https://wiki.octave.org/Release_History> page.
-* Update Savannah bug tracker version info to have new release number.
+* Update Savannah bug tracker `Release` field to have new release number.
 * Update Savannah bug tracker: **OPEN** bugs marked as **WON'T FIX** should be
   marked as **CONFIRMED** (or more appropriate) for the final release.
-* Hide release candidate versions in Savannah.
+* Hide release candidate versions for `Release` field on Savannah.
 
 ### 📢 Announce final release ###
 
@@ -181,9 +199,8 @@
 
 Completion Date:
 
-* Remove all deprecated functions (either tagged with `OCTAVE_DEPRECATED` in
-  C++ or in the directory `scripts/deprecated` for m-files) scheduled for
-  deletion on default branch.  Check file `etc/NEWS.VERSION-2.md` for list of
-  features that have been deprecated.
-* Create new `etc/NEWS.VERSION+1.md` file by copying `etc/NEWS.VERSION.md` and
-  then removing text so that it is a template file with headings only.
+* Remove all deprecated functions scheduled for deletion on default
+  branch.  These functions are tagged with `OCTAVE_DEPRECATED` in C++ or are
+  m-files located in the directory `scripts/deprecated`.  Check file
+  `etc/NEWS.VERSION-2.md` for list of features that have been deprecated.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etc/ROADMAP.md	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,118 @@
+Octave Roadmap (version 10 onwards)
+
+This roadmap is intended to be a living document, and serves multiple purposes:
+* For developers to agree on activities and large-scale features,
+* To decide priorities,
+* To inform new contributors where they can contribute and feel ownership,
+* To allow easier parcelling of smaller activities into GSoC etc,
+* To be a transparent basis for any financial decisions to spend project money.
+
+This document is different from a wishlist of features, such as those
+present on the Octave wiki, in that this document lists names of people
+willing to work on specific activities, whether they are contributors writing code
+themselves, or existing Octave maintainers soliciting / reviewing / accepting code
+from new contributors.
+
+* For new contributors, this is a way to get your contribution
+reviewed and merged into the Octave codebase with more confidence, and a way
+to work with a more experienced Octave developer on a named activity so you too
+can become an Octave developer over time.
+
+* For existing maintainers, this is a way to get new developers and
+contributors in, which helps Octave development scale.
+
+If you want to take ownership of some activity below, or create a new activity,
+please edit the list as necessary, add your name, and post about it on Discourse.
+If you can, please split up a large activity into smaller pieces that can then
+be specifically written by new contributors, GSoC interns, etc. The aim is to
+allow anyone to jump in to start contributing to a topic.
+
+This roadmap process starts from Octave 10. As has been the practice for many
+years, a major version of Octave is released each year, and no single feature
+will be "required" for any given version to be released, but it is good to have
+target versions for this list of features so that certain long-pending activities
+get more priority.
+
+- Better support for classdef. (LEAD?)
+  - Matlab-compatible classdef behavior.
+  - (Needs to be split up into smaller activities.)
+  - Target: Octave 10.
+
+- HDF5 compatibility with Matlab: (LEAD?)
+  - Deprecate Octave's native savefile formats in favor of Matlab-compatible HDF5.
+  - Decide how to handle backwards compatibility with older savefiles.
+  - Needs h5read/h5write as well as v7.3 MAT-file load/save support.
+  - Influenced by classdef decision above.
+  - Note: Examine Nelson's implementation.
+  - Target: Octave 10.
+
+- String class "foo" as distinct from array of characters 'foo'. (LEAD?)
+  - See https://octave.discourse.group/t/implementation-of-a-string-class/1089
+  - Depends on HDF5.
+  - Note: Examine Nelson's implementation.
+  - Target: Octave 10.
+
+- Dictionaries (aka associative arrays / hashmaps).  (LEAD? GUILLAUME?)
+  - See https://octave.discourse.group/t/adding-hashmaps-to-octave/3306
+  - Depends on HDF5 and string.
+  - Target: Octave 10.
+
+- Release bytecode interpreter.  (PETTER, JWE)
+  - First question: When Octave is released with the bytecode interpreter,
+    will it *replace* the tree-walker or will it sit alongside it? Once that
+    question is answered and agreed upon, these activities follow.
+  - Behavior compatibility with tree-walking interpreter.
+  - Code clarity and documentation.
+  - Style check.
+  - Performance experiments.
+  - Target: Octave 10
+
+- New command window widget.  (LEAD?)
+  - In Octave 9, this widget is available but experimental. It can be invoked
+    with the runtime argument `--experimental-terminal-widget`. To make it
+    production quality (i.e., not experimental), the following features and
+    more need to be added:
+    - readline-like command line editing: recall history with up/down arrow keys
+    - capture output written to stdout/stderr
+    - a pager to enable `more on` to work
+    - search the contents of the command window
+    - clear the command window for `clc`
+  - Background: https://wiki.octave.org/GUI_terminal_widget
+  - Discussion: https://octave.discourse.group/t/new-command-window-widget/501
+  - Target: Octave 11
+
+- Graph theory routines (ARUN)
+  - These need a full overhaul and in some cases ground-up implementation.
+  - Matlab switched to graph objects some versions ago, as opposed to the
+    traditional approach (pre-2016) of directly manipulating adjacency matrices
+    and edge lists.
+  - Octave needs to implement / import many classical graph functions
+    (e.g. all-pairs shortest paths, transitive closure, betweenness centrality, etc).
+    These are not difficult to write, but have mostly been written by end users
+    for their own work, so the first effort is to converge on a usable function API.
+  - Possible dependency on HDF5 if graph classes are written as classdefs,
+    so graph objects will not be saved until then, but the rest of the
+    development can start and proceed.
+  - Target: Octave 10-11, potential GSoC project for 2024.
+
+- Argument blocks implementation. (LEAD?)
+  - Some work has already been done, but needs to be completed.
+  - Target: Octave 11.
+
+- Assess OpenGL role and improvements.  (RIK?)
+  - May possibly need a paid consultant.
+  - Target: Octave 11
+
+- Replace GLPK with more performant solver for LP / MILP. (ARUN)
+  - Candidate: HiGHS.
+  - More generally, provide a usable API for optimization routines so that
+    users can drop in their own favorite solver. The idea is that the user
+    should be able to switch backend solvers with just a simple change
+    like changing this:
+    `linprog (... , "solver", "glpk")`
+    to this:
+    `linprog (... , "solver", "highs")`
+    without changing any other user-written code. Can this sort of thing
+    be done properly so that new solvers are easy to add to Octave by their
+    respective authors?
+  - Target: Octave 11
--- a/etc/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/etc/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -14,6 +14,7 @@
   %reldir%/NEWS.7.md \
   %reldir%/NEWS.8.md \
   %reldir%/NEWS.9.md \
+  %reldir%/NEWS.10.md \
   %reldir%/gdbinit
 
 %canon_reldir%_EXTRA_DIST += \
--- a/examples/code/fortrandemo.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/examples/code/fortrandemo.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -15,7 +15,7 @@
 
   NDArray a = args(0).array_value ();
 
-  double *av = a.fortran_vec ();
+  double *av = a.rwdata ();
   octave_idx_type na = a.numel ();
 
   OCTAVE_LOCAL_BUFFER (char, ctmp, 128);
--- a/libgui/graphics/BaseControl.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/BaseControl.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -74,7 +74,7 @@
       QString qss = QString (":enabled { background: %1 none;\n"
                                         "color: %2; }")
                     .arg(bcol.name ()).arg (fcol.name ());
-      w->setStyleSheet(qss);
+      w->setStyleSheet (qss);
       return;
     }
   else if (props.style_is ("radiobutton")
@@ -97,7 +97,7 @@
       QString qss = QString (":enabled { background: %1 none;\n"
                                         "color: %2; }")
                     .arg(bcol.name ()).arg (fcol.name ());
-      w->setStyleSheet(qss);
+      w->setStyleSheet (qss);
       return;
     }
   else
--- a/libgui/graphics/ButtonGroup.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/ButtonGroup.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -179,7 +179,7 @@
     frame->hide ();
 
   connect (m_buttongroup,
-           QOverload<QAbstractButton *>::of (&QButtonGroup::buttonClicked),
+           qOverload<QAbstractButton *> (&QButtonGroup::buttonClicked),
            this, &ButtonGroup::buttonClicked);
 }
 
--- a/libgui/graphics/Canvas.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Canvas.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -902,7 +902,7 @@
                   props.prepend (figObj.get_handle ().as_octave_value ());
 
                   emit interpreter_event
-                    ([=] (octave::interpreter& interp)
+                    ([this, props] (octave::interpreter& interp)
                      {
                        // INTERPRETER THREAD
 
@@ -946,7 +946,7 @@
           if (childObj.isa ("axes"))
             {
 #if defined (HAVE_QWHEELEVENT_POSITION)
-              QPoint pos = event->position().toPoint ();
+              QPoint pos = event->position ().toPoint ();
 #else
               QPoint pos = event->pos ();
 #endif
@@ -976,7 +976,7 @@
 
               if (zoom_enabled (figObj))
                 {
-                  if (event->angleDelta().y () > 0)
+                  if (event->angleDelta ().y () > 0)
                     newMouseMode = ZoomInMode;
                   else
                     newMouseMode = ZoomOutMode;
@@ -1018,7 +1018,7 @@
               {
                 axes::properties& ap = Utils::properties<axes> (axesObj);
 
-                double factor = (event->angleDelta().y () > 0 ? 0.1 : -0.1);
+                double factor = (event->angleDelta ().y () > 0 ? 0.1 : -0.1);
 
                 if (event->modifiers () == Qt::NoModifier
                     && mode != "horizontal")
--- a/libgui/graphics/Container.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Container.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,11 +69,11 @@
           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),
-                   this, QOverload<const octave::fcn_callback&>::of (&Container::interpreter_event));
+          connect (m_canvas, qOverload<const octave::fcn_callback&> (&Canvas::interpreter_event),
+                   this, qOverload<const octave::fcn_callback&> (&Container::interpreter_event));
 
-          connect (m_canvas, QOverload<const octave::meth_callback&>::of (&Canvas::interpreter_event),
-                   this, QOverload<const octave::meth_callback&>::of (&Container::interpreter_event));
+          connect (m_canvas, qOverload<const octave::meth_callback&> (&Canvas::interpreter_event),
+                   this, qOverload<const octave::meth_callback&> (&Container::interpreter_event));
 
           connect (m_canvas,
                    SIGNAL (gh_callback_event (const graphics_handle&,
--- a/libgui/graphics/Figure.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Figure.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -122,11 +122,11 @@
   m_container = new Container (win, interp);
   win->setCentralWidget (m_container);
 
-  connect (m_container, QOverload<const octave::fcn_callback&>::of (&Container::interpreter_event),
-           this, QOverload<const octave::fcn_callback&>::of (&Figure::interpreter_event));
+  connect (m_container, qOverload<const octave::fcn_callback&> (&Container::interpreter_event),
+           this, qOverload<const octave::fcn_callback&> (&Figure::interpreter_event));
 
-  connect (m_container, QOverload<const octave::meth_callback&>::of (&Container::interpreter_event),
-           this, QOverload<const octave::meth_callback&>::of (&Figure::interpreter_event));
+  connect (m_container, qOverload<const octave::meth_callback&> (&Container::interpreter_event),
+           this, qOverload<const octave::meth_callback&> (&Figure::interpreter_event));
 
   figure::properties& fp = properties<figure> ();
 
@@ -262,7 +262,7 @@
   if (! m_resizable)
     {
       win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred);
-      win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+      win->setFixedSize (QSize (QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
     }
 
   // Unlock window if it is maximized or full-screen
@@ -275,7 +275,7 @@
   if (! m_resizable)
     {
       win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
-      win->setFixedSize(win->size ());
+      win->setFixedSize (win->size ());
     }
 }
 
@@ -422,13 +422,13 @@
       if (fp.is_resize ())
         {
           win->setSizePolicy (QSizePolicy::Preferred, QSizePolicy::Preferred);
-          win->setFixedSize (QSize( QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
+          win->setFixedSize (QSize (QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
           m_resizable = true;
         }
       else
         {
           win->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed);
-          win->setFixedSize(win->size ());
+          win->setFixedSize (win->size ());
           m_resizable = false;
         }
       break;
@@ -544,7 +544,7 @@
         if (canvas)
           canvas->setCursor (mouseMode (), fp.get_pointer (),
                              m_pointer_cdata,
-                             fp.get_pointershapehotspot ().matrix_value());
+                             fp.get_pointershapehotspot ().matrix_value ());
       }
       break;
 
@@ -750,8 +750,7 @@
               break;
 
             case QEvent::ChildAdded:
-              if (dynamic_cast<QChildEvent *> (xevent)->child
-                  ()->isWidgetType())
+              if (dynamic_cast<QChildEvent *> (xevent)->child ()->isWidgetType())
                 {
                   octave::autolock guard (gh_mgr.graphics_lock ());
                   update (figure::properties::ID_TOOLBAR);
@@ -761,8 +760,7 @@
               break;
 
             case QEvent::ChildRemoved:
-              if (dynamic_cast<QChildEvent *> (xevent)->child
-                  ()->isWidgetType())
+              if (dynamic_cast<QChildEvent *> (xevent)->child ()->isWidgetType())
                 {
                   octave::autolock guard (gh_mgr.graphics_lock ());
                   update (figure::properties::ID_TOOLBAR);
--- a/libgui/graphics/FigureWindow.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/FigureWindow.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -35,7 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 FigureWindow::FigureWindow (QWidget *xparent)
-: FigureWindowBase (xparent)
+  : FigureWindowBase (xparent)
 {
   // set icon from application resources
   setWindowIcon (QIcon (global_icon_paths.at (ICON_THEME_OCTAVE)));
@@ -51,10 +51,11 @@
   return nullptr;
 }
 
-void FigureWindow::showEvent (QShowEvent *ev)
+void
+FigureWindow::showEvent (QShowEvent *ev)
 {
   QMainWindow::showEvent (ev);
-  emit figureWindowShown();
+  emit figureWindowShown ();
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/graphics/FigureWindow.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/FigureWindow.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,10 +45,10 @@
   QMenu * createPopupMenu ();
 
 protected:
-  void showEvent(QShowEvent *ev);
+  void showEvent (QShowEvent *ev);
 
 signals:
-  void figureWindowShown();
+  void figureWindowShown ();
 
 };
 
--- a/libgui/graphics/GLCanvas.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/GLCanvas.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,7 +69,7 @@
     {
       begin_rendering ();
 
-      unwind_action reset_current ([=] () { end_rendering (); });
+      unwind_action reset_current ([this] () { end_rendering (); });
 
       graphics_object fig = go.get_ancestor ("figure");
       double dpr = fig.get ("__device_pixel_ratio__").double_value ();
@@ -94,7 +94,7 @@
 
       begin_rendering ();
 
-      unwind_action reset_current ([=] () { end_rendering (); });
+      unwind_action reset_current ([this] () { 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
@@ -108,7 +108,7 @@
 
           fbo.bind ();
 
-          unwind_action release_fbo ([&] () { fbo.release (); });
+          unwind_action release_fbo ([&fbo] () { fbo.release (); });
 
           m_renderer.set_viewport (pos(2), pos(3));
           m_renderer.set_device_pixel_ratio (dpr);
@@ -137,7 +137,7 @@
     {
       begin_rendering ();
 
-      unwind_action reset_current ([=] () { end_rendering (); });
+      unwind_action reset_current ([this] () { end_rendering (); });
 
       graphics_object fig (go.get_ancestor ("figure"));
 
@@ -159,7 +159,7 @@
 
           fbo.bind ();
 
-          unwind_action release_fbo ([&] () { fbo.release (); });
+          unwind_action release_fbo ([&fbo] () { fbo.release (); });
 
           octave::gl2ps_print (m_glfcns, fig, file_cmd.toStdString (),
                                term.toStdString ());
@@ -174,7 +174,7 @@
     {
       begin_rendering ();
 
-      unwind_action reset_current ([=] () { end_rendering (); });
+      unwind_action reset_current ([this] () { end_rendering (); });
 
       octave::opengl_selector s (m_glfcns);
 
@@ -201,7 +201,7 @@
 
   begin_rendering ();
 
-  unwind_action reset_current ([=] () { end_rendering (); });
+  unwind_action reset_current ([this] () { end_rendering (); });
 
   m_renderer.draw_zoom_box (width (), height (),
                             p1.x (), p1.y (), p2.x (), p2.y (),
@@ -348,7 +348,7 @@
   catch (octave::execution_exception& ee)
     {
       emit interpreter_event
-        ([=] ()
+        ([ee] ()
         {
           // INTERPRETER THREAD
           throw ee;
--- a/libgui/graphics/GenericEventNotify.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/GenericEventNotify.h	Fri Apr 12 15:10:26 2024 +0200
@@ -66,9 +66,8 @@
   virtual void eventNotifyAfter (QObject *obj, QEvent *evt) = 0;
 };
 
-inline
-bool GenericEventNotifySender::notifyReceiversBefore (QObject *obj,
-                                                      QEvent *evt)
+inline bool
+GenericEventNotifySender::notifyReceiversBefore (QObject *obj, QEvent *evt)
 {
   for (auto *r : m_receivers)
     if (r->eventNotifyBefore (obj, evt))
@@ -77,9 +76,8 @@
   return false;
 }
 
-inline
-void GenericEventNotifySender::notifyReceiversAfter (QObject *obj,
-                                                     QEvent *evt)
+inline void
+GenericEventNotifySender::notifyReceiversAfter (QObject *obj, QEvent *evt)
 {
   for (auto *r : m_receivers)
     r->eventNotifyAfter (obj, evt);
--- a/libgui/graphics/KeyMap.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/KeyMap.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -250,7 +250,8 @@
     return keyMapper;
   }
 
-  std::string qKeyToKeyString (int key)
+  std::string
+  qKeyToKeyString (int key)
   {
     static const QMap<int, std::string> keyMapper = makeKeyMapper ();
 
--- a/libgui/graphics/Object.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Object.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -189,7 +189,8 @@
 Object::beingDeleted ()
 { }
 
-void Object::objectDestroyed (QObject *obj)
+void
+Object::objectDestroyed (QObject *obj)
 {
   if (obj && obj == m_qobject)
     m_qobject = nullptr;
--- a/libgui/graphics/ObjectProxy.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/ObjectProxy.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 ObjectProxy::ObjectProxy (Object *obj)
-: QObject (), m_object (nullptr)
+  : QObject (), m_object (nullptr)
 {
   init (obj);
 }
--- a/libgui/graphics/PopupMenuControl.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/PopupMenuControl.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -64,14 +64,15 @@
 
   update (uicontrol::properties::ID_VALUE);
 
-  connect (box, QOverload<int>::of (&QComboBox::activated),
+  connect (box, qOverload<int> (&QComboBox::activated),
            this, &PopupMenuControl::currentIndexChanged);
 }
 
 PopupMenuControl::~PopupMenuControl ()
 { }
 
-void PopupMenuControl::update (int pId)
+void
+PopupMenuControl::update (int pId)
 {
   uicontrol::properties& up = properties<uicontrol> ();
   QComboBox *box = qWidget<QComboBox> ();
--- a/libgui/graphics/QtHandlesUtils.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/QtHandlesUtils.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -85,7 +85,8 @@
     return v;
   }
 
-  Cell toCellString (const QStringList& l)
+  Cell
+  toCellString (const QStringList& l)
   {
     QStringList tmp = l;
 
@@ -159,7 +160,7 @@
   toRgb (const QColor& c)
   {
     Matrix rgb (1, 3);
-    double *rgbData = rgb.fortran_vec ();
+    double *rgbData = rgb.rwdata ();
 
 #if HAVE_QCOLOR_FLOAT_TYPE
     float tmp[3];
@@ -284,7 +285,7 @@
   QImage
   makeImageFromCData (const octave_value& v, int width, int height)
   {
-    dim_vector dv (v.dims ());
+    const dim_vector& dv = v.dims ();
 
     if (dv.ndims () == 3 && dv(2) == 3)
       {
@@ -384,7 +385,7 @@
 #if defined (Q_OS_MAC)
       modList.push_back ("command");
 #else
-    modList.push_back ("control");
+      modList.push_back ("control");
 #endif
     if (mods & Qt::AltModifier)
       modList.push_back ("alt");
@@ -405,7 +406,7 @@
 
     // We assume a standard mouse with 15 degree steps and Qt returns
     // 1/8 of a degree.
-    int ydelta = -(event->angleDelta().y ());
+    int ydelta = -(event->angleDelta ().y ());
 
     retval.setfield ("VerticalScrollCount", octave_value (ydelta / 120));
 
--- a/libgui/graphics/Table.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Table.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -61,7 +61,8 @@
 
 #define AUTO_HEIGHT (tp.get_fontsize () * 2 - 1)
 
-static QSize realQSizeForTable (QTableWidget *t)
+static QSize
+realQSizeForTable (QTableWidget *t)
 {
   int w = t->verticalHeader ()->width () + 4;
   for (int i = 0; i < t->columnCount (); i++)
@@ -329,8 +330,8 @@
 #undef FORMAT_UINT_VALUE
 #undef FORMAT_INT_VALUE
 
-static QTableWidgetItem * itemFor (octave_value val, std::string format = "",
-                                   bool enabled = false)
+static QTableWidgetItem *
+itemFor (octave_value val, std::string format = "", bool enabled = false)
 {
   QTableWidgetItem *retval = new QTableWidgetItem ();
   std::pair<Qt::AlignmentFlag, QString> flag_and_text =
--- a/libgui/graphics/Table.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/Table.h	Fri Apr 12 15:10:26 2024 +0200
@@ -80,7 +80,7 @@
   bool m_blockUpdates;
   bool m_keyPressHandlerDefined;
   bool m_keyReleaseHandlerDefined;
-  QWidget * checkBoxForLogical(octave_value cal, bool enabled);
+  QWidget * checkBoxForLogical (octave_value cal, bool enabled);
   void updateData (int row, int col, octave_value value, std::string format,
                    bool enabled);
   void updateData (int row, int col);
--- a/libgui/graphics/ToolBarButton.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/ToolBarButton.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -153,7 +153,8 @@
 }
 
 template <typename T>
-QIcon ToolBarButton<T>::get_icon (const std::string& name)
+QIcon
+ToolBarButton<T>::get_icon (const std::string& name)
 {
   return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + QString::fromStdString (name) + ".png");
 }
--- a/libgui/graphics/annotation-dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/annotation-dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -124,7 +124,7 @@
   // set props to the values of the gui
   m_props = octave_value_list ();
 
-  Matrix position(1, 4);
+  Matrix position (1, 4);
   position(0) = m_ui->sb_x->value ();
   position(1) = m_ui->sb_y->value ();
   position(2) = m_ui->sb_width->value ();
@@ -133,7 +133,7 @@
 
   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"));
+                       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.
@@ -153,11 +153,11 @@
 
   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_ui->cb_font_bold->isChecked () ? "bold" : "normal"));
   m_props.append (ovl ("fontangle",
-                     m_ui->cb_font_italic->isChecked () ? "italic" : "normal"));
+                       m_ui->cb_font_italic->isChecked () ? "italic" : "normal"));
   m_props.append (ovl ("color", octave::Utils::toRgb (m_ui->btn_color->palette ().
-                     color (QPalette::Button))));
+                       color (QPalette::Button))));
 
   // FIXME: only "none" linestyle is selectable, change the code bellow
   //        once more linestyles are added in the UI.
--- a/libgui/graphics/gl-select.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/gl-select.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -227,7 +227,7 @@
   octave_idx_type nr = props.get_cdata ().rows ();
   double y_pix_size = (nr == 1 ? 1 : (yd(1) - yd(0)) / (nr - 1));
 
-  ColumnVector p1(3, 0.0), p2(3, 0.0), p3(3, 0.0), p4(3, 0.0);
+  ColumnVector p1 (3, 0.0), p2 (3, 0.0), p3 (3, 0.0), p4 (3, 0.0);
   p1(0) = xd(0) - x_pix_size/2;
   p1(1) = yd(0) - y_pix_size/2;
 
--- a/libgui/graphics/gl-select.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/gl-select.h	Fri Apr 12 15:10:26 2024 +0200
@@ -61,7 +61,7 @@
 
   virtual void setup_opengl_transformation (const axes::properties& props);
 
-  virtual void init_marker (const std::string& m, double m_size, float width);
+  virtual void init_marker (const std::string& m, double size, float width);
 
   virtual Matrix render_text (const std::string& txt,
                               double x, double y, double z,
--- a/libgui/graphics/qt-graphics-toolkit.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/graphics/qt-graphics-toolkit.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -459,47 +459,52 @@
     }
 }
 
-void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
-                                             const std::string& nm)
+void
+qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
+                                        const std::string& nm)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
   gh_mgr.post_callback (h, nm);
 }
 
-void qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
-                                             const std::string& nm,
-                                             const octave_value& data)
+void
+qt_graphics_toolkit::gh_callback_event (const graphics_handle& h,
+                                        const std::string& nm,
+                                        const octave_value& data)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
   gh_mgr.post_callback (h, nm, data);
 }
 
-void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
-                                        const std::string& nm,
-                                        const octave_value& value)
+void
+qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
+                                   const std::string& nm,
+                                   const octave_value& value)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
   gh_mgr.post_set (h, nm, value);
 }
 
-void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
-                                        const std::string& nm,
-                                        const octave_value& value,
-                                        bool notify_toolkit)
+void
+qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
+                                   const std::string& nm,
+                                   const octave_value& value,
+                                   bool notify_toolkit)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
   gh_mgr.post_set (h, nm, value, notify_toolkit);
 }
 
-void qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
-                                        const std::string& nm,
-                                        const octave_value& value,
-                                        bool notify_toolkit,
-                                        bool redraw_figure)
+void
+qt_graphics_toolkit::gh_set_event (const graphics_handle& h,
+                                   const std::string& nm,
+                                   const octave_value& value,
+                                   bool notify_toolkit,
+                                   bool redraw_figure)
 {
   gh_manager& gh_mgr = m_interpreter.get_gh_manager ();
 
--- a/libgui/qterminal/libqterminal/QTerminal.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/QTerminal.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -107,6 +107,7 @@
 
     if (has_selected_text)
       {
+        // Find first word in selected text, trim everything else
         QRegularExpression expr {"(\\w+)"};
         QRegularExpressionMatch match = expr.match (selected_text);
 
@@ -115,15 +116,24 @@
             QString expr_found = match.captured (1);
 
             m_edit_selected_action->setVisible (true);
-            m_edit_selected_action->setText (tr ("Edit %1").arg (expr_found));
+            m_edit_selected_action->setText (tr ("Edit \"%1\"").arg (expr_found));
             m_edit_selected_action->setData (expr_found);
 
             m_help_selected_action->setVisible (true);
-            m_help_selected_action->setText (tr ("Help on %1").arg (expr_found));
+            m_help_selected_action->setText (tr ("Help on \"%1\"").arg (expr_found));
             m_help_selected_action->setData (expr_found);
+          }
+
+        // Grab all of selected text, but trim leading non-word characters
+        // and trailing whitespace
+        expr.setPattern ("(\\w.*)\\s*$");
+        match = expr.match (selected_text);
+        if (match.hasMatch ())
+          {
+            QString expr_found = match.captured (1);
 
             m_doc_selected_action->setVisible (true);
-            m_doc_selected_action->setText (tr ("Documentation on %1")
+            m_doc_selected_action->setText (tr ("Documentation on \"%1\"")
                                             .arg (expr_found));
             m_doc_selected_action->setData (expr_found);
           }
@@ -195,7 +205,7 @@
   std::string expr = m_doc_selected_action->data ().toString ().toStdString ();
 
   emit interpreter_event
-    ([=] (octave::interpreter& interp)
+    ([expr] (octave::interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -204,7 +214,7 @@
 }
 
 void
-QTerminal::notice_settings (void)
+QTerminal::notice_settings ()
 {
   octave::gui_settings settings;
 
@@ -278,7 +288,7 @@
 }
 
 void
-QTerminal::construct (void)
+QTerminal::construct ()
 {
   octave::gui_settings settings;
 
--- a/libgui/qterminal/libqterminal/QTerminal.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/QTerminal.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,7 +45,7 @@
 
   static QTerminal * create (QWidget *xparent);
 
-  virtual ~QTerminal (void) = default;
+  virtual ~QTerminal () = default;
 
   virtual void setTerminalFont (const QFont& font) = 0;
 
@@ -57,8 +57,8 @@
 
   virtual void has_extra_interrupt (bool extra) = 0;
 
-  virtual QList<QAction*> get_hotspot_actions (const QPoint&)
-  { return QList<QAction*> (); }
+  virtual QList<QAction *> get_hotspot_actions (const QPoint&)
+  { return QList<QAction *> (); }
 
   enum CursorType
   {
@@ -91,7 +91,7 @@
 
   void report_status_message (const QString&);
 
-  void interrupt_signal (void);
+  void interrupt_signal ();
 
   void edit_mfile_request (const QString&, int);
 
@@ -105,36 +105,36 @@
 
   void set_screen_size_signal (int, int);
 
-  void clear_command_window_request (void);
+  void clear_command_window_request ();
 
   void interpreter_event (const octave::fcn_callback& fcn);
   void interpreter_event (const octave::meth_callback& meth);
 
 public slots:
 
-  virtual void copyClipboard (void) = 0;
+  virtual void copyClipboard () = 0;
 
-  virtual void pasteClipboard (void) = 0;
+  virtual void pasteClipboard () = 0;
 
-  virtual void selectAll (void) = 0;
+  virtual void selectAll () = 0;
 
   virtual void handleCustomContextMenuRequested (const QPoint& at);
 
-  void notice_settings (void);
+  void notice_settings ();
 
-  virtual void init_terminal_size (void) { }
+  virtual void init_terminal_size () { }
 
-  void terminal_interrupt (void) { emit interrupt_signal (); }
+  void terminal_interrupt () { emit interrupt_signal (); }
 
-  void run_selection (void);
+  void run_selection ();
 
-  void edit_file (void);
+  void edit_file ();
 
-  void edit_selected (void);
+  void edit_selected ();
 
-  void help_on_expression (void);
+  void help_on_expression ();
 
-  void doc_on_expression (void);
+  void doc_on_expression ();
 
   virtual void handle_visibility_changed (bool) { };
 
--- a/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,7 @@
     connect(m_terminalView, SIGNAL(customContextMenuRequested(QPoint)),
             this, SLOT(handleCustomContextMenuRequested(QPoint)));
 
-    connect (m_terminalView, SIGNAL (interrupt_signal (void)),
+    connect (m_terminalView, SIGNAL (interrupt_signal ()),
              this, SLOT (terminal_interrupt ()));
 
 #ifdef Q_OS_MAC
--- a/libgui/qterminal/libqterminal/unix/TerminalView.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/unix/TerminalView.h	Fri Apr 12 15:10:26 2024 +0200
@@ -466,7 +466,7 @@
 
 signals:
 
-    void interrupt_signal (void);
+    void interrupt_signal ();
 
     /**
      * Emitted when the user presses a key whilst the terminal widget has focus.
--- a/libgui/qterminal/libqterminal/win32/QTerminalColors.cpp	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/win32/QTerminalColors.cpp	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-QConsoleColors::QConsoleColors (void)
+QConsoleColors::QConsoleColors ()
     : QMap<int, QColor> ()
 {
   (*this)[0]  = Qt::white;
--- a/libgui/qterminal/libqterminal/win32/QTerminalColors.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/win32/QTerminalColors.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,7 +31,7 @@
 class QConsoleColors : public QMap<int, QColor>
 {
 public:
-  QConsoleColors (void);
+  QConsoleColors ();
 };
 
 //////////////////////////////////////////////////////////////////////////////
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp	Fri Apr 12 15:10:26 2024 +0200
@@ -77,7 +77,7 @@
 {
 public:
   QConsoleView (QWinTerminalImpl *parent = 0) : QWidget (parent), q (parent) { }
-  ~QConsoleView (void) { }
+  ~QConsoleView () { }
 
 protected:
   void paintEvent (QPaintEvent *event) { q->viewPaintEvent (this, event); }
@@ -95,7 +95,7 @@
   QConsoleThread (QWinTerminalImpl *console) : QThread (console), q (console) { }
 
 protected:
-  void run (void)
+  void run ()
     { q->start (); }
 
 private:
@@ -180,21 +180,21 @@
     };
 
   QConsolePrivate (QWinTerminalImpl *parent, const QString& cmd = QString ());
-  ~QConsolePrivate (void);
+  ~QConsolePrivate ();
 
   void updateConsoleSize (bool sync = false, bool allow_smaller_width = false);
-  void syncConsoleParameters (void);
+  void syncConsoleParameters ();
   void grabConsoleBuffer (CHAR_INFO* buf = 0);
-  void updateHorizontalScrollBar (void);
-  void updateVerticalScrollBar (void);
+  void updateHorizontalScrollBar ();
+  void updateVerticalScrollBar ();
   void setHorizontalScrollValue (int value);
   void setVerticalScrollValue (int value);
   void updateConsoleView (bool grab = true);
-  void monitorConsole (void);
-  void startCommand (void);
+  void monitorConsole ();
+  void startCommand ();
   void sendConsoleText (const QString& s);
-  QRect cursorRect (void);
-  QRect boundingRect (void);
+  QRect cursorRect ();
+  QRect boundingRect ();
   void selectAll ();
   void selectWord (const QPoint& cellPos);
   void selectLine (const QPoint& cellPos);
@@ -206,14 +206,14 @@
                         const char *devName);
 
   QPoint posToCell (const QPoint& pt);
-  QString getSelection (void);
-  void updateSelection (void);
-  void clearSelection (void);
+  QString getSelection ();
+  void updateSelection ();
+  void clearSelection ();
 
-  QColor backgroundColor (void) const;
-  QColor foregroundColor (void) const;
-  QColor selectionColor (void) const;
-  QColor cursorColor (void) const;
+  QColor backgroundColor () const;
+  QColor foregroundColor () const;
+  QColor selectionColor () const;
+  QColor cursorColor () const;
 
   void setBackgroundColor (const QColor& color);
   void setForegroundColor (const QColor& color);
@@ -435,8 +435,8 @@
   QObject::connect (m_verticalScrollBar, SIGNAL (valueChanged (int)),
                     q, SLOT (verticalScrollValueChanged (int)));
 
-  QObject::connect (m_consoleWatcher, SIGNAL (timeout (void)),
-                    q, SLOT (monitorConsole (void)));
+  QObject::connect (m_consoleWatcher, SIGNAL (timeout ()),
+                    q, SLOT (monitorConsole ()));
 
   m_consoleWatcher->start ();
 
@@ -445,15 +445,15 @@
   else
     {
       m_consoleThread = new QConsoleThread (q);
-      QObject::connect (m_consoleThread, SIGNAL (finished (void)),
-                        q, SIGNAL (terminated (void)));
+      QObject::connect (m_consoleThread, SIGNAL (finished ()),
+                        q, SIGNAL (terminated ()));
       m_consoleThread->start ();
     }
 }
 
 //////////////////////////////////////////////////////////////////////////////
 
-QConsolePrivate::~QConsolePrivate (void)
+QConsolePrivate::~QConsolePrivate ()
 {
   if (m_consoleThread && m_consoleThread->isRunning () && m_process)
     {
@@ -505,7 +505,7 @@
                                / m_charSize.height ()));
 }
 
-QString QConsolePrivate::getSelection (void)
+QString QConsolePrivate::getSelection ()
 {
   QString selection;
 
@@ -566,7 +566,7 @@
   return selection;
 }
 
-void QConsolePrivate::updateSelection (void)
+void QConsolePrivate::updateSelection ()
 {
   QPoint begin = m_beginSelection;
   QPoint end = m_endSelection;
@@ -579,29 +579,29 @@
   m_consoleView->update ();
 }
 
-void QConsolePrivate::clearSelection (void)
+void QConsolePrivate::clearSelection ()
 {
   m_beginSelection = m_endSelection = QPoint ();
 
   m_consoleView->update ();
 }
 
-QColor QConsolePrivate::backgroundColor (void) const
+QColor QConsolePrivate::backgroundColor () const
 {
   return m_colors[0];
 }
 
-QColor QConsolePrivate::foregroundColor (void) const
+QColor QConsolePrivate::foregroundColor () const
 {
   return m_colors[7];
 }
 
-QColor QConsolePrivate::selectionColor (void) const
+QColor QConsolePrivate::selectionColor () const
 {
   return m_selectionColor;
 }
 
-QColor QConsolePrivate::cursorColor (void) const
+QColor QConsolePrivate::cursorColor () const
 {
   return m_cursorColor.isValid () ? m_cursorColor : foregroundColor ();
 }
@@ -1088,7 +1088,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QConsolePrivate::syncConsoleParameters (void)
+void QConsolePrivate::syncConsoleParameters ()
 {
   CONSOLE_SCREEN_BUFFER_INFO sbi;
   HANDLE hStdOut = m_stdOut;
@@ -1154,7 +1154,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QConsolePrivate::updateHorizontalScrollBar (void)
+void QConsolePrivate::updateHorizontalScrollBar ()
 {
   m_horizontalScrollBar->setMinimum (0);
   if (m_bufferSize.width () > m_consoleRect.width ())
@@ -1172,7 +1172,7 @@
        m_horizontalScrollBar->pageStep ());
 }
 
-void QConsolePrivate::updateVerticalScrollBar (void)
+void QConsolePrivate::updateVerticalScrollBar ()
 {
   m_verticalScrollBar->setMinimum (0);
   if (m_bufferSize.height () > m_consoleRect.height ())
@@ -1266,7 +1266,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QConsolePrivate::monitorConsole (void)
+void QConsolePrivate::monitorConsole ()
 {
   CONSOLE_SCREEN_BUFFER_INFO sbi;
   HANDLE hStdOut = GetStdHandle (STD_OUTPUT_HANDLE);
@@ -1362,7 +1362,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QConsolePrivate::startCommand (void)
+void QConsolePrivate::startCommand ()
 {
   QString cmd = m_command;
 
@@ -1469,7 +1469,7 @@
 }
 
 QRect
-QConsolePrivate::cursorRect (void)
+QConsolePrivate::cursorRect ()
 {
   // The actual character width might be fractional (with non-integer scaling -
   // high DPI).  But m_charSize.width () is integer.
@@ -1492,7 +1492,7 @@
 }
 
 QRect
-QConsolePrivate::boundingRect (void)
+QConsolePrivate::boundingRect ()
 {
   // This is slightly larger than cursorRect to make sure the entirety of a
   // character is redrawn.
@@ -1524,7 +1524,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-QWinTerminalImpl::~QWinTerminalImpl (void)
+QWinTerminalImpl::~QWinTerminalImpl ()
 {
   delete d;
 }
@@ -1632,7 +1632,7 @@
   d->drawText (p, cx1, cy1, cx2, cy2, ch);
 }
 
-void QWinTerminalImpl::blinkCursorEvent (void)
+void QWinTerminalImpl::blinkCursorEvent ()
 {
   if (d->m_hasBlinkingCursor)
     d->m_cursorBlinking = ! d->m_cursorBlinking;
@@ -1665,7 +1665,7 @@
 
 // Reset width of console buffer and terminal window to be the same.
 
-void QWinTerminalImpl::init_terminal_size (void)
+void QWinTerminalImpl::init_terminal_size ()
 {
   d->updateConsoleSize (true, true);
 }
@@ -1697,12 +1697,12 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QWinTerminalImpl::monitorConsole (void)
+void QWinTerminalImpl::monitorConsole ()
 {
   d->monitorConsole ();
 }
 
-void QWinTerminalImpl::updateSelection (void)
+void QWinTerminalImpl::updateSelection ()
 {
   d->updateSelection ();
 }
@@ -1761,7 +1761,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QWinTerminalImpl::start (void)
+void QWinTerminalImpl::start ()
 {
   d->startCommand ();
 }
@@ -1862,7 +1862,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QWinTerminalImpl::pasteClipboard (void)
+void QWinTerminalImpl::pasteClipboard ()
 {
   if(!hasFocus()) return;
 
@@ -1882,7 +1882,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-void QWinTerminalImpl::selectAll (void)
+void QWinTerminalImpl::selectAll ()
 {
   if(!hasFocus()) return;
 
--- a/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/qterminal/libqterminal/win32/QWinTerminalImpl.h	Fri Apr 12 15:10:26 2024 +0200
@@ -50,7 +50,7 @@
 
 public:
   QWinTerminalImpl (QWidget *parent);
-  ~QWinTerminalImpl (void);
+  ~QWinTerminalImpl ();
 
   void setTerminalFont (const QFont& font);
   void setSize (int columns, int lines);
@@ -68,14 +68,14 @@
   void has_extra_interrupt (bool);
 
 public slots:
-  void copyClipboard (void);
-  void pasteClipboard (void);
-  void selectAll (void);
-  void blinkCursorEvent (void);
-  void init_terminal_size (void);
+  void copyClipboard ();
+  void pasteClipboard ();
+  void selectAll ();
+  void blinkCursorEvent ();
+  void init_terminal_size ();
 
 signals:
-  void terminated (void);
+  void terminated ();
   void titleChanged (const QString&);
 
 protected:
@@ -87,7 +87,7 @@
   void focusInEvent (QFocusEvent *);
   void focusOutEvent (QFocusEvent *);
   void keyPressEvent (QKeyEvent *);
-  virtual void start (void);
+  virtual void start ();
   void mouseMoveEvent (QMouseEvent *event);
   void mousePressEvent (QMouseEvent *event);
   void mouseReleaseEvent (QMouseEvent *event);
@@ -102,9 +102,9 @@
 private slots:
   void horizontalScrollValueChanged (int value);
   void verticalScrollValueChanged (int value);
-  void monitorConsole (void);
-  void updateSelection (void);
-  void tripleClickTimeout (void);
+  void monitorConsole ();
+  void updateSelection ();
+  void tripleClickTimeout ();
 
 private:
   QConsolePrivate *d;
--- a/libgui/src/color-picker.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/color-picker.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -36,7 +36,7 @@
 
 // Constructor with initial color as parameter
 color_picker::color_picker (QColor old_color, QWidget *p)
-: QPushButton (p)
+  : QPushButton (p)
 {
   m_color = old_color;
   setFlat (true);
@@ -46,7 +46,8 @@
 }
 
 // Slot for button clicked: select a new color using QColorDialog
-void color_picker::select_color ()
+void
+color_picker::select_color ()
 {
   QColor new_color = QColorDialog::getColor (m_color);
 
@@ -58,14 +59,16 @@
 }
 
 // Set the color of the button
-void color_picker::set_color (QColor new_color)
+void
+color_picker::set_color (QColor new_color)
 {
   m_color = new_color;
   update_button ();
 }
 
 // Draw the button with the actual color (using a stylesheet)
-void color_picker::update_button ()
+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/command-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/command-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -90,17 +90,18 @@
   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 fcn_callback&> (&console::interpreter_event),
+           this, qOverload<const fcn_callback&> (&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));
+  connect (m_console, qOverload<const meth_callback&> (&console::interpreter_event),
+           this, qOverload<const meth_callback&> (&command_widget::interpreter_event));
 
   insert_interpreter_output ("\n\n    Welcome to Octave\n\n");
 
 }
 
-void command_widget::init_command_prompt ()
+void
+command_widget::init_command_prompt ()
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
@@ -109,7 +110,7 @@
   QPointer<command_widget> this_cw (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_cw] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -129,22 +130,26 @@
      });
 }
 
-void command_widget::update_prompt (const QString& prompt)
+void
+command_widget::update_prompt (const QString& prompt)
 {
   m_prompt = prompt;
 }
 
-QString command_widget::prompt ()
+QString
+command_widget::prompt ()
 {
   return m_prompt;
 }
 
-void command_widget::insert_interpreter_output (const QString& msg)
+void
+command_widget::insert_interpreter_output (const QString& msg)
 {
   m_console->append (msg);
 }
 
-void command_widget::process_input_line (const QString& input_line)
+void
+command_widget::process_input_line (const QString& input_line)
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
@@ -153,7 +158,7 @@
   QPointer<command_widget> this_cw (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_cw, input_line] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -180,7 +185,8 @@
 
 }
 
-void command_widget::notice_settings ()
+void
+command_widget::notice_settings ()
 {
   gui_settings settings;
 
@@ -201,7 +207,7 @@
   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.
@@ -231,7 +237,8 @@
 }
 
 // Prepare a new command line with the current prompt
-void console::new_command_line (const QString& command)
+void
+console::new_command_line (const QString& command)
 {
   if (! text (lines () -1).isEmpty ())
     append ("\n");
@@ -239,19 +246,20 @@
   append_string (m_command_widget->prompt ());
 
   int line, index;
-  getCursorPosition (&line,&index);
+  getCursorPosition (&line, &index);
   m_command_position = positionFromLineIndex (line, index);
 
   append_string (command);
 }
 
 // Accept the current command line (or block)
-void console::accept_command_line ()
+void
+console::accept_command_line ()
 {
   QString input_line = text (lines () - 1);
 
   if (input_line.startsWith (m_command_widget->prompt ()))
-    input_line.remove(0, m_command_widget->prompt ().length ());
+    input_line.remove (0, m_command_widget->prompt ().length ());
 
   input_line = input_line.trimmed ();
 
@@ -264,7 +272,8 @@
 }
 
 // Execute a command
-void console::execute_command (const QString& command)
+void
+console::execute_command (const QString& command)
 {
   if (command.trimmed ().isEmpty ())
     return;
@@ -274,7 +283,8 @@
 }
 
 // Append a string and update the curdor püosition
-void console::append_string (const QString& string)
+void
+console::append_string (const QString& string)
 {
   setReadOnly (false);
   append (string);
@@ -286,7 +296,8 @@
 }
 
 // Cursor position changed: Are we in the command line or not?
-void console::cursor_position_changed (int line, int col)
+void
+console::cursor_position_changed (int line, int col)
 {
   m_cursor_position = positionFromLineIndex (line, col);
   if (m_cursor_position < m_command_position)
@@ -308,7 +319,8 @@
 
 // User attempted to type on read only mode: move cursor at end and allow
 // editing
-void console::move_cursor_to_end ()
+void
+console::move_cursor_to_end ()
 {
   if ((! m_last_key_string.isEmpty ()) && (m_last_key_string.at (0).isPrint ()))
     {
@@ -319,13 +331,15 @@
 
 // Text has changed: is cursor still in "writable" area?
 // This signal seems to be emitted before cursor position changed.
-void console::text_changed ()
+void
+console::text_changed ()
 {
   m_text_changed = true;
 }
 
 // Re-implement key event
-void console::keyPressEvent (QKeyEvent *e)
+void
+console::keyPressEvent (QKeyEvent *e)
 {
   if (e->key () == Qt::Key_Return)
     // On "return", accept the current command line
@@ -334,7 +348,7 @@
     {
       // Otherwise, store text process the expected event
       m_last_key_string = e->text ();
-      QsciScintilla::keyPressEvent(e);
+      QsciScintilla::keyPressEvent (e);
     }
 }
 
--- a/libgui/src/community-news.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/community-news.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -53,8 +53,9 @@
   construct (base_url, page, serial);
 }
 
-void community_news::construct (const QString& base_url, const QString& page,
-                                int serial)
+void
+community_news::construct (const QString& base_url, const QString& page,
+                           int serial)
 {
   m_browser = new QTextBrowser (this);
 
@@ -114,12 +115,14 @@
   worker_thread->start ();
 }
 
-void community_news::set_news (const QString& news)
+void
+community_news::set_news (const QString& news)
 {
   m_browser->setHtml (news);
 }
 
-void community_news::display ()
+void
+community_news::display ()
 {
   if (! isVisible ())
     show ();
--- a/libgui/src/dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -65,19 +65,21 @@
            this, &QUIWidgetCreator::handle_create_filedialog);
 }
 
-QString QUIWidgetCreator::rm_amp (const QString& text)
+QString
+QUIWidgetCreator::rm_amp (const QString& text)
 {
   QString text_wo_amp = text;
   text_wo_amp.replace (QRegularExpression {"&(\\w)"}, "\\1");
   return text_wo_amp;
 }
 
-QString QUIWidgetCreator::message_dialog (const QString& message,
-                                          const QString& title,
-                                          const QString& icon,
-                                          const QStringList& buttons,
-                                          const QString& defbutton,
-                                          const QStringList& role)
+QString
+QUIWidgetCreator::message_dialog (const QString& message,
+                                  const QString& title,
+                                  const QString& icon,
+                                  const QStringList& buttons,
+                                  const QString& defbutton,
+                                  const QStringList& role)
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -130,11 +132,12 @@
 // Create a message dialog with specified string, buttons and
 // decorative text.
 
-QStringList QUIWidgetCreator::input_dialog (const QStringList& prompt,
-                                            const QString& title,
-                                            const QFloatList& nr,
-                                            const QFloatList& nc,
-                                            const QStringList& defaults)
+QStringList
+QUIWidgetCreator::input_dialog (const QStringList& prompt,
+                                const QString& title,
+                                const QFloatList& nr,
+                                const QFloatList& nc,
+                                const QStringList& defaults)
 {
   if (prompt.isEmpty ())
     return QStringList ();
@@ -150,11 +153,12 @@
   return m_string_list;
 };
 
-QStringList QUIWidgetCreator::file_dialog (const QStringList& filters,
-                                           const QString& title,
-                                           const QString& filename,
-                                           const QString& dirname,
-                                           const QString& multimode)
+QStringList
+QUIWidgetCreator::file_dialog (const QStringList& filters,
+                               const QString& title,
+                               const QString& filename,
+                               const QString& dirname,
+                               const QString& multimode)
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -173,12 +177,13 @@
   return retval;
 }
 
-void QUIWidgetCreator::handle_create_dialog (const QString& message,
-                                             const QString& title,
-                                             const QString& icon,
-                                             const QStringList& button,
-                                             const QString& defbutton,
-                                             const QStringList& role)
+void
+QUIWidgetCreator::handle_create_dialog (const QString& message,
+                                        const QString& title,
+                                        const QString& icon,
+                                        const QStringList& button,
+                                        const QString& defbutton,
+                                        const QStringList& role)
 {
   MessageDialog *message_dialog
     = new MessageDialog (message, title, icon, button, defbutton, role);
@@ -190,7 +195,8 @@
   message_dialog->show ();
 }
 
-void QUIWidgetCreator::dialog_button_clicked (QAbstractButton *button)
+void
+QUIWidgetCreator::dialog_button_clicked (QAbstractButton *button)
 {
   // button is NULL when dialog is closed.
   if (button)
@@ -222,14 +228,15 @@
 // Create a list dialog with specified list, initially selected, mode,
 // view size and decorative text.
 
-void QUIWidgetCreator::handle_create_listview (const QStringList& list,
-                                               const QString& mode,
-                                               int wd, int ht,
-                                               const QIntList& initial,
-                                               const QString& name,
-                                               const QStringList& prompt,
-                                               const QString& ok_string,
-                                               const QString& cancel_string)
+void
+QUIWidgetCreator::handle_create_listview (const QStringList& list,
+    const QString& mode,
+    int wd, int ht,
+    const QIntList& initial,
+    const QString& name,
+    const QStringList& prompt,
+    const QString& ok_string,
+    const QString& cancel_string)
 {
   ListDialog *list_dialog
     = new ListDialog (list, mode, wd, ht, initial,
@@ -242,8 +249,9 @@
   list_dialog->show ();
 }
 
-void QUIWidgetCreator::list_select_finished (const QIntList& selected,
-                                             int button_pressed)
+void
+QUIWidgetCreator::list_select_finished (const QIntList& selected,
+                                        int button_pressed)
 {
   // Store the value so that builtin functions can retrieve.
 
@@ -257,11 +265,12 @@
 // Create an input dialog with specified prompts and defaults, title
 // and row/column size specifications.
 
-void QUIWidgetCreator::handle_create_inputlayout (const QStringList& prompt,
-                                                  const QString& title,
-                                                  const QFloatList& nr,
-                                                  const QFloatList& nc,
-                                                  const QStringList& defaults)
+void
+QUIWidgetCreator::handle_create_inputlayout (const QStringList& prompt,
+    const QString& title,
+    const QFloatList& nr,
+    const QFloatList& nc,
+    const QStringList& defaults)
 {
   InputDialog *input_dialog
     = new InputDialog (prompt, title, nr, nc, defaults);
@@ -273,8 +282,9 @@
   input_dialog->show ();
 }
 
-void QUIWidgetCreator::input_finished (const QStringList& input,
-                                       int button_pressed)
+void
+QUIWidgetCreator::input_finished (const QStringList& input,
+                                  int button_pressed)
 {
   // Store the value so that builtin functions can retrieve.
 
@@ -285,11 +295,12 @@
   wake_all ();
 }
 
-void QUIWidgetCreator::handle_create_filedialog (const QStringList& filters,
-                                                 const QString& title,
-                                                 const QString& filename,
-                                                 const QString& dirname,
-                                                 const QString& multimode)
+void
+QUIWidgetCreator::handle_create_filedialog (const QStringList& filters,
+    const QString& title,
+    const QString& filename,
+    const QString& dirname,
+    const QString& multimode)
 {
   FileDialog *file_dialog
     = new FileDialog (filters, title, filename, dirname, multimode);
@@ -301,9 +312,10 @@
   file_dialog->show ();
 }
 
-void QUIWidgetCreator::filedialog_finished (const QStringList& files,
-                                            const QString& path,
-                                            int filterindex)
+void
+QUIWidgetCreator::filedialog_finished (const QStringList& files,
+                                       const QString& path,
+                                       int filterindex)
 {
   // Store the value so that builtin functions can retrieve.
 
@@ -406,7 +418,7 @@
     view->setSelectionMode (QAbstractItemView::NoSelection);
 
   m_selector = view->selectionModel ();
-  for (int i = 0; i < initial.count(); i++)
+  for (int i = 0; i < initial.count (); i++)
     {
       QModelIndex idx = m_model->index (initial.value (i) - 1, 0,
                                         QModelIndex ());
@@ -475,7 +487,8 @@
            this, &ListDialog::item_double_clicked);
 }
 
-void ListDialog::buttonOk_clicked ()
+void
+ListDialog::buttonOk_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -491,7 +504,8 @@
   done (QDialog::Accepted);
 }
 
-void ListDialog::buttonCancel_clicked ()
+void
+ListDialog::buttonCancel_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -503,12 +517,14 @@
   done (QDialog::Rejected);
 }
 
-void ListDialog::reject ()
+void
+ListDialog::reject ()
 {
   buttonCancel_clicked ();
 }
 
-void ListDialog::item_double_clicked (const QModelIndex&)
+void
+ListDialog::item_double_clicked (const QModelIndex&)
 {
   buttonOk_clicked ();
 }
@@ -580,7 +596,8 @@
            this, &InputDialog::buttonCancel_clicked);
 }
 
-void InputDialog::buttonOk_clicked ()
+void
+InputDialog::buttonOk_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -592,7 +609,8 @@
   done (QDialog::Accepted);
 }
 
-void InputDialog::buttonCancel_clicked ()
+void
+InputDialog::buttonCancel_clicked ()
 {
   // Store information about what button was pressed so that builtin
   // functions can retrieve.
@@ -602,7 +620,8 @@
   done (QDialog::Rejected);
 }
 
-void InputDialog::reject ()
+void
+InputDialog::reject ()
 {
   buttonCancel_clicked ();
 }
@@ -616,7 +635,7 @@
 
   // This should be set before any other dialog properties
   if (! settings.bool_value (global_use_native_dialogs))
-    setOption(QFileDialog::DontUseNativeDialog);
+    setOption (QFileDialog::DontUseNativeDialog);
 
   // Create a NonModal message.
   setWindowModality (Qt::NonModal);
@@ -659,13 +678,15 @@
   connect (this, &FileDialog::rejected, this, &FileDialog::rejectSelection);
 }
 
-void FileDialog::rejectSelection ()
+void
+FileDialog::rejectSelection ()
 {
   QStringList empty;
   emit finish_input (empty, "", 0);
 }
 
-void FileDialog::acceptSelection ()
+void
+FileDialog::acceptSelection ()
 {
   QStringList string_result;
   QString path;
--- a/libgui/src/documentation-bookmarks.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/documentation-bookmarks.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -66,10 +66,10 @@
   m_tree->setContextMenuPolicy (Qt::CustomContextMenu);
   m_tree->setSelectionMode (QAbstractItemView::ExtendedSelection);
   m_tree->setSortingEnabled (false);
-  m_tree->setDragEnabled(true);
-  m_tree->viewport()->setAcceptDrops(true);
-  m_tree->setDropIndicatorShown(true);
-  m_tree->setDragDropMode(QAbstractItemView::InternalMove);
+  m_tree->setDragEnabled (true);
+  m_tree->viewport ()->setAcceptDrops (true);
+  m_tree->setDropIndicatorShown (true);
+  m_tree->setDragDropMode (QAbstractItemView::InternalMove);
   m_tree->setColumnCount (1);
   m_tree->setHeaderHidden (true);
   m_tree->setEditTriggers (QAbstractItemView::EditKeyPressed
@@ -81,11 +81,11 @@
            this, &documentation_bookmarks::handle_double_click);
 
   // Define the icons for the tree view
-  m_icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirClosedIcon),
-                         QIcon::Normal, QIcon::Off);
-  m_icon_folder.addPixmap (style ()->standardPixmap(QStyle::SP_DirOpenIcon),
-                         QIcon::Normal, QIcon::On);
-  m_icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon));
+  m_icon_folder.addPixmap (style ()->standardPixmap (QStyle::SP_DirClosedIcon),
+                           QIcon::Normal, QIcon::Off);
+  m_icon_folder.addPixmap (style ()->standardPixmap (QStyle::SP_DirOpenIcon),
+                           QIcon::Normal, QIcon::On);
+  m_icon_bookmark.addPixmap (style ()->standardPixmap (QStyle::SP_FileIcon));
 
   // Setup and read the bookmarkfile
   QFileInfo f (settings.fileName ());
@@ -154,7 +154,8 @@
 }
 
 // Slot for adding the current page as a bookmark
-void documentation_bookmarks::add_bookmark ()
+void
+documentation_bookmarks::add_bookmark ()
 {
   QUrl url = m_browser->historyUrl (0);
 
@@ -179,17 +180,18 @@
 }
 
 // Function for actually adding a bookmark to the tree
-void documentation_bookmarks::add_bookmark (const QString& title,
-                                            const QString& url,
-                                            QTreeWidgetItem* item)
+void
+documentation_bookmarks::add_bookmark (const QString& title,
+                                       const QString& url,
+                                       QTreeWidgetItem *item)
 {
   // Create new bookmark
   QTreeWidgetItem *new_item = new QTreeWidgetItem (QStringList (title));
   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);
+                      | Qt::ItemIsEditable
+                      | Qt::ItemIsDragEnabled);
   new_item->setIcon (0, m_icon_bookmark);
 
   // Insert as top level or child item
@@ -202,7 +204,8 @@
 }
 
 // Slot for adding a folder from the context menu
-void documentation_bookmarks::add_folder (bool)
+void
+documentation_bookmarks::add_folder (bool)
 {
   QTreeWidgetItem *parent_item = nullptr;
 
@@ -225,14 +228,15 @@
 }
 
 // Function for actually adding a folder to the tree
-QTreeWidgetItem* documentation_bookmarks::add_folder (const QString& folder,
-                                          QTreeWidgetItem *item, bool expanded)
+QTreeWidgetItem *
+documentation_bookmarks::add_folder (const QString& folder,
+                                     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);
+  new_folder->setFlags (new_folder->flags () | Qt::ItemIsEditable
+                        | Qt::ItemIsDragEnabled
+                        | Qt::ItemIsDropEnabled);
   new_folder->setChildIndicatorPolicy (QTreeWidgetItem::DontShowIndicatorWhenChildless);
   new_folder->setIcon (0, m_icon_folder);
   new_folder->setExpanded (expanded);
@@ -246,7 +250,8 @@
   return new_folder;
 }
 
-void documentation_bookmarks::filter_bookmarks (const QString& pattern)
+void
+documentation_bookmarks::filter_bookmarks (const QString& pattern)
 {
   QTreeWidgetItemIterator it (m_tree);
 
@@ -271,7 +276,8 @@
     }
 }
 
-void documentation_bookmarks::filter_activate (bool state)
+void
+documentation_bookmarks::filter_activate (bool state)
 {
   m_filter->setEnabled (state);
 
@@ -282,7 +288,8 @@
   filter_bookmarks (pattern);
 }
 
-void documentation_bookmarks::update_filter_history ()
+void
+documentation_bookmarks::update_filter_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -294,7 +301,8 @@
   m_filter->setCurrentIndex (0);
 }
 
-void documentation_bookmarks::handle_double_click (QTreeWidgetItem *item, int)
+void
+documentation_bookmarks::handle_double_click (QTreeWidgetItem *item, int)
 {
   int tag = item->data (0, tag_role).toInt ();
 
@@ -313,7 +321,8 @@
     }
 }
 
-void documentation_bookmarks::ctx_menu (const QPoint& xpos)
+void
+documentation_bookmarks::ctx_menu (const QPoint& xpos)
 {
   QMenu menu (this);
 
@@ -331,7 +340,7 @@
     }
 
   menu.addAction (tr ("&Add Folder"), this,
-                  QOverload<bool>::of (&documentation_bookmarks::add_folder));
+                  qOverload<bool> (&documentation_bookmarks::add_folder));
 
   menu.addSeparator ();
 
@@ -345,7 +354,8 @@
   menu.exec (m_tree->mapToGlobal (xpos));
 }
 
-void documentation_bookmarks::open (bool)
+void
+documentation_bookmarks::open (bool)
 {
   QList<QTreeWidgetItem *> items = m_tree->selectedItems ();
 
@@ -353,7 +363,8 @@
     handle_double_click (items.at (0));
 }
 
-void documentation_bookmarks::edit (bool)
+void
+documentation_bookmarks::edit (bool)
 {
   QList<QTreeWidgetItem *> items = m_tree->selectedItems ();
 
@@ -361,7 +372,8 @@
     m_tree->editItem (items.at (0));
 }
 
-void documentation_bookmarks::remove (bool)
+void
+documentation_bookmarks::remove (bool)
 {
   QList<QTreeWidgetItem *> items = m_tree->selectedItems ();
 
@@ -370,13 +382,15 @@
       m_tree->takeTopLevelItem (m_tree->indexOfTopLevelItem (it));
 }
 
-void documentation_bookmarks::show_filter (bool)
+void
+documentation_bookmarks::show_filter (bool)
 {
   m_filter_shown = ! m_filter_shown;
   m_filter_widget->setVisible (m_filter_shown);
 }
 
-void documentation_bookmarks::save_settings ()
+void
+documentation_bookmarks::save_settings ()
 {
   // Write the bookmarks to the xbel-file
   write_bookmarks ();
@@ -395,7 +409,8 @@
   settings.sync ();
 }
 
-void documentation_bookmarks::write_bookmarks ()
+void
+documentation_bookmarks::write_bookmarks ()
 {
   if (! m_xbel_file.open (QFile::WriteOnly | QFile::Text))
     {
@@ -403,7 +418,7 @@
                             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.errorString ()));
       return;
     }
 
@@ -415,17 +430,18 @@
   xml_writer.writeStartElement (dc_xbel_name_format);
   xml_writer.writeAttribute (dc_xbel_attr_version, dc_xbel_value_version);
 
-  for (int i = 0; i < m_tree->topLevelItemCount(); i++)
+  for (int i = 0; i < m_tree->topLevelItemCount (); i++)
     write_tree_item (&xml_writer, m_tree->topLevelItem (i));
 
-  xml_writer.writeEndDocument();
+  xml_writer.writeEndDocument ();
 
   m_xbel_file.flush ();
   m_xbel_file.close ();
 }
 
-void documentation_bookmarks::write_tree_item (QXmlStreamWriter* xml_writer,
-                                               const QTreeWidgetItem *item)
+void
+documentation_bookmarks::write_tree_item (QXmlStreamWriter *xml_writer,
+    const QTreeWidgetItem *item)
 {
   switch (item->data (0, tag_role).toInt ())
     {
@@ -448,7 +464,8 @@
     }
 }
 
-QString documentation_bookmarks::read_bookmarks ()
+QString
+documentation_bookmarks::read_bookmarks ()
 {
   QString error_message;
 
@@ -457,7 +474,7 @@
     {
       error_message = tr ("Unable to read file %1:\n%2.")
                           .arg (m_xbel_file.fileName ())
-                          .arg (m_xbel_file.errorString());
+                          .arg (m_xbel_file.errorString ());
       return error_message;
     }
 
@@ -471,7 +488,7 @@
       return error_message;
     }
 
-  if (xml_reader.name() != dc_xbel_name_format
+  if (xml_reader.name () != dc_xbel_name_format
       || xml_reader.attributes ().value (dc_xbel_attr_version) != dc_xbel_value_version)
     {
       error_message = tr ("The file\n"
@@ -497,14 +514,15 @@
   return error_message;
 }
 
-void documentation_bookmarks::read_next_item (QXmlStreamReader *xml_reader,
-                                              item_tag tag, QTreeWidgetItem *item)
+void
+documentation_bookmarks::read_next_item (QXmlStreamReader *xml_reader,
+    item_tag tag, QTreeWidgetItem *item)
 {
   QString title (tr ("Unknown title"));
   if (tag == folder_tag)
     {
       // Next item is a folder, which might also have children
-      bool expanded = (xml_reader->attributes().value (dc_xbel_attr_folded) == dc_xbel_value_no);
+      bool expanded = (xml_reader->attributes ().value (dc_xbel_attr_folded) == dc_xbel_value_no);
 
       QTreeWidgetItem *new_folder = add_folder (title, item, expanded);
 
@@ -514,7 +532,7 @@
         {
           if (xml_reader->name () == dc_xbel_name_title)
             {
-              title = xml_reader->readElementText();
+              title = xml_reader->readElementText ();
               new_folder->setText (0, title);
             }
           else if (xml_reader->name () == dc_xbel_name_folder)
@@ -528,11 +546,11 @@
   else if (tag == bookmark_tag)
     {
       // Next item is a bookmark, without children
-      QString url = xml_reader->attributes().value (dc_xbel_attr_href).toString ();
+      QString url = xml_reader->attributes ().value (dc_xbel_attr_href).toString ();
       while (xml_reader->readNextStartElement ())
         {
-          if (xml_reader->name() == dc_xbel_name_title)
-            title = xml_reader->readElementText();
+          if (xml_reader->name () == dc_xbel_name_title)
+            title = xml_reader->readElementText ();
           else
             xml_reader->skipCurrentElement ();
         }
--- a/libgui/src/documentation-dock-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/documentation-dock-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,33 +46,39 @@
     make_window ();
 }
 
-void documentation_dock_widget::notice_settings ()
+void
+documentation_dock_widget::notice_settings ()
 {
   m_docs->notice_settings ();
 }
 
-void documentation_dock_widget::save_settings ()
+void
+documentation_dock_widget::save_settings ()
 {
   m_docs->save_settings ();
   octave_dock_widget::save_settings ();
 }
 
-void documentation_dock_widget::copyClipboard ()
+void
+documentation_dock_widget::copyClipboard ()
 {
   m_docs->copyClipboard ();
 }
 
-void documentation_dock_widget::pasteClipboard ()
+void
+documentation_dock_widget::pasteClipboard ()
 {
   m_docs->pasteClipboard ();
 }
 
-void documentation_dock_widget::selectAll ()
+void
+documentation_dock_widget::selectAll ()
 {
   m_docs->selectAll ();
 }
 
-void documentation_dock_widget::showDoc (const QString& name)
+void
+documentation_dock_widget::showDoc (const QString& name)
 {
   // show the doc pane without focus for carrying on typing in the console
   if (! isVisible ())
@@ -83,12 +89,14 @@
   m_docs->load_ref (name);
 }
 
-void documentation_dock_widget::registerDoc (const QString& name)
+void
+documentation_dock_widget::registerDoc (const QString& name)
 {
   m_docs->registerDoc (name);
 }
 
-void documentation_dock_widget::unregisterDoc (const QString& name)
+void
+documentation_dock_widget::unregisterDoc (const QString& name)
 {
   m_docs->unregisterDoc (name);
 }
--- a/libgui/src/documentation.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/documentation.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -128,7 +128,7 @@
   if (copy_ok)
     m_help_engine->setCollectionFile (m_collection);
   else
-#ifdef ENABLE_DOCS
+#if defined (ENABLE_DOCS)
     // FIXME: Perhaps a better way to do this would be to keep a count
     // in the GUI preferences file.  After issuing this warning 3 times
     // it would be disabled.  The count would need to be reset when a new
@@ -144,9 +144,9 @@
   connect(m_help_engine, SIGNAL(setupFinished ()),
           m_help_engine->searchEngine (), SLOT(reindexDocumentation ()));
 
-  if (! m_help_engine->setupData())
+  if (! m_help_engine->setupData ())
     {
-#ifdef ENABLE_DOCS
+#if defined (ENABLE_DOCS)
       QMessageBox::warning (this, tr ("Octave Documentation"),
                             tr ("Could not setup the data required for the\n"
                                 "documentation viewer. Maybe the Qt SQlite\n"
@@ -184,7 +184,7 @@
   QLabel *find_label = new QLabel (tr ("Find:"), find_footer);
   m_find_line_edit = new QLineEdit (find_footer);
   connect (m_find_line_edit, &QLineEdit::returnPressed,
-           this, [=] () { find (); });
+           this, [this] () { find (); });
   connect (m_find_line_edit, &QLineEdit::textEdited,
            this, &documentation::find_forward_from_anchor);
   QToolButton *forward_button = new QToolButton (find_footer);
@@ -195,7 +195,7 @@
 
   forward_button->setIcon (settings.icon ("go-down"));
   connect (forward_button, &QToolButton::pressed,
-           this, [=] () { find (); });
+           this, [this] () { find (); });
   QToolButton *backward_button = new QToolButton (find_footer);
   backward_button->setText (tr ("Search backward"));
   backward_button->setToolTip (tr ("Search backward"));
@@ -220,7 +220,7 @@
 
   m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
   connect (m_findnext_shortcut, &QShortcut::activated,
-           this, [=] () { find (); });
+           this, [this] () { find (); });
   m_findprev_shortcut->setContext (Qt::WidgetWithChildrenShortcut);
   connect (m_findprev_shortcut, &QShortcut::activated,
            this, &documentation::find_backward);
@@ -246,8 +246,7 @@
 
       connect (m_help_engine->contentWidget (),
                &QHelpContentWidget::linkActivated,
-               m_doc_browser, [=] (const QUrl& url) {
-                 m_doc_browser->handle_index_clicked (url); });
+               m_doc_browser, [this] (const QUrl& url) { m_doc_browser->handle_index_clicked (url); });
 
       // Index
       QHelpIndexWidget *index = m_help_engine->indexWidget ();
@@ -283,8 +282,7 @@
 #if defined (HAVE_NEW_QHELPINDEXWIDGET_API)
       connect (m_help_engine->indexWidget (),
                &QHelpIndexWidget::documentActivated,
-               this, [=] (const QHelpLink &link) {
-                 m_doc_browser->handle_index_clicked (link.url); });
+               this, [this] (const QHelpLink &link) { m_doc_browser->handle_index_clicked (link.url); });
 #else
       connect (m_help_engine->indexWidget (),
                &QHelpIndexWidget::linkActivated,
@@ -302,7 +300,7 @@
       navi->addTab (m_bookmarks, tr ("Bookmarks"));
 
       connect (m_action_bookmark, &QAction::triggered,
-               m_bookmarks, [=] () { m_bookmarks->add_bookmark (); });
+               m_bookmarks, [this] () { m_bookmarks->add_bookmark (); });
 
       // Search
       QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
@@ -353,13 +351,14 @@
           sys::recursive_rmdir (file_name);
         }
 
-      file.remove();
+      file.remove ();
     }
 }
 
-QAction * documentation::add_action (const QIcon& icon, const QString& text,
-                                     const char *member, QWidget *receiver,
-                                     QToolBar *tool_bar)
+QAction *
+documentation::add_action (const QIcon& icon, const QString& text,
+                           const char *member, QWidget *receiver,
+                           QToolBar *tool_bar)
 {
   QAction *a;
   QWidget *r = this;
@@ -380,7 +379,8 @@
   return a;
 }
 
-void documentation::construct_tool_bar ()
+void
+documentation::construct_tool_bar ()
 {
   // Home, Previous, Next
   gui_settings settings;
@@ -401,7 +401,7 @@
   popdown_button_prev_pages->setPopupMode (QToolButton::InstantPopup);
   popdown_button_prev_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
   popdown_button_prev_pages->setCheckable (false);
-  popdown_button_prev_pages->setArrowType(Qt::DownArrow);
+  popdown_button_prev_pages->setArrowType (Qt::DownArrow);
   m_tool_bar->addWidget (popdown_button_prev_pages);
 
   m_action_go_next
@@ -415,7 +415,7 @@
   popdown_button_next_pages->setMenu (m_next_pages_menu);
   popdown_button_next_pages->setPopupMode (QToolButton::InstantPopup);
   popdown_button_next_pages->setToolButtonStyle (Qt::ToolButtonTextOnly);
-  popdown_button_next_pages->setArrowType(Qt::DownArrow);
+  popdown_button_next_pages->setArrowType (Qt::DownArrow);
   m_tool_bar->addWidget (popdown_button_next_pages);
 
   connect (m_doc_browser, &documentation_browser::backwardAvailable,
@@ -470,7 +470,8 @@
                   tr ("Bookmark current page"), nullptr, nullptr, m_tool_bar);
 }
 
-void documentation::global_search ()
+void
+documentation::global_search ()
 {
   if (! m_help_engine)
     return;
@@ -508,12 +509,14 @@
   m_help_engine->searchEngine ()->search (queries);
 }
 
-void documentation::global_search_started ()
+void
+documentation::global_search_started ()
 {
-  qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+  qApp->setOverrideCursor (QCursor (Qt::WaitCursor));
 }
 
-void documentation::global_search_finished (int)
+void
+documentation::global_search_finished (int)
 {
   if (! m_help_engine)
     return;
@@ -583,10 +586,11 @@
       m_internal_search = QString ();
     }
 
-  qApp->restoreOverrideCursor();
+  qApp->restoreOverrideCursor ();
 }
 
-void documentation::handle_search_result_clicked (const QUrl& url)
+void
+documentation::handle_search_result_clicked (const QUrl& url)
 {
   // Open url with matching text
   m_doc_browser->handle_index_clicked (url);
@@ -612,7 +616,8 @@
     }
 }
 
-void documentation::select_all_occurrences (const QString& text)
+void
+documentation::select_all_occurrences (const QString& text)
 {
   // Get highlight background and text color
   QPalette pal = QApplication::palette ();
@@ -640,7 +645,8 @@
   m_doc_browser->moveCursor (QTextCursor::Start);
 }
 
-void documentation::notice_settings ()
+void
+documentation::notice_settings ()
 {
   gui_settings settings;
 
@@ -673,7 +679,8 @@
   m_doc_browser->notice_settings ();
 }
 
-void documentation::save_settings ()
+void
+documentation::save_settings ()
 {
   gui_settings settings;
 
@@ -681,19 +688,23 @@
   m_bookmarks->save_settings ();
 }
 
-void documentation::copyClipboard ()
+void
+documentation::copyClipboard ()
 {
   if (m_doc_browser->hasFocus ())
     {
-      m_doc_browser->copy();
+      m_doc_browser->copy ();
     }
 }
 
-void documentation::pasteClipboard () { }
+void
+documentation::pasteClipboard () { }
 
-void documentation::selectAll () { }
+void
+documentation::selectAll () { }
 
-void documentation::load_index ()
+void
+documentation::load_index ()
 {
   m_indexed = true;
 
@@ -707,7 +718,8 @@
   m_help_engine->contentWidget ()->expandToDepth (0);
 }
 
-void documentation::load_ref (const QString& ref_name)
+void
+documentation::load_ref (const QString& ref_name)
 {
   if (! m_help_engine || ref_name.isEmpty ())
     return;
@@ -727,19 +739,19 @@
 
   QTabWidget *navi = static_cast<QTabWidget *> (widget (0));
 
-  if (found_links.count() > 0)
+  if (found_links.count () > 0)
     {
       // First search in the function index
 #if defined (HAVE_QHELPENGINE_DOCUMENTSFORIDENTIFIER)
-      QUrl first_url = found_links.constFirst().url;
+      QUrl first_url = found_links.constFirst ().url;
 #else
-      QUrl first_url = found_links.constBegin().value ();
+      QUrl first_url = found_links.constBegin ().value ();
 #endif
 
       m_doc_browser->setSource (first_url);
 
       // Switch to function index tab
-      m_help_engine->indexWidget()->filterIndices (ref_name);
+      m_help_engine->indexWidget ()->filterIndices (ref_name);
       QWidget *index_tab
         = navi->findChild<QWidget *> ("documentation_tab_index");
       navi->setCurrentWidget (index_tab);
@@ -756,7 +768,7 @@
 #else
       QList<QHelpSearchQuery> query;
       query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,
-                                 QStringList (QString("\"") + ref_name + QString("\"")));
+                                 QStringList (QString ("\"") + ref_name + QString ("\"")));
 #endif
       m_internal_search = ref_name;
       search_engine->search (query);
@@ -773,7 +785,8 @@
     }
 }
 
-void documentation::activate_find ()
+void
+documentation::activate_find ()
 {
   if (m_find_line_edit->parentWidget ()->isVisible ())
     {
@@ -788,19 +801,21 @@
     }
 }
 
-void documentation::filter_update (const QString& expression)
+void
+documentation::filter_update (const QString& expression)
 {
   if (! m_help_engine)
     return;
 
   QString wildcard;
-  if (expression.contains (QLatin1Char('*')))
+  if (expression.contains (QLatin1Char ('*')))
     wildcard = expression;
 
-  m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
+  m_help_engine->indexWidget ()->filterIndices (expression, wildcard);
 }
 
-void documentation::filter_update_history ()
+void
+documentation::filter_update_history ()
 {
   QString text = m_filter->currentText ();   // get current text
   int index = m_filter->findText (text);     // and its actual index
@@ -812,12 +827,14 @@
   m_filter->setCurrentIndex (0);
 }
 
-void documentation::find_backward ()
+void
+documentation::find_backward ()
 {
   find (true);
 }
 
-void documentation::find (bool backward)
+void
+documentation::find (bool backward)
 {
   if (! m_help_engine)
     return;
@@ -841,7 +858,8 @@
   record_anchor_position ();
 }
 
-void documentation::find_forward_from_anchor (const QString& text)
+void
+documentation::find_forward_from_anchor (const QString& text)
 {
   if (! m_help_engine)
     return;
@@ -860,7 +878,8 @@
     }
 }
 
-void documentation::record_anchor_position ()
+void
+documentation::record_anchor_position ()
 {
   if (! m_help_engine)
     return;
@@ -868,7 +887,8 @@
   m_search_anchor_position = m_doc_browser->textCursor ().position ();
 }
 
-void documentation::handle_cursor_position_change ()
+void
+documentation::handle_cursor_position_change ()
 {
   if (! m_help_engine)
     return;
@@ -877,7 +897,8 @@
     record_anchor_position ();
 }
 
-void documentation::registerDoc (const QString& qch)
+void
+documentation::registerDoc (const QString& qch)
 {
   if (m_help_engine)
     {
@@ -902,11 +923,12 @@
         }
 
       if (do_setup)
-        m_help_engine->setupData();
+        m_help_engine->setupData ();
     }
 }
 
-void documentation::unregisterDoc (const QString& qch)
+void
+documentation::unregisterDoc (const QString& qch)
 {
   if (! m_help_engine)
     return;
@@ -921,7 +943,8 @@
     }
 }
 
-void documentation::update_history_menus ()
+void
+documentation::update_history_menus ()
 {
   if (m_prev_pages_count != m_doc_browser->backwardHistoryCount ())
     {
@@ -938,7 +961,8 @@
     }
 }
 
-void documentation::update_history (int new_count, QAction **actions)
+void
+documentation::update_history (int new_count, QAction **actions)
 {
   // Which menu has to be updated?
   int prev_next = -1;
@@ -976,14 +1000,16 @@
     }
 }
 
-void documentation::open_hist_url (QAction *a)
+void
+documentation::open_hist_url (QAction *a)
 {
   m_doc_browser->setSource (a->data ().toUrl ());
 }
 
 // Utility functions
 
-QString documentation::title_and_anchor (const QString& title, const QUrl& url)
+QString
+documentation::title_and_anchor (const QString& title, const QUrl& url)
 {
   QString retval = title;
   QString u = url.toString ();
@@ -1032,12 +1058,13 @@
 {
   setOpenLinks (false);
   connect (this, &documentation_browser::anchorClicked,
-           this, [=] (const QUrl& url) { handle_index_clicked (url); });
+           this, [this] (const QUrl& url) { handle_index_clicked (url); });
 
   // 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;
 
@@ -1058,19 +1085,20 @@
                                 + sys::file_ops::dir_sep_str ());
 
       QStringList default_fonts = {"FreeMono", "FreeMonoBold",
-                                   "FreeMonoBoldOblique", "FreeMonoOblique"};
+                                   "FreeMonoBoldOblique", "FreeMonoOblique"
+                                  };
 
       for (int i = 0; i < default_fonts.size (); ++i)
         {
           QString fontpath =
-            fonts_dir + default_fonts.at(i) + QString (".otf");
+            fonts_dir + default_fonts.at (i) + QString (".otf");
           QFontDatabase::addApplicationFont (fontpath);
         }
     }
 }
 
-void documentation_browser::handle_index_clicked (const QUrl& url,
-                                                  const QString&)
+void
+documentation_browser::handle_index_clicked (const QUrl& url, const QString&)
 {
   if (url.scheme () == "qthelp")
     setSource (QUrl (url));
@@ -1078,7 +1106,8 @@
     QDesktopServices::openUrl (url);
 }
 
-void documentation_browser::notice_settings ()
+void
+documentation_browser::notice_settings ()
 {
   gui_settings settings;
 
@@ -1090,15 +1119,17 @@
     }
 }
 
-QVariant documentation_browser::loadResource (int type, const QUrl& url)
+QVariant
+documentation_browser::loadResource (int type, const QUrl& url)
 {
   if (m_help_engine && url.scheme () == "qthelp")
-    return QVariant (m_help_engine->fileData(url));
+    return QVariant (m_help_engine->fileData (url));
   else
-    return QTextBrowser::loadResource(type, url);
+    return QTextBrowser::loadResource (type, url);
 }
 
-void documentation_browser::save_settings ()
+void
+documentation_browser::save_settings ()
 {
   gui_settings settings;
 
@@ -1107,7 +1138,8 @@
   settings.sync ();
 }
 
-void documentation_browser::zoom_in ()
+void
+documentation_browser::zoom_in ()
 {
   if (m_zoom_level < max_zoom_level)
     {
@@ -1116,7 +1148,8 @@
     }
 }
 
-void documentation_browser::zoom_out ()
+void
+documentation_browser::zoom_out ()
 {
   if (m_zoom_level > min_zoom_level)
     {
@@ -1125,17 +1158,19 @@
     }
 }
 
-void documentation_browser::zoom_original ()
+void
+documentation_browser::zoom_original ()
 {
   zoomIn (- m_zoom_level);
   m_zoom_level = 0;
 }
 
-void documentation_browser::wheelEvent (QWheelEvent *we)
+void
+documentation_browser::wheelEvent (QWheelEvent *we)
 {
   if (we->modifiers () == Qt::ControlModifier)
     {
-      if (we->angleDelta().y () > 0)
+      if (we->angleDelta ().y () > 0)
         zoom_in ();
       else
         zoom_out ();
--- a/libgui/src/dw-main-window.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/dw-main-window.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -79,7 +79,8 @@
 }
 
 // Re-implementing the popup menu of the main window
-QMenu *dw_main_window::createPopupMenu ()
+QMenu *
+dw_main_window::createPopupMenu ()
 {
   QList<QAction *> new_actions = QList<QAction *> ();
   new_actions.append (m_close_action);
@@ -87,7 +88,7 @@
   new_actions.append (m_close_all_action);
 
   QMenu *menu = QMainWindow::createPopupMenu ();
-  QList<QAction *> actions = menu->actions();
+  QList<QAction *> actions = menu->actions ();
 
   if (actions.length () > 0)
     {
@@ -101,9 +102,10 @@
 }
 
 // Adding an action to the main window
-QAction * dw_main_window::add_action (QMenu *menu, const QIcon& icon,
-                                      const QString& text, const char *member,
-                                      QWidget *receiver)
+QAction *
+dw_main_window::add_action (QMenu *menu, const QIcon& icon,
+                            const QString& text, const char *member,
+                            QWidget *receiver)
 {
   QAction *a;
   QWidget *r = this;
@@ -127,7 +129,8 @@
 }
 
 // Update the settings
-void dw_main_window::notice_settings ()
+void
+dw_main_window::notice_settings ()
 {
   gui_settings settings;
 
@@ -142,7 +145,8 @@
 // Slots for handling actions
 
 // Close current widget
-void dw_main_window::request_close ()
+void
+dw_main_window::request_close ()
 {
   for (int i = 0; i < m_dw_list.length (); i++)
     {
@@ -157,7 +161,8 @@
 }
 
 // Close other widgets
-void dw_main_window::request_close_other ()
+void
+dw_main_window::request_close_other ()
 {
   for (int i = m_dw_list.length () - 1; i >= 0; i--)
     {
@@ -167,26 +172,30 @@
 }
 
 // Close all widgets
-void dw_main_window::request_close_all ()
+void
+dw_main_window::request_close_all ()
 {
   for (int i = m_dw_list.length () - 1; i >= 0; i--)
     m_dw_list.at (i)->close ();
 }
 
 // Switch to left widget
-void dw_main_window::request_switch_left ()
+void
+dw_main_window::request_switch_left ()
 {
   request_switch (-1);
 }
 
 // Switch to right widget
-void dw_main_window::request_switch_right ()
+void
+dw_main_window::request_switch_right ()
 {
   request_switch (1);
 }
 
 // Switch to left/right widget
-void dw_main_window::request_switch (int direction)
+void
+dw_main_window::request_switch (int direction)
 {
   int active = -1, next;
 
@@ -215,7 +224,8 @@
 }
 
 // Reimplemented Event
-bool dw_main_window::event (QEvent *ev)
+bool
+dw_main_window::event (QEvent *ev)
 {
   if (ev->type () == QEvent::ChildAdded
       || ev->type () == QEvent::ChildRemoved)
--- a/libgui/src/external-editor-interface.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/external-editor-interface.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -80,26 +80,30 @@
 
 // Slots for the several signals for invoking the editor
 
-void external_editor_interface::request_new_file (const QString&)
+void
+external_editor_interface::request_new_file (const QString&)
 {
   call_custom_editor ();
 }
 
-void external_editor_interface::request_open_file (const QString& file_name,
-                                                   const QString&, int line,
-                                                   bool, bool, bool,
-                                                   const QString&)
+void
+external_editor_interface::request_open_file (const QString& file_name,
+                                              const QString&, int line,
+                                              bool, bool, bool,
+                                              const QString&)
 {
   call_custom_editor (file_name, line);
 }
 
-void external_editor_interface::handle_edit_file_request (const QString& file)
+void
+external_editor_interface::handle_edit_file_request (const QString& file)
 {
   call_custom_editor (file);
 }
 
 // Get and verify the settings of the external editor program
-QString external_editor_interface::external_editor ()
+QString
+external_editor_interface::external_editor ()
 {
   gui_settings settings;
 
--- a/libgui/src/files-dock-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/files-dock-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -106,23 +106,23 @@
         return false;
       }
 
-    auto parent_dir = QDir(filePath (parent (idx)));
+    auto parent_dir = QDir (filePath (parent (idx)));
 
-    files_dock_widget *fdw = static_cast<files_dock_widget*>(parent());
+    files_dock_widget *fdw = static_cast<files_dock_widget *>(parent ());
 
-    fdw->file_remove_signal(parent_dir.filePath(old_name), parent_dir.filePath(new_name));
+    fdw->file_remove_signal (parent_dir.filePath (old_name), parent_dir.filePath (new_name));
 
     if (!parent_dir.rename (old_name, new_name))
       {
         display_rename_failed_message (old_name, new_name);
-        fdw->file_renamed_signal(false);
+        fdw->file_renamed_signal (false);
         return false;
       }
 
-    fdw->file_renamed_signal(true);
+    fdw->file_renamed_signal (true);
 
-    emit fileRenamed(parent_dir.absolutePath(), old_name, new_name);
-    revert();
+    emit fileRenamed (parent_dir.absolutePath (), old_name, new_name);
+    revert ();
 
     return true;
   }
@@ -148,7 +148,7 @@
 {
 public:
   RenameItemDelegate (QObject *parent = nullptr)
-      : QStyledItemDelegate{ parent }
+    : QStyledItemDelegate{ parent }
   {
   }
 
@@ -175,9 +175,7 @@
     // actually restrict the selection, we have to post the modification at
     // the end of the event loop.
     // QTimer allows this easily with 0 as timeout.
-    QTimer::singleShot (0, [=] () {
-      line_edit->setSelection (0, select_len);
-    });
+    QTimer::singleShot (0, [line_edit, select_len] () { line_edit->setSelection (0, select_len); });
   }
 };
 
@@ -383,7 +381,7 @@
   m_file_tree_view->setToolTip (tr ("Double-click to open file/folder, right click for alternatives"));
 
   // allow renaming directly in the tree view with
-  // m_file_tree_view->edit(index)
+  // m_file_tree_view->edit (index)
   m_file_system_model->setReadOnly (false);
   // delegate to improve rename ergonomy by pre-selecting text up to the
   // extension
@@ -395,10 +393,10 @@
   // and associate to F2 key shortcut
   m_rename_action = new QAction (tr ("Rename..."), this);
   m_rename_action->setShortcut (Qt::Key_F2);
-  m_rename_action->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+  m_rename_action->setShortcutContext (Qt::WidgetWithChildrenShortcut);
   connect (m_rename_action, &QAction::triggered, this,
            &files_dock_widget::contextmenu_rename);
-  addAction(m_rename_action);
+  addAction (m_rename_action);
 
   // get sort column and order as well as column state (order and width)
 
@@ -408,10 +406,6 @@
      // FIXME: use value<Qt::SortOrder> instead of static cast after
      //        dropping support of Qt 5.4
 
-  if (settings.contains (fb_column_state.settings_key ()))
-    m_file_tree_view->header ()->restoreState
-      (settings.value (fb_column_state.settings_key ()).toByteArray ());
-
   // Set header properties for sorting
   m_file_tree_view->header ()->setSectionsClickable (true);
   m_file_tree_view->header ()->setSectionsMovable (true);
@@ -470,9 +464,27 @@
 
   if (! p)
     make_window ();
+
+  // Initialize column order and width of the file browser. From this post,
+  // https://www.qtcentre.org/threads/26675-QTableView-saving-restoring-columns-widths
+  // this might fail if done directly in the constructor. This effect shows
+  // up in the GUI since Qt 6.6.x. As a solution, the following timer ensures
+  // that the header is restored when the event loop is idle.
+  QTimer::singleShot (0, this, SLOT(restore_header_state ()));
 }
 
-void files_dock_widget::save_settings ()
+void
+files_dock_widget::restore_header_state ()
+{
+  gui_settings settings;
+
+  if (settings.contains (fb_column_state.settings_key ()))
+    m_file_tree_view->header ()->restoreState
+      (settings.value (fb_column_state.settings_key ()).toByteArray ());
+}
+
+void
+files_dock_widget::save_settings ()
 {
   gui_settings settings;
 
@@ -498,24 +510,28 @@
     delete m_sig_mapper;
 }
 
-void files_dock_widget::item_double_clicked (const QModelIndex& index)
+void
+files_dock_widget::item_double_clicked (const QModelIndex& index)
 {
   // Retrieve the file info associated with the model index.
   QFileInfo fileInfo = m_file_system_model->fileInfo (index);
   set_current_directory (fileInfo.absoluteFilePath ());
 }
 
-void files_dock_widget::set_current_directory (const QString& dir)
+void
+files_dock_widget::set_current_directory (const QString& dir)
 {
   display_directory (dir);
 }
 
-void files_dock_widget::accept_directory_line_edit ()
+void
+files_dock_widget::accept_directory_line_edit ()
 {
   display_directory (m_current_directory->currentText ());
 }
 
-void files_dock_widget::change_directory_up ()
+void
+files_dock_widget::change_directory_up ()
 {
   QDir dir
     = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
@@ -524,7 +540,8 @@
   display_directory (dir.absolutePath ());
 }
 
-void files_dock_widget::do_sync_octave_directory ()
+void
+files_dock_widget::do_sync_octave_directory ()
 {
   QDir dir
     = QDir (m_file_system_model->filePath (m_file_tree_view->rootIndex ()));
@@ -532,20 +549,23 @@
   emit displayed_directory_changed (dir.absolutePath ());
 }
 
-void files_dock_widget::do_sync_browser_directory ()
+void
+files_dock_widget::do_sync_browser_directory ()
 {
   display_directory (m_octave_dir, false); // false: no sync of octave dir
 }
 
-void files_dock_widget::update_octave_directory (const QString& dir)
+void
+files_dock_widget::update_octave_directory (const QString& dir)
 {
   m_octave_dir = dir;
   if (m_sync_octave_dir)
     display_directory (m_octave_dir, false); // false: no sync of octave dir
 }
 
-void files_dock_widget::display_directory (const QString& dir,
-                                           bool set_octave_dir)
+void
+files_dock_widget::display_directory (const QString& dir,
+                                      bool set_octave_dir)
 {
   QFileInfo fileInfo (dir);
   if (fileInfo.exists ())
@@ -594,7 +614,8 @@
     }
 }
 
-void files_dock_widget::open_item_in_app (const QModelIndex& index)
+void
+files_dock_widget::open_item_in_app (const QModelIndex& index)
 {
   // Retrieve the file info associated with the model index.
   QFileInfo fileInfo = m_file_system_model->fileInfo (index);
@@ -604,7 +625,8 @@
   QDesktopServices::openUrl (QUrl::fromLocalFile (file));
 }
 
-void files_dock_widget::toggle_header (int col)
+void
+files_dock_widget::toggle_header (int col)
 {
   gui_settings settings;
 
@@ -629,7 +651,8 @@
     }
 }
 
-void files_dock_widget::headercontextmenu_requested (const QPoint& mpos)
+void
+files_dock_widget::headercontextmenu_requested (const QPoint& mpos)
 {
   QMenu menu (this);
 
@@ -661,7 +684,8 @@
   menu.exec (m_file_tree_view->mapToGlobal (mpos));
 }
 
-void files_dock_widget::contextmenu_requested (const QPoint& mpos)
+void
+files_dock_widget::contextmenu_requested (const QPoint& mpos)
 {
 
   QMenu menu (this);
@@ -721,7 +745,7 @@
           QMenu *add_path_menu = menu.addMenu (tr ("Add to Path"));
 
           add_path_menu->addAction (tr ("Selected Directories"),
-                                    this, [=] (bool checked) { contextmenu_add_to_path (checked); });
+                                    this, [this] (bool checked) { contextmenu_add_to_path (checked); });
           add_path_menu->addAction (tr ("Selected Directories and Subdirectories"),
                                     this, &files_dock_widget::contextmenu_add_to_path_subdirs);
 
@@ -758,7 +782,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_open (bool)
+void
+files_dock_widget::contextmenu_open (bool)
 {
 
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
@@ -772,7 +797,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_open_in_editor (bool)
+void
+files_dock_widget::contextmenu_open_in_editor (bool)
 {
 
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
@@ -786,7 +812,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_open_in_app (bool)
+void
+files_dock_widget::contextmenu_open_in_app (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -795,7 +822,8 @@
     open_item_in_app (it);
 }
 
-void files_dock_widget::contextmenu_copy_selection (bool)
+void
+files_dock_widget::contextmenu_copy_selection (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -813,7 +841,8 @@
   clipboard->setText (selection.join ("\n"));
 }
 
-void files_dock_widget::contextmenu_load (bool)
+void
+files_dock_widget::contextmenu_load (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -828,7 +857,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_run (bool)
+void
+files_dock_widget::contextmenu_run (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -842,18 +872,20 @@
     }
 }
 
-void files_dock_widget::contextmenu_rename (bool)
+void
+files_dock_widget::contextmenu_rename (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
   if (rows.size () > 0)
     {
       QModelIndex index = rows[0];
-      m_file_tree_view->edit(index);
+      m_file_tree_view->edit (index);
     }
 }
 
-void files_dock_widget::contextmenu_delete (bool)
+void
+files_dock_widget::contextmenu_delete (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -883,10 +915,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)
@@ -929,7 +961,8 @@
 
 // Get the currently selected files/dirs and return their file info
 // in a list.
-QList<QFileInfo> files_dock_widget::get_selected_items_info (bool dir)
+QList<QFileInfo>
+files_dock_widget::get_selected_items_info (bool dir)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -948,7 +981,8 @@
   return infos;
 }
 
-void files_dock_widget::contextmenu_newfile (bool)
+void
+files_dock_widget::contextmenu_newfile (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -964,7 +998,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_newdir (bool)
+void
+files_dock_widget::contextmenu_newdir (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -980,7 +1015,8 @@
     }
 }
 
-void files_dock_widget::contextmenu_setcurrentdir (bool)
+void
+files_dock_widget::contextmenu_setcurrentdir (bool)
 {
   QList<QFileInfo> infos = get_selected_items_info (true);
 
@@ -988,7 +1024,8 @@
     process_set_current_dir (infos.first ().absoluteFilePath ());
 }
 
-void files_dock_widget::contextmenu_add_to_path (bool, bool rm, bool subdirs)
+void
+files_dock_widget::contextmenu_add_to_path (bool, bool rm, bool subdirs)
 {
   QList<QFileInfo> infos = get_selected_items_info (true);
 
@@ -1001,22 +1038,26 @@
     emit modify_path_signal (dir_list, rm, subdirs);
 }
 
-void files_dock_widget::contextmenu_add_to_path_subdirs (bool)
+void
+files_dock_widget::contextmenu_add_to_path_subdirs (bool)
 {
   contextmenu_add_to_path (true, false, true);
 }
 
-void files_dock_widget::contextmenu_rm_from_path (bool)
+void
+files_dock_widget::contextmenu_rm_from_path (bool)
 {
   contextmenu_add_to_path (true, true, false);
 }
 
-void files_dock_widget::contextmenu_rm_from_path_subdirs (bool)
+void
+files_dock_widget::contextmenu_rm_from_path_subdirs (bool)
 {
   contextmenu_add_to_path (true, true, true);
 }
 
-void files_dock_widget::contextmenu_findfiles (bool)
+void
+files_dock_widget::contextmenu_findfiles (bool)
 {
   QItemSelectionModel *m = m_file_tree_view->selectionModel ();
   QModelIndexList rows = m->selectedRows ();
@@ -1034,7 +1075,8 @@
     }
 }
 
-void files_dock_widget::notice_settings ()
+void
+files_dock_widget::notice_settings ()
 {
   gui_settings settings;
 
@@ -1050,7 +1092,7 @@
   // 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 ())
@@ -1059,7 +1101,7 @@
     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
@@ -1079,7 +1121,8 @@
     do_sync_browser_directory ();
 }
 
-void files_dock_widget::popdownmenu_home (bool)
+void
+files_dock_widget::popdownmenu_home (bool)
 {
   QString dir = QString::fromStdString (sys::env::get_home_directory ());
 
@@ -1089,7 +1132,8 @@
   set_current_directory (dir);
 }
 
-void files_dock_widget::popdownmenu_search_dir (bool)
+void
+files_dock_widget::popdownmenu_search_dir (bool)
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly;
@@ -1100,28 +1144,32 @@
     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);
 }
 
-void files_dock_widget::popdownmenu_findfiles (bool)
+void
+files_dock_widget::popdownmenu_findfiles (bool)
 {
   process_find_files (m_file_system_model->rootPath ());
 }
 
-void files_dock_widget::popdownmenu_newdir (bool)
+void
+files_dock_widget::popdownmenu_newdir (bool)
 {
   process_new_dir (m_file_system_model->rootPath ());
 }
 
-void files_dock_widget::popdownmenu_newfile (bool)
+void
+files_dock_widget::popdownmenu_newfile (bool)
 {
   process_new_file (m_file_system_model->rootPath ());
 }
 
-void files_dock_widget::process_new_file (const QString& parent_dir)
+void
+files_dock_widget::process_new_file (const QString& parent_dir)
 {
   bool ok;
 
@@ -1139,7 +1187,8 @@
     }
 }
 
-void files_dock_widget::process_new_dir (const QString& parent_dir)
+void
+files_dock_widget::process_new_dir (const QString& parent_dir)
 {
   bool ok;
 
@@ -1155,17 +1204,20 @@
     }
 }
 
-void files_dock_widget::process_set_current_dir (const QString& dir)
+void
+files_dock_widget::process_set_current_dir (const QString& dir)
 {
   emit displayed_directory_changed (dir);
 }
 
-void files_dock_widget::process_find_files (const QString& dir)
+void
+files_dock_widget::process_find_files (const QString& dir)
 {
   emit find_files_signal (dir);
 }
 
-void files_dock_widget::copyClipboard ()
+void
+files_dock_widget::copyClipboard ()
 {
   if (m_file_tree_view->hasFocus ())
     contextmenu_copy_selection (true);
@@ -1181,7 +1233,8 @@
     }
 }
 
-void files_dock_widget::pasteClipboard ()
+void
+files_dock_widget::pasteClipboard ()
 {
   if (m_current_directory->hasFocus ())
     {
@@ -1193,7 +1246,8 @@
     }
 }
 
-void files_dock_widget::selectAll ()
+void
+files_dock_widget::selectAll ()
 {
   if (m_file_tree_view->hasFocus ())
     m_file_tree_view->selectAll ();
--- a/libgui/src/files-dock-widget.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/files-dock-widget.h	Fri Apr 12 15:10:26 2024 +0200
@@ -136,6 +136,7 @@
 
 private slots:
 
+  void restore_header_state ();
   void headercontextmenu_requested (const QPoint& pos);
   void toggle_header (int col);
 
--- a/libgui/src/find-files-dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/find-files-dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -129,8 +129,8 @@
   m_file_list->sortByColumn (settings.int_value (ff_sort_files_by_column),
                              static_cast<Qt::SortOrder>
                              (settings.uint_value (ff_sort_files_by_order)));
-              // FIXME: use value<Qt::SortOrder> instead of static cast after
-              //        dropping support of Qt 5.4
+  // 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);
@@ -205,7 +205,8 @@
   delete m_dir_iterator;
 }
 
-void find_files_dialog::save_settings ()
+void
+find_files_dialog::save_settings ()
 {
   gui_settings settings;
 
@@ -231,13 +232,15 @@
   settings.sync ();
 }
 
-void find_files_dialog::set_search_dir (const QString& dir)
+void
+find_files_dialog::set_search_dir (const QString& dir)
 {
   stop_find ();
   m_start_dir_edit->setText (dir);
 }
 
-void find_files_dialog::start_find ()
+void
+find_files_dialog::start_find ()
 {
   stop_find ();
 
@@ -279,7 +282,8 @@
   m_timer->start (0);
 }
 
-void find_files_dialog::stop_find ()
+void
+find_files_dialog::stop_find ()
 {
   m_timer->stop ();
 
@@ -302,7 +306,8 @@
   m_status_bar->showMessage (res_str);
 }
 
-void find_files_dialog::browse_folders ()
+void
+find_files_dialog::browse_folders ()
 {
   int opts = 0;  // No options by default.
 
@@ -322,7 +327,8 @@
     m_start_dir_edit->setText (dir);
 }
 
-void find_files_dialog::item_double_clicked (const QModelIndex& idx)
+void
+find_files_dialog::item_double_clicked (const QModelIndex& idx)
 {
   find_files_model *m = static_cast<find_files_model *> (m_file_list->model ());
 
@@ -343,7 +349,8 @@
     }
 }
 
-void find_files_dialog::look_for_files ()
+void
+find_files_dialog::look_for_files ()
 {
   if (m_dir_iterator && m_dir_iterator->hasNext ())
     {
@@ -361,13 +368,15 @@
     }
 }
 
-void find_files_dialog::handle_done (int)
+void
+find_files_dialog::handle_done (int)
 {
   // make sure we stopped processing
   stop_find ();
 }
 
-bool find_files_dialog::is_match (const QFileInfo& info)
+bool
+find_files_dialog::is_match (const QFileInfo& info)
 {
   bool match = true;
   if (info.isDir ())
--- a/libgui/src/find-files-model.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/find-files-model.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,8 @@
 
   find_file_less_than (int ord) { m_sortorder = ord; }
 
-  QVariant getValue (const QFileInfo& f) const
+  QVariant
+  getValue (const QFileInfo& f) const
   {
     QVariant val;
 
@@ -65,13 +66,15 @@
     return val;
   }
 
-  bool lessThan (const QVariant& left, const QVariant& right) const
+  bool
+  lessThan (const QVariant& left, const QVariant& right) const
   {
     return
       left.toString ().compare (right.toString (), Qt::CaseInsensitive) < 0;
   }
 
-  bool operator () (const QFileInfo& left, const QFileInfo& right) const
+  bool
+  operator () (const QFileInfo& left, const QFileInfo& right) const
   {
     QVariant leftval = getValue (left);
     QVariant rightval = getValue (right);
@@ -95,7 +98,8 @@
   m_sortorder = 0;
 }
 
-void find_files_model::clear ()
+void
+find_files_model::clear ()
 {
   beginResetModel ();
 
@@ -104,7 +108,8 @@
   endResetModel ();
 }
 
-void find_files_model::addFile (const QFileInfo& info)
+void
+find_files_model::addFile (const QFileInfo& info)
 {
   beginInsertRows (QModelIndex (), m_files.size (), m_files.size ());
 
@@ -125,17 +130,20 @@
   endInsertRows ();
 }
 
-int find_files_model::rowCount (const QModelIndex&) const
+int
+find_files_model::rowCount (const QModelIndex&) const
 {
   return m_files.size ();
 }
 
-int find_files_model::columnCount (const QModelIndex&) const
+int
+find_files_model::columnCount (const QModelIndex&) const
 {
   return m_columnNames.size ();
 }
 
-QVariant find_files_model::data (const QModelIndex& idx, int role) const
+QVariant
+find_files_model::data (const QModelIndex& idx, int role) const
 {
   QVariant retval;
 
@@ -173,15 +181,17 @@
   return retval;
 }
 
-QVariant find_files_model::headerData (int section,
-                                       Qt::Orientation orientation,
-                                       int role) const
+QVariant
+find_files_model::headerData (int section,
+                              Qt::Orientation orientation,
+                              int role) const
 {
   return ((orientation == Qt::Horizontal && role == Qt::DisplayRole)
           ? m_columnNames[section] : QVariant ());
 }
 
-void find_files_model::sort (int column, Qt::SortOrder order)
+void
+find_files_model::sort (int column, Qt::SortOrder order)
 {
   if (column >= 0)
     {
@@ -204,12 +214,14 @@
     }
 }
 
-QFileInfo find_files_model::fileInfo (const QModelIndex& p) const
+QFileInfo
+find_files_model::fileInfo (const QModelIndex& p) const
 {
   return p.isValid () ? m_files[p.row ()] : QFileInfo ();
 }
 
-QIcon find_files_model::fileIcon (const QModelIndex& p) const
+QIcon
+find_files_model::fileIcon (const QModelIndex& p) const
 {
   QFileIconProvider icon_provider;
 
--- a/libgui/src/gui-preferences-cs.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-cs.h	Fri Apr 12 15:10:26 2024 +0200
@@ -56,7 +56,8 @@
 extern gui_pref cs_colors[];
 
 const QStringList
-cs_color_names = {
+cs_color_names =
+{
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Foreground"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Background"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Selection"),
--- a/libgui/src/gui-preferences-ed.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-ed.h	Fri Apr 12 15:10:26 2024 +0200
@@ -133,7 +133,8 @@
 ed_last_comment_str ("editor/oct_last_comment_str");
 
 const QStringList
-ed_comment_strings = {
+ed_comment_strings =
+{
   "##",
   "#",
   "%",
@@ -159,7 +160,8 @@
 
 // Tabs
 const QStringList
-ed_tab_position_names = {
+ed_tab_position_names =
+{
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Top"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Bottom"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Left"),
--- a/libgui/src/gui-preferences-global.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-global.h	Fri Apr 12 15:10:26 2024 +0200
@@ -93,7 +93,8 @@
 }  ;
 
 const QStringList
-global_icon_paths = {
+global_icon_paths =
+{
   "",
   ":/icons/octave/128x128/",
   ":/icons/tango/128x128/",
@@ -103,7 +104,8 @@
 extern gui_pref global_icon_theme_index;
 
 const QStringList
-global_all_icon_themes = {
+global_all_icon_themes =
+{
   "",
   "octave",
   "tango",
@@ -111,7 +113,8 @@
 };
 
 const QStringList
-global_all_icon_theme_names = {
+global_all_icon_theme_names =
+{
   "System",
   "Octave",
   "Tango"
@@ -126,7 +129,8 @@
   EXTRA_STYLE_FUSION_DARK = 0
 }  ;
 const QStringList
-global_extra_styles = {
+global_extra_styles =
+{
   "Fusion-Dark"
 };
 
@@ -173,7 +177,8 @@
 extern gui_pref global_proxy_pass;
 
 const QStringList
-global_proxy_all_types = {
+global_proxy_all_types =
+{
   "HttpProxy",
   "Socks5Proxy",
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Environment Variables")
--- a/libgui/src/gui-preferences-sc.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-sc.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -217,7 +217,8 @@
 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", OCTAVE_QT_KEYCOMBINATION (CTRL, Qt::Key_D));
 
-QString get_shortcut_section (const QString& key)
+QString
+get_shortcut_section (const QString& key)
 {
   QString section;
 
--- a/libgui/src/gui-preferences-ve.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-ve.h	Fri Apr 12 15:10:26 2024 +0200
@@ -51,7 +51,8 @@
 
 extern gui_pref ve_colors[];
 
-const QStringList ve_color_names = {
+const QStringList ve_color_names =
+{
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Foreground"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Background"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Selected Foreground"),
@@ -59,7 +60,8 @@
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "Alternating Background")
 };
 
-const QStringList ve_save_formats = {
+const QStringList ve_save_formats =
+{
   "ascii",
   "binary",
   "float-binary",
@@ -74,7 +76,8 @@
 
 // The following list is a relation between save format and fiel extension.
 // The format string are case insensitive.
-const QStringList ve_save_formats_ext = {
+const QStringList ve_save_formats_ext =
+{
   "-ascii",       "dat",
   "-hdf5",        "h5",
   "-text",        "txt",
--- a/libgui/src/gui-preferences-ws.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences-ws.h	Fri Apr 12 15:10:26 2024 +0200
@@ -46,14 +46,16 @@
 
 extern gui_pref ws_mru_list;
 
-const QStringList ws_columns_shown = {
+const QStringList ws_columns_shown =
+{
   QT_TRANSLATE_NOOP ("octave::workspace_view", "Class"),
   QT_TRANSLATE_NOOP ("octave::workspace_view", "Dimension"),
   QT_TRANSLATE_NOOP ("octave::workspace_view", "Value"),
   QT_TRANSLATE_NOOP ("octave::workspace_view", "Attribute")
 };
 
-const QStringList ws_columns_shown_keys = {
+const QStringList ws_columns_shown_keys =
+{
   "workspaceview/show_class",
   "workspaceview/show_dimension",
   "workspaceview/show_value",
@@ -71,7 +73,8 @@
 const QString ws_class_chars ("agp");
 
 const QStringList
-ws_color_names = {
+ws_color_names =
+{
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "argument"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "global"),
   QT_TRANSLATE_NOOP ("octave::settings_dialog", "persistent")
--- a/libgui/src/gui-preferences.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-preferences.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -39,30 +39,34 @@
 
 all_gui_preferences *all_gui_preferences::s_instance = nullptr;
 
-void all_gui_preferences::insert (const QString& settings_key,
-                                  const gui_pref& pref)
+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)
+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 ()
+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)
+void
+all_gui_preferences::do_insert (const QString& settings_key,
+                                const gui_pref& pref)
 {
   m_hash.insert (settings_key, pref);
 }
@@ -73,12 +77,14 @@
   return m_hash.value (settings_key);
 }
 
-QStringList all_gui_preferences::do_keys () const
+QStringList
+all_gui_preferences::do_keys () const
 {
   return m_hash.keys ();
 }
 
-void all_gui_preferences::ensure_instance ()
+void
+all_gui_preferences::ensure_instance ()
 {
   if (! s_instance)
     s_instance = new all_gui_preferences ();
@@ -108,7 +114,8 @@
   all_shortcut_preferences::insert (settings_key, *this);
 }
 
-QKeySequence sc_pref::def_value () const
+QKeySequence
+sc_pref::def_value () const
 {
   QKeySequence key_seq = QKeySequence ();
 
@@ -120,37 +127,42 @@
   return key_seq;
 }
 
-QString sc_pref::def_text () const
+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)
+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)
+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 ()
+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)
+void
+all_shortcut_preferences::do_insert (const QString& settings_key,
+                                     const sc_pref& scpref)
 {
   m_hash.insert (settings_key, scpref);
 }
@@ -161,12 +173,14 @@
   return m_hash.value (settings_key);
 }
 
-QStringList all_shortcut_preferences::do_keys () const
+QStringList
+all_shortcut_preferences::do_keys () const
 {
   return m_hash.keys ();
 }
 
-void all_shortcut_preferences::ensure_instance ()
+void
+all_shortcut_preferences::ensure_instance ()
 {
   if (! s_instance)
     s_instance = new all_shortcut_preferences ();
--- a/libgui/src/gui-settings.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-settings.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -71,54 +71,64 @@
   return fileName ();
 }
 
-QString gui_settings::directory_name () const
+QString
+gui_settings::directory_name () const
 {
   QFileInfo sfile (fileName ());
 
   return sfile.absolutePath ();
 }
 
-bool gui_settings::bool_value (const gui_pref& pref) const
+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
+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
+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
+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
+int
+gui_settings::int_value (const gui_pref& pref) const
 {
   return value (pref).toInt ();
 }
 
-QString gui_settings::string_value (const gui_pref& pref) const
+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
+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
+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
+gui_settings::get_color_value (const QVariant& def, int mode) const
 {
   QColor default_color;
 
@@ -136,8 +146,8 @@
       // 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
+      // 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))
@@ -158,7 +168,8 @@
   return default_color;
 }
 
-QColor gui_settings::color_value (const gui_pref& pref, int mode) const
+QColor
+gui_settings::color_value (const gui_pref& pref, int mode) const
 {
   QColor default_color = get_color_value (pref.def (), mode);
 
@@ -166,8 +177,9 @@
                 QVariant (default_color)).value<QColor> ();
 }
 
-void gui_settings::set_color_value (const gui_pref& pref,
-                                    const QColor& color, int mode)
+void
+gui_settings::set_color_value (const gui_pref& pref,
+                               const QColor& color, int mode)
 {
   int m = mode;
   if (m > 1)
@@ -177,7 +189,8 @@
             QVariant (color));
 }
 
-QString gui_settings::sc_value (const sc_pref& scpref) const
+QString
+gui_settings::sc_value (const sc_pref& scpref) const
 {
   QKeySequence key_seq = sc_def_value (scpref);
 
@@ -187,13 +200,14 @@
                 key_seq.toString ()).toString ();
 }
 
-QKeySequence gui_settings::sc_def_value (const sc_pref& scpref) const
+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)
+void
+gui_settings::set_shortcut (QAction *action, const sc_pref& scpref, bool enable)
 {
   if (! enable)
     {
@@ -211,7 +225,8 @@
               << " not found in settings";
 }
 
-void gui_settings::shortcut (QShortcut *sc, const sc_pref& scpref)
+void
+gui_settings::shortcut (QShortcut *sc, const sc_pref& scpref)
 {
   QString shortcut = sc_value (scpref);
 
@@ -222,7 +237,8 @@
               << " not found in settings";
 }
 
-void gui_settings::config_icon_theme ()
+void
+gui_settings::config_icon_theme ()
 {
   int theme_index;
 
@@ -267,8 +283,9 @@
   setValue (global_icon_fallbacks.settings_key (), icon_fallbacks);
 }
 
-QIcon gui_settings::icon (const QString& icon_name, bool octave_only,
-                          const QString& icon_alt_name)
+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");
@@ -288,11 +305,12 @@
         return QIcon (icon_file);
     }
 
-    //QIcon::setThemeName (current_theme);
-    return QIcon ();
+  //QIcon::setThemeName (current_theme);
+  return QIcon ();
 }
 
-QString gui_settings::get_default_font_family ()
+QString
+gui_settings::get_default_font_family ()
 {
   // Get all available fixed width fonts from the Qt font database.
 
@@ -349,7 +367,8 @@
   return default_family;
 }
 
-QStringList gui_settings::get_default_font ()
+QStringList
+gui_settings::get_default_font ()
 {
   QString default_family = get_default_font_family ();
 
@@ -360,7 +379,7 @@
 
   int font_size = font.pointSize ();
   if (font_size == -1)
-    font_size = static_cast <int> (std::floor(font.pointSizeF ()));
+    font_size = static_cast <int> (std::floor (font.pointSizeF ()));
 
   // check for valid font size, otherwise take default 10
   QString default_font_size = "10";
@@ -379,7 +398,8 @@
   return result;
 }
 
-QString gui_settings::get_gui_translation_dir ()
+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");
@@ -388,22 +408,25 @@
   return QString::fromStdString (dldir);
 }
 
-void gui_settings::load_translator (QTranslator *tr, const QLocale& locale, const QString& filename, const QString& prefix, const QString& directory) const
+void
+gui_settings::load_translator (QTranslator *tr, const QLocale& locale, const QString& filename, const QString& prefix, const QString& directory) const
 {
   if (! tr->load (locale, filename, prefix, directory))
     qWarning () << "failed to load translator for locale" << locale.name () << "from file" << filename << "with prefix" << prefix << "from directory" << directory;
 }
 
-void gui_settings::load_translator (QTranslator *tr, const QString& prefix, const QString& language, const QString& directory) const
+void
+gui_settings::load_translator (QTranslator *tr, const QString& prefix, const QString& language, const QString& directory) const
 {
   if (! tr->load (prefix + language, directory))
     if (! tr->load (prefix + language.toLower (), directory))
       qWarning () << "failed to load translator file" << (prefix + language) << "or" << (prefix + language.toLower ()) << "from directory" << directory;
 }
 
-void gui_settings::config_translators (QTranslator *qt_tr,
-                                       QTranslator *qsci_tr,
-                                       QTranslator *gui_tr)
+void
+gui_settings::config_translators (QTranslator *qt_tr,
+                                  QTranslator *qsci_tr,
+                                  QTranslator *gui_tr)
 {
   QString qt_trans_dir
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
@@ -441,7 +464,8 @@
 }
 
 #if defined (HAVE_QSCINTILLA)
-int gui_settings::get_valid_lexer_styles (QsciLexer *lexer, int *styles)
+int
+gui_settings::get_valid_lexer_styles (QsciLexer *lexer, int *styles)
 {
   int max_style = 0;
   int actual_style = 0;
@@ -462,7 +486,8 @@
  * @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)
+static QFont
+copy_font_attributes (const QFont& attr, const QFont& base)
 {
   QFont dest (base);
 
@@ -474,7 +499,8 @@
 }
 
 #if defined (HAVE_QSCINTILLA)
-void gui_settings::read_lexer_settings (QsciLexer *lexer, int mode, int def)
+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
@@ -543,8 +569,9 @@
 }
 #endif
 
-bool gui_settings::update_settings_key (const QString& old_key,
-                                        const QString& new_key)
+bool
+gui_settings::update_settings_key (const QString& old_key,
+                                   const QString& new_key)
 {
   if (contains (old_key))
     {
@@ -557,7 +584,8 @@
   return false;
 }
 
-void gui_settings::update_network_settings ()
+void
+gui_settings::update_network_settings ()
 {
   QNetworkProxy proxy;
 
@@ -618,7 +646,7 @@
           while (! proxy_url.isValid () && count < env_vars.size ())
             {
               proxy_url = QUrl (QString::fromStdString
-                                  (sys::env::getenv (env_vars[count])));
+                                (sys::env::getenv (env_vars[count])));
               count++;
             }
 
@@ -650,7 +678,7 @@
   QNetworkProxy::setApplicationProxy (proxy);
 
   // Set proxy for curl library if not based on environment variables
-  std::string proxy_url_str = proxy_url.toString().toStdString ();
+  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);
@@ -658,7 +686,8 @@
 }
 
 // initialize a given combo box with available text encodings
-void gui_settings::combo_encoding (QComboBox *combo, const QString& current)
+void
+gui_settings::combo_encoding (QComboBox *combo, const QString& current)
 {
   std::vector<std::string> encoding_list {string::get_encoding_list ()};
 
@@ -721,7 +750,8 @@
   combo->setMaxVisibleItems (12);
 }
 
-void gui_settings::reload ()
+void
+gui_settings::reload ()
 {
   // Declare some empty options, which may be set at first startup for
   // writing them into the newly created settings file
@@ -762,7 +792,8 @@
   setValue (global_mono_font.settings_key (), get_default_font_family ());
 }
 
-void gui_settings::check ()
+void
+gui_settings::check ()
 {
   if (status () == QSettings::NoError)
     {
--- a/libgui/src/gui-settings.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-settings.h	Fri Apr 12 15:10:26 2024 +0200
@@ -138,7 +138,7 @@
     Reading a color from the gui_settings taking possible 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 (see get_color_value())
+    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
@@ -221,6 +221,9 @@
 // Some constants used in the preferences of several widgets and therefore
 // defined globally here
 
+// Constants for distinguishing between full GUI and dockwidgets initiated
+// from the command line
+const QString settings_no_mainwin ("__no_mainwin");
 // Constants for handling different color schemes
 const QColor settings_color_no_change (255, 0, 255);
 const QStringList settings_color_modes_ext (QStringList () << "" << "_2");
--- a/libgui/src/gui-utils.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-utils.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -74,7 +74,7 @@
     = actual_geometry.width () * actual_geometry.height ();
   QRect intersection;
 
-  foreach (const QScreen *screen, QGuiApplication::screens())
+  foreach (const QScreen *screen, QGuiApplication::screens ())
     {
       QRect screen_geom = screen->availableGeometry ();
       intersection = screen_geom.intersected (actual_geometry);
--- a/libgui/src/gui-utils.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/gui-utils.h	Fri Apr 12 15:10:26 2024 +0200
@@ -51,9 +51,9 @@
   @return New color as QColor
 */
 
-  extern OCTGUI_API QColor
-  interpolate_color (const QColor& col1, const QColor& col2,
-                     double fs, double fv);
+extern OCTGUI_API QColor
+interpolate_color (const QColor& col1, const QColor& col2,
+                   double fs, double fv);
 
 /*!
   Get the screen geometry of the actual screen.
--- a/libgui/src/history-dock-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/history-dock-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -58,13 +58,15 @@
     make_window ();
 }
 
-void history_dock_widget::set_history (const QStringList& hist)
+void
+history_dock_widget::set_history (const QStringList& hist)
 {
   m_history_model->setStringList (hist);
   m_history_list_view->scrollToBottom ();
 }
 
-void history_dock_widget::append_history (const QString& hist_entry)
+void
+history_dock_widget::append_history (const QString& hist_entry)
 {
   QStringList lst = m_history_model->stringList ();
   lst.append (hist_entry);
@@ -80,12 +82,14 @@
     m_history_list_view->scrollToBottom ();
 }
 
-void history_dock_widget::clear_history ()
+void
+history_dock_widget::clear_history ()
 {
   m_history_model->setStringList (QStringList ());
 }
 
-void history_dock_widget::save_settings ()
+void
+history_dock_widget::save_settings ()
 {
   gui_settings settings;
 
@@ -102,7 +106,8 @@
   octave_dock_widget::save_settings ();
 }
 
-void history_dock_widget::update_filter_history ()
+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
@@ -114,7 +119,8 @@
   m_filter->setCurrentIndex (0);
 }
 
-void history_dock_widget::set_filter_focus (bool focus)
+void
+history_dock_widget::set_filter_focus (bool focus)
 {
   if (focus)
     {
@@ -128,7 +134,8 @@
     }
 }
 
-void history_dock_widget::filter_activate (bool state)
+void
+history_dock_widget::filter_activate (bool state)
 {
   m_filter->setEnabled (state);
   m_sort_filter_proxy_model.setDynamicSortFilter (state);
@@ -141,7 +148,8 @@
   set_filter_focus (state);
 }
 
-void history_dock_widget::ctxMenu (const QPoint& xpos)
+void
+history_dock_widget::ctxMenu (const QPoint& xpos)
 {
   QMenu menu (this);
 
@@ -169,12 +177,14 @@
   menu.exec (m_history_list_view->mapToGlobal (xpos));
 }
 
-void history_dock_widget::handle_double_click (QModelIndex modelIndex)
+void
+history_dock_widget::handle_double_click (QModelIndex modelIndex)
 {
   emit command_double_clicked (modelIndex.data ().toString ());
 }
 
-void history_dock_widget::handle_contextmenu_copy (bool)
+void
+history_dock_widget::handle_contextmenu_copy (bool)
 {
   QString text;
   QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
@@ -193,7 +203,8 @@
   QApplication::clipboard ()->setText (text);
 }
 
-void history_dock_widget::handle_contextmenu_evaluate (bool)
+void
+history_dock_widget::handle_contextmenu_evaluate (bool)
 {
   QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
   QModelIndexList rows = selectionModel->selectedRows ();
@@ -202,7 +213,8 @@
       emit command_double_clicked (it.data ().toString ());
 }
 
-void history_dock_widget::handle_contextmenu_create_script (bool)
+void
+history_dock_widget::handle_contextmenu_create_script (bool)
 {
   QString text;
   QItemSelectionModel *selectionModel = m_history_list_view->selectionModel ();
@@ -224,7 +236,8 @@
     emit command_create_script (text);
 }
 
-void history_dock_widget::handle_contextmenu_filter ()
+void
+history_dock_widget::handle_contextmenu_filter ()
 {
   m_filter_shown = ! m_filter_shown;
   m_filter_widget->setVisible (m_filter_shown);
@@ -232,7 +245,8 @@
   set_filter_focus (m_filter_shown && m_filter_checkbox->isChecked ()) ;
 }
 
-void history_dock_widget::copyClipboard ()
+void
+history_dock_widget::copyClipboard ()
 {
   if (m_history_list_view->hasFocus ())
     handle_contextmenu_copy (true);
@@ -244,7 +258,8 @@
     }
 }
 
-void history_dock_widget::pasteClipboard ()
+void
+history_dock_widget::pasteClipboard ()
 {
   if (m_filter->lineEdit ()->hasFocus ())
     {
@@ -255,7 +270,8 @@
     }
 }
 
-void history_dock_widget::selectAll ()
+void
+history_dock_widget::selectAll ()
 {
   if (m_filter->lineEdit ()->hasFocus ())
     m_filter->lineEdit ()->selectAll ();
@@ -264,7 +280,8 @@
     m_history_list_view->selectAll ();
 }
 
-void history_dock_widget::handle_visibility (bool visible)
+void
+history_dock_widget::handle_visibility (bool visible)
 {
   octave_dock_widget::handle_visibility (visible);
 
@@ -275,7 +292,8 @@
     }
 }
 
-void history_dock_widget::construct ()
+void
+history_dock_widget::construct ()
 {
   m_history_model = new QStringListModel ();
   m_sort_filter_proxy_model.setSourceModel (m_history_model);
@@ -352,7 +370,8 @@
   m_history_list_view->setTextElideMode (Qt::ElideRight);
 }
 
-void history_dock_widget::notice_settings ()
+void
+history_dock_widget::notice_settings ()
 {
   gui_settings settings;
 
--- a/libgui/src/interpreter-qobject.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/interpreter-qobject.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,8 @@
   : QObject (), m_octave_qobj (oct_qobj), m_interpreter (nullptr)
 { }
 
-void interpreter_qobject::execute ()
+void
+interpreter_qobject::execute ()
 {
   // The Octave application context owns the interpreter.
 
@@ -108,7 +109,8 @@
   emit shutdown_finished (exit_status);
 }
 
-void interpreter_qobject::interpreter_event (const fcn_callback& fcn)
+void
+interpreter_qobject::interpreter_event (const fcn_callback& fcn)
 {
   if (! m_interpreter)
     return;
@@ -118,7 +120,8 @@
   evmgr.post_event (fcn);
 }
 
-void interpreter_qobject::interpreter_event (const meth_callback& meth)
+void
+interpreter_qobject::interpreter_event (const meth_callback& meth)
 {
   if (! m_interpreter)
     return;
@@ -128,7 +131,8 @@
   evmgr.post_event (meth);
 }
 
-void interpreter_qobject::interrupt ()
+void
+interpreter_qobject::interrupt ()
 {
   if (! m_interpreter)
     return;
@@ -139,7 +143,8 @@
   m_interpreter->interrupt ();
 }
 
-void interpreter_qobject::pause ()
+void
+interpreter_qobject::pause ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -156,7 +161,8 @@
     }
 }
 
-void interpreter_qobject::stop ()
+void
+interpreter_qobject::stop ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -173,7 +179,8 @@
     }
 }
 
-void interpreter_qobject::resume ()
+void
+interpreter_qobject::resume ()
 {
   // FIXME: Should we make this action work with the old terminal
   // widget?
@@ -184,7 +191,7 @@
       // interpreter is paused.
 
       interpreter_event
-        ([=] (interpreter& interp)
+        ([] (interpreter& interp)
         {
           // INTERPRETER THREAD
 
@@ -193,7 +200,8 @@
     }
 }
 
-qt_interpreter_events *interpreter_qobject::qt_link ()
+qt_interpreter_events *
+interpreter_qobject::qt_link ()
 {
   return m_octave_qobj.qt_link ();
 }
--- a/libgui/src/led-indicator.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/led-indicator.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -35,13 +35,14 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 led_indicator::led_indicator (led_state initial_state, QWidget *p)
-: QLabel (p)
+  : QLabel (p)
 {
-  setFixedSize(12, 12);
+  setFixedSize (12, 12);
   set_state (initial_state);
 }
 
-void led_indicator::set_state (led_state state)
+void
+led_indicator::set_state (led_state state)
 {
   QColor col (Qt::gray);
 
@@ -63,7 +64,8 @@
   setStyleSheet (style_sheet (col));
 }
 
-QString led_indicator::style_sheet (const QColor& col)
+QString
+led_indicator::style_sheet (const QColor& col)
 {
   QColor col_light = interpolate_color (col, QColor (Qt::white), 0.25, 0.9);
 
--- a/libgui/src/led-indicator.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/led-indicator.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,11 +37,11 @@
 public:
 
   enum led_state
-    {
-      LED_STATE_NO = -1,
-      LED_STATE_INACTIVE,
-      LED_STATE_ACTIVE
-    };
+  {
+    LED_STATE_NO = -1,
+    LED_STATE_INACTIVE,
+    LED_STATE_ACTIVE
+  };
 
   led_indicator (led_state initial_state = LED_STATE_INACTIVE,
                  QWidget *parent = 0);
--- a/libgui/src/m-editor/file-editor-interface.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/file-editor-interface.h	Fri Apr 12 15:10:26 2024 +0200
@@ -71,7 +71,7 @@
 
   virtual void empty_script (bool, bool) = 0;
 
-  virtual void restore_session () = 0;
+  virtual void restore_session (bool) = 0;
 
   virtual void enable_menu_shortcuts (bool enable) = 0;
 
--- a/libgui/src/m-editor/file-editor-tab.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/file-editor-tab.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -130,10 +130,10 @@
   m_breakpoint_info.remove_line = -1;
 
   // Initialize last modification date to now
-  m_last_modified = QDateTime::currentDateTimeUtc();
+  m_last_modified = QDateTime::currentDateTimeUtc ();
 
   connect (m_edit_area, SIGNAL (cursorPositionChanged (int, int)),
-           this, SLOT (handle_cursor_moved (int,int)));
+           this, SLOT (handle_cursor_moved (int, int)));
 
   connect (m_edit_area, SIGNAL (SCN_CHARADDED (int)),
            this, SLOT (handle_char_added (int)));
@@ -232,11 +232,11 @@
   // Any interpreter_event signal from a file_editor_tab_widget is
   // handled the same as for the parent main_window object.
 
-  connect (m_edit_area, QOverload<const fcn_callback&>::of (&octave_qscintilla::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&file_editor_tab::interpreter_event));
-
-  connect (m_edit_area, QOverload<const meth_callback&>::of (&octave_qscintilla::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&file_editor_tab::interpreter_event));
+  connect (m_edit_area, qOverload<const fcn_callback&> (&octave_qscintilla::interpreter_event),
+           this, qOverload<const fcn_callback&> (&file_editor_tab::interpreter_event));
+
+  connect (m_edit_area, qOverload<const meth_callback&> (&octave_qscintilla::interpreter_event),
+           this, qOverload<const meth_callback&> (&file_editor_tab::interpreter_event));
 
   // connect modified signal
   connect (m_edit_area, SIGNAL (modificationChanged (bool)),
@@ -246,7 +246,7 @@
            this, SLOT (handle_copy_available (bool)));
 
   connect (&m_file_system_watcher, &QFileSystemWatcher::fileChanged,
-           this, [=] (const QString& path) { file_has_changed (path); });
+           this, [this] (const QString& path) { file_has_changed (path); });
 
   connect (this, &file_editor_tab::maybe_remove_next,
            this, &file_editor_tab::handle_remove_next);
@@ -293,7 +293,8 @@
     }
 }
 
-void file_editor_tab::set_encoding (const QString& new_encoding)
+void
+file_editor_tab::set_encoding (const QString& new_encoding)
 {
   if (new_encoding.isEmpty ())
     return;
@@ -304,7 +305,8 @@
     set_modified (true);
 }
 
-void file_editor_tab::closeEvent (QCloseEvent *e)
+void
+file_editor_tab::closeEvent (QCloseEvent *e)
 {
   int save_dialog = check_file_modified (true);
   if ((save_dialog == QMessageBox::Cancel) ||
@@ -322,12 +324,14 @@
     }
 }
 
-void file_editor_tab::set_current_directory (const QString& dir)
+void
+file_editor_tab::set_current_directory (const QString& dir)
 {
   m_ced = dir;
 }
 
-void file_editor_tab::handle_context_menu_edit (const QString& word_at_cursor)
+void
+file_editor_tab::handle_context_menu_edit (const QString& word_at_cursor)
 {
   // Search for a function with that name in the current file
   // This is done first because local functions and subfunctions have priority
@@ -366,7 +370,7 @@
       // reg expr. found: it is an internal function
       m_edit_area->setCursorPosition (line, match.capturedStart ());
       m_edit_area->SendScintilla (2232, line);     // SCI_ENSUREVISIBLE
-      // SCI_VISIBLEFROMDOCLINE
+                                                   // SCI_VISIBLEFROMDOCLINE
       int vis_line = m_edit_area->SendScintilla (2220, line);
       m_edit_area->SendScintilla (2613, vis_line); // SCI_SETFIRSTVISIBLELINE
       return;
@@ -378,7 +382,8 @@
 // If "dbstop if ..." selected from context menu, create a conditional
 // breakpoint.  The default condition is (a) the existing condition if there
 // is already a breakpoint, (b) any selected text, or (c) empty
-void file_editor_tab::handle_context_menu_break_condition (int linenr)
+void
+file_editor_tab::handle_context_menu_break_condition (int linenr)
 {
   // Ensure editor line numbers match Octave core's line numbers.
   // Give users the option to save modifications if necessary.
@@ -422,8 +427,9 @@
 // to add the breakpoint in the editor tab or a signal to display a
 // new dialog.
 
-void file_editor_tab::handle_dbstop_if (const QString& prompt, int line,
-                                        const QString& cond)
+void
+file_editor_tab::handle_dbstop_if (const QString& prompt, int line,
+                                   const QString& cond)
 {
   bool ok;
   QString new_cond
@@ -442,7 +448,7 @@
       QPointer<file_editor_tab> this_fetab (this);
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([this, this_fetab, line, new_cond] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -507,7 +513,8 @@
     }
 }
 
-void file_editor_tab::set_file_name (const QString& fileName)
+void
+file_editor_tab::set_file_name (const QString& fileName)
 {
   // update tracked file if we really have a file on disk
   QStringList trackedFiles = m_file_system_watcher.files ();
@@ -539,7 +546,8 @@
 
 // valid_file_name (file): checks whether "file" names a file.
 // By default, "file" is empty; then m_file_name is checked
-bool file_editor_tab::valid_file_name (const QString& file)
+bool
+file_editor_tab::valid_file_name (const QString& file)
 {
   if (file.isEmpty ())
     {
@@ -552,7 +560,8 @@
   return true;
 }
 
-void file_editor_tab::enable_file_watcher (bool do_enable)
+void
+file_editor_tab::enable_file_watcher (bool do_enable)
 {
   if (do_enable)
     m_file_system_watcher.addPath (m_file_name);
@@ -565,7 +574,8 @@
 // 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 ()
+bool
+file_editor_tab::unchanged_or_saved ()
 {
   bool retval = true;
   if (m_edit_area->isModified () || ! valid_file_name ())
@@ -586,8 +596,9 @@
 
 // Toggle a breakpoint at the editor_linenr or, if this was called by
 // a click with CTRL pressed, toggle a bookmark at that point.
-void file_editor_tab::handle_margin_clicked (int margin, int editor_linenr,
-                                             Qt::KeyboardModifiers state)
+void
+file_editor_tab::handle_margin_clicked (int margin, int editor_linenr,
+                                        Qt::KeyboardModifiers state)
 {
   if (margin == 1)
     {
@@ -614,7 +625,8 @@
     }
 }
 
-void file_editor_tab::update_lexer ()
+void
+file_editor_tab::update_lexer ()
 {
   // Create a new lexer
   QsciLexer *lexer = nullptr;
@@ -696,7 +708,7 @@
   // If new file, no lexer, or lexer has changed,
   // delete old one and set the newly created as current lexer
   if (! old_lexer || ! valid_file_name ()
-      || QString(old_lexer->lexer ()) != QString(lexer->lexer ()))
+      || QString (old_lexer->lexer ()) != QString (lexer->lexer ()))
     {
       // Delete and set new lexer
       if (old_lexer)
@@ -725,7 +737,8 @@
 //    a) the lexer changes,
 //    b) the settings have changed, or
 //    c) a package was loaded/unloaded
-void file_editor_tab::update_lexer_settings (bool update_apis_only)
+void
+file_editor_tab::update_lexer_settings (bool update_apis_only)
 {
   QsciLexer *lexer = m_edit_area->lexer ();
 
@@ -840,7 +853,7 @@
               QPointer<file_editor_tab> this_fetab (this);
 
               emit interpreter_event
-                ([=] (interpreter& interp)
+                ([this, this_fetab, octave_builtins, octave_functions] (interpreter& interp)
                  {
                    // INTERPRETER THREAD
 
@@ -938,9 +951,9 @@
   QColor current_line_bg
     = 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);
 
@@ -972,7 +985,8 @@
 }
 
 // function for adding entries to the octave lexer's APIs
-void file_editor_tab::handle_add_octave_apis (const QStringList& api_entries)
+void
+file_editor_tab::handle_add_octave_apis (const QStringList& api_entries)
 {
   for (int idx = 0; idx < api_entries.size (); idx++)
     m_lexer_apis->add (api_entries.at (idx));
@@ -980,7 +994,8 @@
   emit api_entries_added ();
 }
 
-void file_editor_tab::handle_api_entries_added ()
+void
+file_editor_tab::handle_api_entries_added ()
 {
   // disconnect slot for saving prepared info if already connected
   disconnect (m_lexer_apis, &QsciAPIs::apiPreparationFinished,
@@ -997,13 +1012,15 @@
   m_lexer_apis->prepare ();  // prepare apis info
 }
 
-void file_editor_tab::save_apis_info ()
+void
+file_editor_tab::save_apis_info ()
 {
   m_lexer_apis->savePrepared (m_prep_apis_file);
 }
 
 // slot for fetab_set_focus: sets the focus to the current edit area
-void file_editor_tab::set_focus (const QWidget *ID)
+void
+file_editor_tab::set_focus (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1011,7 +1028,8 @@
   emit edit_area_changed (m_edit_area); // update the edit area in find dlg
 }
 
-void file_editor_tab::context_help (const QWidget *ID, bool doc)
+void
+file_editor_tab::context_help (const QWidget *ID, bool doc)
 {
   if (ID != this)
     return;
@@ -1019,7 +1037,8 @@
   m_edit_area->context_help_doc (doc);
 }
 
-void file_editor_tab::context_edit (const QWidget *ID)
+void
+file_editor_tab::context_edit (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1027,7 +1046,8 @@
   m_edit_area->context_edit ();
 }
 
-void file_editor_tab::save_file (const QWidget *ID)
+void
+file_editor_tab::save_file (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1035,8 +1055,9 @@
   save_file (m_file_name);
 }
 
-void file_editor_tab::save_file (const QWidget *ID, const QString& fileName,
-                                 bool remove_on_success)
+void
+file_editor_tab::save_file (const QWidget *ID, const QString& fileName,
+                            bool remove_on_success)
 {
   if (ID != this)
     return;
@@ -1044,7 +1065,8 @@
   save_file (fileName, remove_on_success);
 }
 
-void file_editor_tab::save_file_as (const QWidget *ID)
+void
+file_editor_tab::save_file_as (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1052,7 +1074,8 @@
   save_file_as ();
 }
 
-void file_editor_tab::print_file (const QWidget *ID)
+void
+file_editor_tab::print_file (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1067,7 +1090,8 @@
   delete printer;
 }
 
-void file_editor_tab::run_file (const QWidget *ID, bool step_into)
+void
+file_editor_tab::run_file (const QWidget *ID, bool step_into)
 {
   if (ID != this)
     return;
@@ -1103,7 +1127,8 @@
   emit run_file_signal (info);
 }
 
-void file_editor_tab::context_run (const QWidget *ID)
+void
+file_editor_tab::context_run (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1111,7 +1136,8 @@
   m_edit_area->context_run ();
 }
 
-void file_editor_tab::toggle_bookmark (const QWidget *ID)
+void
+file_editor_tab::toggle_bookmark (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1127,7 +1153,8 @@
 
 // Move the text cursor to the closest bookmark
 // after the current line.
-void file_editor_tab::next_bookmark (const QWidget *ID)
+void
+file_editor_tab::next_bookmark (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1148,7 +1175,8 @@
 
 // Move the text cursor to the closest bookmark
 // before the current line.
-void file_editor_tab::previous_bookmark (const QWidget *ID)
+void
+file_editor_tab::previous_bookmark (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1168,7 +1196,8 @@
   m_edit_area->setCursorPosition (prevline, 0);
 }
 
-QString file_editor_tab::get_all_bookmarks ()
+QString
+file_editor_tab::get_all_bookmarks ()
 {
   QString bmlist;
   int line = 0;
@@ -1188,7 +1217,8 @@
   return bmlist;
 }
 
-void file_editor_tab::remove_bookmark (const QWidget *ID)
+void
+file_editor_tab::remove_bookmark (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1206,10 +1236,11 @@
   add_breakpoint_event (line, condition);
 }
 
-void file_editor_tab::handle_request_remove_breakpoint (int line)
+void
+file_editor_tab::handle_request_remove_breakpoint (int line)
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, line] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1220,7 +1251,8 @@
      });
 }
 
-void file_editor_tab::toggle_breakpoint (const QWidget *ID)
+void
+file_editor_tab::toggle_breakpoint (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1239,7 +1271,8 @@
 
 // Move the text cursor to the closest breakpoint (conditional or unconditional)
 // after the current line.
-void file_editor_tab::next_breakpoint (const QWidget *ID)
+void
+file_editor_tab::next_breakpoint (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1261,7 +1294,8 @@
 
 // Move the text cursor to the closest breakpoint (conditional or unconditional)
 // before the current line.
-void file_editor_tab::previous_breakpoint (const QWidget *ID)
+void
+file_editor_tab::previous_breakpoint (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1281,13 +1315,14 @@
   m_edit_area->setCursorPosition (prevline, 0);
 }
 
-void file_editor_tab::remove_all_breakpoints (const QWidget *ID)
+void
+file_editor_tab::remove_all_breakpoints (const QWidget *ID)
 {
   if (ID != this)
     return;
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1299,8 +1334,9 @@
      });
 }
 
-void file_editor_tab::scintilla_command (const QWidget *ID,
-                                         unsigned int sci_msg)
+void
+file_editor_tab::scintilla_command (const QWidget *ID,
+                                    unsigned int sci_msg)
 {
   if (ID != this)
     return;
@@ -1308,8 +1344,9 @@
   m_edit_area->SendScintilla (sci_msg);
 }
 
-void file_editor_tab::comment_selected_text (const QWidget *ID,
-                                             bool input_str)
+void
+file_editor_tab::comment_selected_text (const QWidget *ID,
+                                        bool input_str)
 {
   if (ID != this)
     return;
@@ -1317,7 +1354,8 @@
   do_comment_selected_text (true, input_str);
 }
 
-void file_editor_tab::uncomment_selected_text (const QWidget *ID)
+void
+file_editor_tab::uncomment_selected_text (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1325,7 +1363,8 @@
   do_comment_selected_text (false);
 }
 
-void file_editor_tab::indent_selected_text (const QWidget *ID)
+void
+file_editor_tab::indent_selected_text (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1333,7 +1372,8 @@
   do_indent_selected_text (true);
 }
 
-void file_editor_tab::unindent_selected_text (const QWidget *ID)
+void
+file_editor_tab::unindent_selected_text (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1341,7 +1381,8 @@
   do_indent_selected_text (false);
 }
 
-void file_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID)
+void
+file_editor_tab::smart_indent_line_or_selected_text (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1349,8 +1390,9 @@
   do_smart_indent_line_or_selected_text ();
 }
 
-void file_editor_tab::convert_eol (const QWidget *ID,
-                                   QsciScintilla::EolMode eol_mode)
+void
+file_editor_tab::convert_eol (const QWidget *ID,
+                              QsciScintilla::EolMode eol_mode)
 {
   if (ID != this)
     return;
@@ -1360,7 +1402,8 @@
   update_eol_indicator ();
 }
 
-void file_editor_tab::zoom_in (const QWidget *ID)
+void
+file_editor_tab::zoom_in (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1369,7 +1412,8 @@
   auto_margin_width ();
 }
 
-void file_editor_tab::zoom_out (const QWidget *ID)
+void
+file_editor_tab::zoom_out (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1378,7 +1422,8 @@
   auto_margin_width ();
 }
 
-void file_editor_tab::zoom_normal (const QWidget *ID)
+void
+file_editor_tab::zoom_normal (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1387,7 +1432,8 @@
   auto_margin_width ();
 }
 
-void file_editor_tab::add_breakpoint_event (int line, const QString& cond)
+void
+file_editor_tab::add_breakpoint_event (int line, const QString& cond)
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
@@ -1396,7 +1442,7 @@
   QPointer<file_editor_tab> this_fetab (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_fetab, line, cond] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1421,7 +1467,8 @@
      });
 }
 
-void file_editor_tab::handle_remove_next (int remove_line)
+void
+file_editor_tab::handle_remove_next (int remove_line)
 {
   // Store some info breakpoint
   if (m_breakpoint_info.remove_next)
@@ -1431,7 +1478,8 @@
     }
 }
 
-void file_editor_tab::goto_line (const QWidget *ID, int line)
+void
+file_editor_tab::goto_line (const QWidget *ID, int line)
 {
   if (ID != this)
     return;
@@ -1461,7 +1509,8 @@
   center_current_line (false);  // only center line if at top or bottom
 }
 
-void file_editor_tab::move_match_brace (const QWidget *ID, bool select)
+void
+file_editor_tab::move_match_brace (const QWidget *ID, bool select)
 {
   if (ID != this)
     return;
@@ -1472,7 +1521,8 @@
     m_edit_area->moveToMatchingBrace ();
 }
 
-void file_editor_tab::show_auto_completion (const QWidget *ID)
+void
+file_editor_tab::show_auto_completion (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -1499,7 +1549,8 @@
     }
 }
 
-void file_editor_tab::do_indent_selected_text (bool indent)
+void
+file_editor_tab::do_indent_selected_text (bool indent)
 {
   // FIXME:
   m_edit_area->beginUndoAction ();
@@ -1536,7 +1587,8 @@
   m_edit_area->endUndoAction ();
 }
 
-void file_editor_tab::do_smart_indent_line_or_selected_text ()
+void
+file_editor_tab::do_smart_indent_line_or_selected_text ()
 {
   m_edit_area->beginUndoAction ();
 
@@ -1563,7 +1615,8 @@
   m_edit_area->endUndoAction ();
 }
 
-void file_editor_tab::do_comment_selected_text (bool comment, bool input_str)
+void
+file_editor_tab::do_comment_selected_text (bool comment, bool input_str)
 {
   QRegularExpression rxc;
   QString ws = "^(?:[ \\t]*)";
@@ -1712,7 +1765,8 @@
   m_edit_area->endUndoAction ();
 }
 
-void file_editor_tab::update_window_title (bool modified)
+void
+file_editor_tab::update_window_title (bool modified)
 {
   QString title ("");
   QString tooltip ("");
@@ -1729,7 +1783,8 @@
   emit file_name_changed (title, tooltip, modified);
 }
 
-void file_editor_tab::handle_copy_available (bool enableCopy)
+void
+file_editor_tab::handle_copy_available (bool enableCopy)
 {
   m_copy_available = enableCopy;
   emit editor_state_changed (m_copy_available, m_is_octave_file,
@@ -1737,7 +1792,8 @@
 }
 
 // show_dialog: shows a modal or non modal dialog depending on input arg
-void file_editor_tab::show_dialog (QDialog *dlg, bool modal)
+void
+file_editor_tab::show_dialog (QDialog *dlg, bool modal)
 {
   dlg->setAttribute (Qt::WA_DeleteOnClose);
   if (modal)
@@ -1750,7 +1806,8 @@
     }
 }
 
-int file_editor_tab::check_file_modified (bool remove)
+int
+file_editor_tab::check_file_modified (bool remove)
 {
   int decision = QMessageBox::Yes;
   if (m_edit_area->isModified ())
@@ -1803,12 +1860,14 @@
   return decision;
 }
 
-void file_editor_tab::set_modified (bool modified)
+void
+file_editor_tab::set_modified (bool modified)
 {
   m_edit_area->setModified (modified);
 }
 
-void file_editor_tab::recover_from_exit ()
+void
+file_editor_tab::recover_from_exit ()
 {
   // reset the possibly still existing read only state
   m_edit_area->setReadOnly (false);
@@ -1820,7 +1879,8 @@
   check_restore_breakpoints ();
 }
 
-void file_editor_tab::check_restore_breakpoints ()
+void
+file_editor_tab::check_restore_breakpoints ()
 {
   if (! m_bp_lines.isEmpty ())
     {
@@ -1840,7 +1900,8 @@
     }
 }
 
-QString file_editor_tab::load_file (const QString& fileName)
+QString
+file_editor_tab::load_file (const QString& fileName)
 {
   // get the absolute path
   QFileInfo file_info = QFileInfo (fileName);
@@ -1850,7 +1911,7 @@
   else
     file_to_load = fileName;
   QFile file (file_to_load);
-  if (!file.open(QIODevice::ReadOnly))
+  if (! file.open (QIODevice::ReadOnly))
     return file.errorString ();
 
   int col = 0, line = 0;
@@ -1957,7 +2018,7 @@
           msg_box->show ();
         }
 
-      unwind_action free_u16_str ([=] () { ::free (u16_str); });
+      unwind_action free_u16_str ([u16_str] () { ::free (u16_str); });
 
       QString text
         = QString::fromUtf16 (reinterpret_cast<char16_t *> (u16_str), length);
@@ -1978,7 +2039,8 @@
   return QString ();
 }
 
-void file_editor_tab::handle_decode_warning_answer (QAbstractButton *btn)
+void
+file_editor_tab::handle_decode_warning_answer (QAbstractButton *btn)
 {
   QString txt = btn->text ();
 
@@ -2035,12 +2097,14 @@
   m_edit_area->setReadOnly (false);
 }
 
-void file_editor_tab::handle_current_enc_changed (const QString& enc)
+void
+file_editor_tab::handle_current_enc_changed (const QString& enc)
 {
   m_new_encoding = enc;
 }
 
-QsciScintilla::EolMode file_editor_tab::detect_eol_mode ()
+QsciScintilla::EolMode
+file_editor_tab::detect_eol_mode ()
 {
   QByteArray text = m_edit_area->text ().toLatin1 ();
 
@@ -2078,7 +2142,8 @@
   return eol_mode;
 }
 
-void file_editor_tab::update_eol_indicator ()
+void
+file_editor_tab::update_eol_indicator ()
 {
   switch (m_edit_area->eolMode ())
     {
@@ -2094,7 +2159,8 @@
     }
 }
 
-void file_editor_tab::update_breakpoints ()
+void
+file_editor_tab::update_breakpoints ()
 {
   if (m_file_name.isEmpty ())
     return;
@@ -2108,7 +2174,7 @@
   QPointer<file_editor_tab> this_fetab (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_fetab] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -2128,7 +2194,8 @@
      });
 }
 
-void file_editor_tab::update_breakpoints_handler (const octave_value_list& argout)
+void
+file_editor_tab::update_breakpoints_handler (const octave_value_list& argout)
 {
   octave_map dbg = argout(0).map_value ();
   octave_idx_type n_dbg = dbg.numel ();
@@ -2145,7 +2212,8 @@
     }
 }
 
-void file_editor_tab::new_file (const QString& commands)
+void
+file_editor_tab::new_file (const QString& commands)
 {
   update_window_title (false); // window title (no modification)
 
@@ -2163,10 +2231,11 @@
   m_edit_area->setModified (!commands.isEmpty ());
 }
 
-void file_editor_tab::confirm_dbquit_and_save (const QString& file_to_save,
-                                               const QString& base_name,
-                                               bool remove_on_success,
-                                               bool restore_breakpoints)
+void
+file_editor_tab::confirm_dbquit_and_save (const QString& file_to_save,
+    const QString& base_name,
+    bool remove_on_success,
+    bool restore_breakpoints)
 {
   int ans = QMessageBox::question (nullptr, tr ("Debug or Save"),
                                    tr ("This file is currently being executed.\n"
@@ -2183,7 +2252,7 @@
       QPointer<file_editor_tab> this_fetab (this);
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([this, this_fetab, base_name, file_to_save, remove_on_success, restore_breakpoints] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -2212,9 +2281,10 @@
     }
 }
 
-void file_editor_tab::save_file (const QString& saveFileName,
-                                 bool remove_on_success,
-                                 bool restore_breakpoints)
+void
+file_editor_tab::save_file (const QString& saveFileName,
+                            bool remove_on_success,
+                            bool restore_breakpoints)
 {
   // If it is a new file with no name, signal that saveFileAs
   // should be performed.
@@ -2251,7 +2321,7 @@
       QPointer<file_editor_tab> this_fetab (this);
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([this, this_fetab, base_name, file_to_save, remove_on_success, restore_breakpoints] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -2342,9 +2412,10 @@
                               restore_breakpoints);
 }
 
-void file_editor_tab::do_save_file (const QString& file_to_save,
-                                    bool remove_on_success,
-                                    bool restore_breakpoints)
+void
+file_editor_tab::do_save_file (const QString& file_to_save,
+                               bool remove_on_success,
+                               bool restore_breakpoints)
 {
   QSaveFile file (file_to_save);
 
@@ -2499,7 +2570,8 @@
     }
 }
 
-void file_editor_tab::save_file_as (bool remove_on_success)
+void
+file_editor_tab::save_file_as (bool remove_on_success)
 {
   // Simply put up the file chooser dialog box with a slot connection
   // then return control to the system waiting for a file selection.
@@ -2507,111 +2579,123 @@
   // reset m_new_encoding
   m_new_encoding = m_encoding;
 
-  // If the tab is removed in response to a QFileDialog signal, the tab
-  // can't be a parent.
-  QFileDialog *fileDialog;
-  if (remove_on_success)
-    {
-      // If tab is closed, "this" cannot be parent in which case modality
-      // has no effect.  Disable editing instead.
-      m_edit_area->setReadOnly (true);
-      fileDialog = new QFileDialog ();
-    }
-  else
-    fileDialog = new QFileDialog (this);
+  QFileDialog fileDialog (this);
 
   gui_settings settings;
 
   if (! settings.bool_value (global_use_native_dialogs))
     {
       // Qt file dialogs
-      fileDialog->setOption(QFileDialog::DontUseNativeDialog);
+      fileDialog.setOption (QFileDialog::DontUseNativeDialog);
     }
   else
     {
       // Native file dialogs: Test for already existing files is done manually
       // since native file dialogs might not consider the automatically
       // appended default extension when checking if the file already exists
-      fileDialog->setOption(QFileDialog::DontConfirmOverwrite);
+      fileDialog.setOption (QFileDialog::DontConfirmOverwrite);
     }
 
   // add the possible filters and the default suffix
   QStringList filters;
   filters << tr ("Octave Files (*.m)")
           << tr ("All Files (*)");
-  fileDialog->setNameFilters (filters);
-  fileDialog->setDefaultSuffix ("m");
+  fileDialog.setNameFilters (filters);
 
   if (valid_file_name ())
     {
-      fileDialog->selectFile (m_file_name);
+      fileDialog.selectFile (m_file_name);
       QFileInfo file_info (m_file_name);
       if (file_info.suffix () != "m")
-        {
-          // it is not an octave file
-          fileDialog->selectNameFilter (filters.at (1));  // "All Files"
-          fileDialog->setDefaultSuffix ("");              // no default suffix
-        }
+        fileDialog.selectNameFilter (filters.at (1));  // "All Files"
     }
   else
     {
-      fileDialog->selectFile ("");
-      fileDialog->setDirectory (m_ced);
+      fileDialog.selectFile ("");
+      fileDialog.setDirectory (m_ced);
 
       // propose a name corresponding to the function name
       // if the new file contains a function
       QString fname = get_function_name ();
       if (! fname.isEmpty ())
-        fileDialog->selectFile (fname + ".m");
-    }
-
-  fileDialog->setAcceptMode (QFileDialog::AcceptSave);
-  fileDialog->setViewMode (QFileDialog::Detail);
-  fileDialog->setOption (QFileDialog::HideNameFilterDetails, false);
-
-  // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
-
-  connect (fileDialog, &QFileDialog::filterSelected,
-           this, &file_editor_tab::handle_save_as_filter_selected);
-
-  if (remove_on_success)
-    {
-      connect (fileDialog, &QFileDialog::fileSelected,
-               this, &file_editor_tab::handle_save_file_as_answer_close);
-
-      connect (fileDialog, &QFileDialog::rejected,
-               this, &file_editor_tab::handle_save_file_as_answer_cancel);
-    }
-  else
-    {
-      connect (fileDialog, &QFileDialog::fileSelected,
-               this, &file_editor_tab::handle_save_file_as_answer);
+        fileDialog.selectFile (fname + ".m");
     }
 
-  show_dialog (fileDialog, ! valid_file_name ());
+  fileDialog.setAcceptMode (QFileDialog::AcceptSave);
+  fileDialog.setViewMode (QFileDialog::Detail);
+  fileDialog.setOption (QFileDialog::HideNameFilterDetails, false);
+
+  if (fileDialog.exec ())     // Modal dialog
+    {
+      // Accepted file dialog, no actions required if rejected
+
+      QString save_file_name = fileDialog.selectedFiles ().at (0);
+
+      if (remove_on_success)
+        {
+          // Remove the tab after save
+          if (check_valid_identifier (save_file_name))
+            save_file_as (true);
+          else
+            emit editor_check_conflict_save (save_file_name, true);
+        }
+      else
+        {
+          // Save the file under the selected name
+
+          QFileInfo file (save_file_name);
+
+          // Make sure that the file has the desire suffix
+          QString filter = fileDialog.selectedNameFilter ();
+          QRegularExpression rx {"\\*\\.([^ ^\\)]*)[ \\)]"};    // regexp for suffix in filter
+          QRegularExpressionMatch match = rx.match (filter);
+
+          bool file_name_changed = false;
+          if (match.hasMatch () && file.suffix ().isEmpty ())
+            {
+              save_file_name = save_file_name + "." + match.captured (1);
+              file_name_changed = true;
+            }
+
+          // Use final file name
+          file.setFile (save_file_name);
+
+          // Check if overwrite has to checked again
+          if ((file_name_changed || fileDialog.testOption (QFileDialog::DontConfirmOverwrite))
+              && file.exists ())
+            {
+              int ans = QMessageBox::question (this,
+                                    tr ("Octave Editor"),
+                                    tr ("%1\n already exists\n"
+                                        "Do you want to overwrite it?").arg (save_file_name),
+                                    QMessageBox::Yes | QMessageBox::No);
+              if (ans != QMessageBox::Yes)
+                {
+                  // Try again, if edit area is read only, remove on success
+                  save_file_as (remove_on_success);
+                  return;
+                }
+            }
+
+          if (save_file_name == m_file_name)
+            {
+              save_file (save_file_name);
+            }
+          else
+            {
+              // Have editor check for conflict, do not delete tab after save.
+              if (check_valid_identifier (save_file_name))
+                save_file_as (false);
+              else
+                emit editor_check_conflict_save (save_file_name, false);
+            }
+
+        }
+    }
 }
 
-void file_editor_tab::handle_save_as_filter_selected (const QString& filter)
-{
-  // On some systems, the filterSelected signal is emitted without user
-  // action and with  an empty filter string when the file dialog is shown.
-  // Just return in this case and do not remove the current default suffix.
-  if (filter.isEmpty ())
-    return;
-
-  QFileDialog *file_dialog = qobject_cast<QFileDialog *> (sender ());
-
-  // 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
-}
-
-bool file_editor_tab::check_valid_identifier (QString file_name)
+bool
+file_editor_tab::check_valid_identifier (QString file_name)
 {
   QFileInfo file = QFileInfo (file_name);
   QString base_name = file.baseName ();
@@ -2634,7 +2718,8 @@
   return false;
 }
 
-bool file_editor_tab::check_valid_codec ()
+bool
+file_editor_tab::check_valid_codec ()
 {
   QString editor_text = m_edit_area->text ();
 
@@ -2693,72 +2778,8 @@
   return can_encode;
 }
 
-void file_editor_tab::handle_save_file_as_answer (const QString& save_file_name)
-{
-  QString saveFileName = save_file_name;
-  QFileInfo file (saveFileName);
-  QFileDialog *file_dialog = qobject_cast<QFileDialog *> (sender ());
-
-  // Test if the file dialog should have added a default file
-  // suffix, but the selected file still has no suffix (see Qt bug
-  // https://bugreports.qt.io/browse/QTBUG-59401)
-  if ((! file_dialog->defaultSuffix ().isEmpty ()) && file.suffix ().isEmpty ())
-    {
-      saveFileName = saveFileName + "." + file_dialog->defaultSuffix ();
-    }
-
-  file.setFile (saveFileName);
-
-  // If overwrite confirmation was not done by the file dialog (in case
-  // of native file dialogs, see above), do it here
-  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);
-      if (ans != QMessageBox::Yes)
-        {
-          // Try again, if edit area is read only, remove on success
-          save_file_as (m_edit_area->isReadOnly ());
-          return;
-        }
-    }
-
-  if (saveFileName == m_file_name)
-    {
-      save_file (saveFileName);
-    }
-  else
-    {
-      // Have editor check for conflict, do not delete tab after save.
-      if (check_valid_identifier (saveFileName))
-        save_file_as (false);
-      else
-        emit editor_check_conflict_save (saveFileName, false);
-    }
-}
-
-void file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName)
-{
-  // saveFileName == m_file_name can not happen, because we only can get here
-  // when we close a tab and m_file_name is not a valid filename yet
-
-  // Have editor check for conflict, delete tab after save.
-  if (check_valid_identifier (saveFileName))
-    save_file_as (true);
-  else
-    emit editor_check_conflict_save (saveFileName, true);
-}
-
-void file_editor_tab::handle_save_file_as_answer_cancel ()
-{
-  // User canceled, allow editing again.
-  m_edit_area->setReadOnly (false);
-}
-
-void file_editor_tab::file_has_changed (const QString&, bool do_close)
+void
+file_editor_tab::file_has_changed (const QString&, bool do_close)
 {
   bool file_exists = QFile::exists (m_file_name);
 
@@ -2853,7 +2874,8 @@
     }
 }
 
-void file_editor_tab::notice_settings (bool init)
+void
+file_editor_tab::notice_settings (bool init)
 {
   gui_settings settings;
 
@@ -2954,8 +2976,8 @@
 
   m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR,
                               settings.bool_value (ed_show_hscroll_bar));
-  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1);
-  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING,true);
+  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH, -1);
+  m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING, true);
 
   update_window_title (m_edit_area->isModified ());
 
@@ -3022,7 +3044,8 @@
 
 }
 
-void file_editor_tab::auto_margin_width ()
+void
+file_editor_tab::auto_margin_width ()
 {
   m_edit_area->setMarginWidth (2, "1" + QString::number (m_edit_area->lines ()));
 }
@@ -3032,12 +3055,14 @@
 // 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 ()
+bool
+file_editor_tab::conditional_close ()
 {
   return close ();
 }
 
-void file_editor_tab::change_editor_state (const QWidget *ID)
+void
+file_editor_tab::change_editor_state (const QWidget *ID)
 {
   if (ID != this)
     return;
@@ -3046,7 +3071,8 @@
                              m_edit_area->isModified ());
 }
 
-void file_editor_tab::handle_file_reload_answer (int decision)
+void
+file_editor_tab::handle_file_reload_answer (int decision)
 {
   if (decision == QMessageBox::Yes)
     {
@@ -3060,7 +3086,8 @@
     }
 }
 
-void file_editor_tab::handle_file_resave_answer (int decision)
+void
+file_editor_tab::handle_file_resave_answer (int decision)
 {
   // check decision of user in dialog
   if (decision == QMessageBox::Save)
@@ -3079,7 +3106,8 @@
     }
 }
 
-void file_editor_tab::insert_debugger_pointer (const QWidget *ID, int line)
+void
+file_editor_tab::insert_debugger_pointer (const QWidget *ID, int line)
 {
   if (ID != this || ID == nullptr)
     return;
@@ -3153,7 +3181,8 @@
     }
 }
 
-void file_editor_tab::delete_debugger_pointer (const QWidget *ID, int line)
+void
+file_editor_tab::delete_debugger_pointer (const QWidget *ID, int line)
 {
   if (ID != this || ID == nullptr)
     return;
@@ -3162,9 +3191,10 @@
     emit remove_position_via_debugger_linenr (line);
 }
 
-void file_editor_tab::do_breakpoint_marker (bool insert,
-                                            const QWidget *ID, int line,
-                                            const QString& cond)
+void
+file_editor_tab::do_breakpoint_marker (bool insert,
+                                       const QWidget *ID, int line,
+                                       const QString& cond)
 {
   if (ID != this || ID == nullptr)
     return;
@@ -3218,7 +3248,8 @@
     }
 }
 
-void file_editor_tab::center_current_line (bool always)
+void
+file_editor_tab::center_current_line (bool always)
 {
   long int visible_lines
     = m_edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN);
@@ -3245,13 +3276,15 @@
     }
 }
 
-void file_editor_tab::handle_lines_changed ()
+void
+file_editor_tab::handle_lines_changed ()
 {
   // the related signal is emitted before cursor-move-signal!
   m_lines_changed = true;
 }
 
-void file_editor_tab::handle_cursor_moved (int line, int col)
+void
+file_editor_tab::handle_cursor_moved (int line, int col)
 {
   // Cursor has moved, first check wether an autocompletion list
   // is active or if it was closed. Scintilla provides signals for
@@ -3282,7 +3315,8 @@
                                o_line, m_ind_char_width);
 }
 
-void file_editor_tab::update_rowcol_indicator (int line, int col)
+void
+file_editor_tab::update_rowcol_indicator (int line, int col)
 {
   m_line = line;
   m_col  = col;
@@ -3294,7 +3328,8 @@
 // It is used for handling line breaking if this is desired.
 // The related signal is emitted after the signal for a moved cursor
 // such that m_col and m_line can not be used for current position.
-void file_editor_tab::handle_char_added (int)
+void
+file_editor_tab::handle_char_added (int)
 {
   if (m_line_break)
     {
@@ -3358,7 +3393,8 @@
 }
 
 // Slot handling a double click into the text area
-void file_editor_tab::handle_double_click (int, int, int modifier)
+void
+file_editor_tab::handle_double_click (int, int, int modifier)
 {
   if (! modifier)
     {
@@ -3432,7 +3468,8 @@
     }
 }
 
-QString file_editor_tab::get_function_name ()
+QString
+file_editor_tab::get_function_name ()
 {
   QRegularExpression rxfun1 {"^[\t ]*function[^=]+=([^\\(]+)\\([^\\)]*\\)[\t ]*$"};
   QRegularExpression rxfun2 {"^[\t ]*function[\t ]+([^\\(]+)\\([^\\)]*\\)[\t ]*$"};
--- a/libgui/src/m-editor/file-editor-tab.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/file-editor-tab.h	Fri Apr 12 15:10:26 2024 +0200
@@ -218,12 +218,6 @@
   // When user closes message box for resave question.
   void handle_file_resave_answer (int decision);
 
-  // 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 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);
 
--- a/libgui/src/m-editor/file-editor.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/file-editor.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -81,7 +81,8 @@
   setMovable (true);
 }
 
-tab_bar *file_editor_tab_widget::get_tab_bar () const
+tab_bar *
+file_editor_tab_widget::get_tab_bar () const
 {
   return qobject_cast<tab_bar *> (tabBar ());
 }
@@ -113,7 +114,7 @@
 
   m_find_dialog = nullptr;
 
-  m_closed = false;
+  m_closed = true;
   m_no_focus = false;
   m_editor_ready = false;
 
@@ -128,7 +129,8 @@
   setFocusPolicy (Qt::StrongFocus);
 }
 
-void file_editor::focusInEvent (QFocusEvent *e)
+void
+file_editor::focusInEvent (QFocusEvent *e)
 {
   // The focus is transferred to the active tab and its edit
   // area in this focus in event handler. This is to avoid
@@ -142,7 +144,8 @@
 
 // insert global actions, that should also be displayed in the editor window,
 // into the editor's menu and/or toolbar
-void file_editor::insert_global_actions (QList<QAction *> shared_actions)
+void
+file_editor::insert_global_actions (QList<QAction *> shared_actions)
 {
   // actions/menus that have to be added to the toolbar or the menu
   QAction *open_action = shared_actions.at (OPEN_ACTION);
@@ -177,7 +180,8 @@
   m_edit_menu->insertAction (m_find_action, m_find_files_action);
 }
 
-void file_editor::handle_enter_debug_mode ()
+void
+file_editor::handle_enter_debug_mode ()
 {
   gui_settings settings;
 
@@ -192,7 +196,8 @@
   emit enter_debug_mode_signal ();
 }
 
-void file_editor::handle_exit_debug_mode ()
+void
+file_editor::handle_exit_debug_mode ()
 {
   gui_settings settings;
   settings.set_shortcut (m_run_action, sc_edit_run_run_file);
@@ -201,7 +206,8 @@
   emit exit_debug_mode_signal ();
 }
 
-void file_editor::check_actions ()
+void
+file_editor::check_actions ()
 {
   // Do not include shared actions not only related to the editor
   bool have_tabs = m_tab_widget->count () > 0;
@@ -252,7 +258,8 @@
 // 1. At startup, when the editor has to be (really) visible
 //    (Here we can not use the visibility changed signal)
 // 2. When the editor becomes visible when octave is running
-void file_editor::empty_script (bool startup, bool visible)
+void
+file_editor::empty_script (bool startup, bool visible)
 {
 
   if (startup)
@@ -316,8 +323,13 @@
   request_new_file ("");
 }
 
-void file_editor::restore_session ()
+void
+file_editor::restore_session (bool visible)
 {
+
+  if (! visible)
+    return;
+
   gui_settings settings;
 
   //restore previous session
@@ -355,7 +367,8 @@
         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)
@@ -377,7 +390,8 @@
                        s_data.at (n).bookmarks);
 }
 
-void file_editor::activate ()
+void
+file_editor::activate ()
 {
   if (m_no_focus)
     return;  // No focus for the editor if external open/close request
@@ -388,7 +402,8 @@
   reset_focus ();
 }
 
-void file_editor::set_focus (QWidget *fet)
+void
+file_editor::set_focus (QWidget *fet)
 {
   setFocus ();
 
@@ -399,7 +414,8 @@
 
 // function enabling/disabling the menu accelerators depending on the
 // focus of the editor
-void file_editor::enable_menu_shortcuts (bool enable)
+void
+file_editor::enable_menu_shortcuts (bool enable)
 {
   // Hide or show the find dialog together with the focus of the
   // editor widget depending on the overall visibility of the find dialog.
@@ -438,7 +454,8 @@
 // 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
+file_editor::save_session ()
 {
   gui_settings settings;
 
@@ -481,7 +498,8 @@
   settings.sync ();
 }
 
-bool file_editor::check_closing ()
+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
@@ -531,7 +549,8 @@
   return true;
 }
 
-void file_editor::handle_tab_ready_to_close ()
+void
+file_editor::handle_tab_ready_to_close ()
 {
   if (m_closing_canceled)
     return;
@@ -566,7 +585,8 @@
   setVisible (vis);
 }
 
-void file_editor::request_new_file (const QString& commands)
+void
+file_editor::request_new_file (const QString& commands)
 {
   // Custom editor? If yes, we can only call the editor without passing
   // some initial contents and even without being sure a new file is opened
@@ -583,14 +603,16 @@
   activate ();                              // focus editor and new tab
 }
 
-void file_editor::request_close_file (bool)
+void
+file_editor::request_close_file (bool)
 {
   file_editor_tab *editor_tab
     = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
   editor_tab->conditional_close ();
 }
 
-void file_editor::request_close_all_files (bool)
+void
+file_editor::request_close_all_files (bool)
 {
   file_editor_tab *editor_tab;
 
@@ -602,7 +624,8 @@
     }
 }
 
-void file_editor::request_close_other_files (bool)
+void
+file_editor::request_close_other_files (bool)
 {
   file_editor_tab *editor_tab;
   QWidget *tabID = m_tab_widget->currentWidget ();
@@ -619,7 +642,8 @@
     }
 }
 
-void file_editor::copy_full_file_path (bool)
+void
+file_editor::copy_full_file_path (bool)
 {
   file_editor_tab *editor_tab
     = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
@@ -629,7 +653,8 @@
 }
 
 // open a file from the mru list
-void file_editor::request_mru_open_file (QAction *action)
+void
+file_editor::request_mru_open_file (QAction *action)
 {
   if (action)
     {
@@ -638,49 +663,58 @@
     }
 }
 
-void file_editor::request_print_file (bool)
+void
+file_editor::request_print_file (bool)
 {
   emit fetab_print_file (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_redo (bool)
+void
+file_editor::request_redo (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_REDO);
 }
 
-void file_editor::request_cut (bool)
+void
+file_editor::request_cut (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_CUT);
 }
 
-void file_editor::request_context_help (bool)
+void
+file_editor::request_context_help (bool)
 {
   emit fetab_context_help (m_tab_widget->currentWidget (), false);
 }
 
-void file_editor::request_context_doc (bool)
+void
+file_editor::request_context_doc (bool)
 {
   emit fetab_context_help (m_tab_widget->currentWidget (), true);
 }
 
-void file_editor::request_context_edit (bool)
+void
+file_editor::request_context_edit (bool)
 {
   emit fetab_context_edit (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_save_file (bool)
+void
+file_editor::request_save_file (bool)
 {
   emit fetab_save_file (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_save_file_as (bool)
+void
+file_editor::request_save_file_as (bool)
 {
   emit fetab_save_file_as (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_run_file (bool)
+void
+file_editor::request_run_file (bool)
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
@@ -689,7 +723,7 @@
   QPointer<file_editor> this_fe (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_fe] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -715,166 +749,196 @@
      });
 }
 
-void file_editor::request_step_into_file ()
+void
+file_editor::request_step_into_file ()
 {
   emit fetab_run_file (m_tab_widget->currentWidget (), true);
 }
 
-void file_editor::request_context_run (bool)
+void
+file_editor::request_context_run (bool)
 {
   emit fetab_context_run (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_toggle_bookmark (bool)
+void
+file_editor::request_toggle_bookmark (bool)
 {
   emit fetab_toggle_bookmark (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_next_bookmark (bool)
+void
+file_editor::request_next_bookmark (bool)
 {
   emit fetab_next_bookmark (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_previous_bookmark (bool)
+void
+file_editor::request_previous_bookmark (bool)
 {
   emit fetab_previous_bookmark (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_remove_bookmark (bool)
+void
+file_editor::request_remove_bookmark (bool)
 {
   emit fetab_remove_bookmark (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_move_match_brace (bool)
+void
+file_editor::request_move_match_brace (bool)
 {
   emit fetab_move_match_brace (m_tab_widget->currentWidget (), false);
 }
 
-void file_editor::request_sel_match_brace (bool)
+void
+file_editor::request_sel_match_brace (bool)
 {
   emit fetab_move_match_brace (m_tab_widget->currentWidget (), true);
 }
 
 // FIXME: What should this do with conditional breakpoints?
-void file_editor::request_toggle_breakpoint (bool)
+void
+file_editor::request_toggle_breakpoint (bool)
 {
   emit fetab_toggle_breakpoint (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_next_breakpoint (bool)
+void
+file_editor::request_next_breakpoint (bool)
 {
   emit fetab_next_breakpoint (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_previous_breakpoint (bool)
+void
+file_editor::request_previous_breakpoint (bool)
 {
   emit fetab_previous_breakpoint (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_remove_breakpoint (bool)
+void
+file_editor::request_remove_breakpoint (bool)
 {
   emit fetab_remove_all_breakpoints (m_tab_widget->currentWidget ());
 }
 
 // slots for Edit->Commands actions
-void file_editor::request_delete_start_word (bool)
+void
+file_editor::request_delete_start_word (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_DELWORDLEFT);
 }
 
-void file_editor::request_delete_end_word (bool)
+void
+file_editor::request_delete_end_word (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_DELWORDRIGHT);
 }
 
-void file_editor::request_delete_start_line (bool)
+void
+file_editor::request_delete_start_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_DELLINELEFT);
 }
 
-void file_editor::request_delete_end_line (bool)
+void
+file_editor::request_delete_end_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_DELLINERIGHT);
 }
 
-void file_editor::request_delete_line (bool)
+void
+file_editor::request_delete_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_LINEDELETE);
 }
 
-void file_editor::request_copy_line (bool)
+void
+file_editor::request_copy_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_LINECOPY);
 }
 
-void file_editor::request_cut_line (bool)
+void
+file_editor::request_cut_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_LINECUT);
 }
 
-void file_editor::request_duplicate_selection (bool)
+void
+file_editor::request_duplicate_selection (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_SELECTIONDUPLICATE);
 }
 
-void file_editor::request_transpose_line (bool)
+void
+file_editor::request_transpose_line (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_LINETRANSPOSE);
 }
 
-void file_editor::request_comment_selected_text (bool)
+void
+file_editor::request_comment_selected_text (bool)
 {
   emit fetab_comment_selected_text (m_tab_widget->currentWidget (), false);
 }
 
-void file_editor::request_uncomment_selected_text (bool)
+void
+file_editor::request_uncomment_selected_text (bool)
 {
   emit fetab_uncomment_selected_text (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_comment_var_selected_text (bool)
+void
+file_editor::request_comment_var_selected_text (bool)
 {
   emit fetab_comment_selected_text (m_tab_widget->currentWidget (), true);
 }
 
 // slots for Edit->Format actions
-void file_editor::request_upper_case (bool)
+void
+file_editor::request_upper_case (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_UPPERCASE);
 }
 
-void file_editor::request_lower_case (bool)
+void
+file_editor::request_lower_case (bool)
 {
   emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                 QsciScintillaBase::SCI_LOWERCASE);
 }
 
-void file_editor::request_indent_selected_text (bool)
+void
+file_editor::request_indent_selected_text (bool)
 {
   emit fetab_indent_selected_text (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_unindent_selected_text (bool)
+void
+file_editor::request_unindent_selected_text (bool)
 {
   emit fetab_unindent_selected_text (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_smart_indent_line_or_selected_text ()
+void
+file_editor::request_smart_indent_line_or_selected_text ()
 {
   emit fetab_smart_indent_line_or_selected_text (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_conv_eol_windows (bool)
+void
+file_editor::request_conv_eol_windows (bool)
 {
   emit fetab_convert_eol (m_tab_widget->currentWidget (),
                           QsciScintilla::EolWindows);
@@ -886,14 +950,16 @@
                           QsciScintilla::EolUnix);
 }
 
-void file_editor::request_conv_eol_mac (bool)
+void
+file_editor::request_conv_eol_mac (bool)
 {
   emit fetab_convert_eol (m_tab_widget->currentWidget (),
                           QsciScintilla::EolMac);
 }
 
 // Slot for initially creating and showing the find dialog
-void file_editor::request_find (bool)
+void
+file_editor::request_find (bool)
 {
   // Create the dialog
   find_create ();
@@ -909,7 +975,8 @@
 
 // This method creates the find dialog.
 
-void file_editor::find_create ()
+void
+file_editor::find_create ()
 {
   if (m_find_dialog)
     m_find_dialog->close ();
@@ -959,31 +1026,36 @@
   m_find_dialog->set_visible (true);
 }
 
-void file_editor::request_find_next (bool)
+void
+file_editor::request_find_next (bool)
 {
   if (m_find_dialog)
     m_find_dialog->find_next ();
 }
 
-void file_editor::request_find_previous (bool)
+void
+file_editor::request_find_previous (bool)
 {
   if (m_find_dialog)
     m_find_dialog->find_prev ();
 }
 
-void file_editor::request_goto_line (bool)
+void
+file_editor::request_goto_line (bool)
 {
   emit fetab_goto_line (m_tab_widget->currentWidget ());
 }
 
-void file_editor::request_completion (bool)
+void
+file_editor::request_completion (bool)
 {
   emit fetab_completion (m_tab_widget->currentWidget ());
 }
 
-void file_editor::handle_file_name_changed (const QString& fname,
-                                            const QString& tip,
-                                            bool modified)
+void
+file_editor::handle_file_name_changed (const QString& fname,
+                                       const QString& tip,
+                                       bool modified)
 {
   QObject *fileEditorTab = sender ();
   if (fileEditorTab)
@@ -1009,7 +1081,8 @@
     }
 }
 
-void file_editor::handle_tab_close_request (int index)
+void
+file_editor::handle_tab_close_request (int index)
 {
   file_editor_tab *editor_tab
     = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
@@ -1042,15 +1115,17 @@
 }
 
 // context menu of edit area
-void file_editor::active_tab_changed (int index)
+void
+file_editor::active_tab_changed (int index)
 {
   emit fetab_change_request (m_tab_widget->widget (index));
   activate ();
 }
 
-void file_editor::handle_editor_state_changed (bool copy_available,
-                                               bool is_octave_file,
-                                               bool is_modified)
+void
+file_editor::handle_editor_state_changed (bool copy_available,
+    bool is_octave_file,
+    bool is_modified)
 {
   // In case there is some scenario where traffic could be coming from
   // all the file editor tabs, just process info from the current active tab.
@@ -1075,8 +1150,9 @@
   m_undo_action_enabled = m_undo_action->isEnabled ();
 }
 
-void file_editor::handle_mru_add_file (const QString& file_name,
-                                       const QString& encoding)
+void
+file_editor::handle_mru_add_file (const QString& file_name,
+                                  const QString& encoding)
 {
   int index;
   while ((index = m_mru_files.indexOf (file_name)) >= 0)
@@ -1091,8 +1167,9 @@
   mru_menu_update ();
 }
 
-void file_editor::check_conflict_save (const QString& saveFileName,
-                                       bool remove_on_success)
+void
+file_editor::check_conflict_save (const QString& saveFileName,
+                                  bool remove_on_success)
 {
   // Check whether this file is already open in the editor.
   file_editor_tab *tab = find_tab_widget (saveFileName);
@@ -1153,14 +1230,16 @@
   emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success);
 }
 
-void file_editor::handle_insert_debugger_pointer_request (const QString& file,
-                                                          int line)
+void
+file_editor::handle_insert_debugger_pointer_request (const QString& file,
+    int line)
 {
   request_open_file (file, QString (), line, true); // default encoding
 }
 
-void file_editor::handle_delete_debugger_pointer_request (const QString& file,
-                                                          int line)
+void
+file_editor::handle_delete_debugger_pointer_request (const QString& file,
+    int line)
 {
   if (! file.isEmpty ())
     {
@@ -1179,23 +1258,26 @@
     }
 }
 
-void file_editor::handle_update_breakpoint_marker_request (bool insert,
-                                                           const QString& file,
-                                                           int line,
-                                                           const QString& cond)
+void
+file_editor::handle_update_breakpoint_marker_request (bool insert,
+    const QString& file,
+    int line,
+    const QString& cond)
 {
   request_open_file (file, QString (), line, false, true, insert, cond);
 }
 
-void file_editor::handle_edit_file_request (const QString& file)
+void
+file_editor::handle_edit_file_request (const QString& file)
 {
   request_open_file (file);
 }
 
 // Slot used for signals indicating that a file was changed/renamed or
 // is going to be deleted/renamed
-void file_editor::handle_file_remove (const QString& old_name,
-                                      const QString& new_name)
+void
+file_editor::handle_file_remove (const QString& old_name,
+                                 const QString& new_name)
 {
   // Clear old list of file data and declare a structure for file data
   m_tmp_closed_files.clear ();
@@ -1257,7 +1339,8 @@
 }
 
 // Slot for signal indicating that a file was renamed
-void file_editor::handle_file_renamed (bool load_new)
+void
+file_editor::handle_file_renamed (bool load_new)
 {
   m_no_focus = true;  // Remember for not focussing editor
 
@@ -1288,7 +1371,8 @@
   m_tmp_closed_files.clear ();
 }
 
-void file_editor::notice_settings ()
+void
+file_editor::notice_settings ()
 {
   gui_settings settings;
 
@@ -1395,7 +1479,8 @@
   emit fetab_settings_changed ();
 }
 
-void file_editor::set_shortcuts ()
+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
@@ -1489,7 +1574,8 @@
 // This slot is a reimplementation of the virtual slot in octave_dock_widget.
 // We need this for creating an empty script when the editor has no open
 // files and is made visible.
-void file_editor::handle_visibility (bool visible)
+void
+file_editor::handle_visibility (bool visible)
 {
   octave_dock_widget::handle_visibility (visible);
 
@@ -1500,7 +1586,7 @@
     {
       m_closed = false;
 
-      restore_session ();
+      restore_session (visible);
     }
 
   empty_script (false, visible);
@@ -1508,7 +1594,8 @@
 
 // This slot is a reimplementation of the virtual slot in octave_dock_widget.
 // We need this for updating the parent of the find dialog
-void file_editor::toplevel_change (bool)
+void
+file_editor::toplevel_change (bool)
 {
   if (m_find_dialog)
     {
@@ -1521,34 +1608,39 @@
     }
 }
 
-void file_editor::update_octave_directory (const QString& dir)
+void
+file_editor::update_octave_directory (const QString& dir)
 {
   m_ced = dir;
   emit fetab_set_directory (m_ced);  // for save dialog
 }
 
-void file_editor::copyClipboard ()
+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
+file_editor::pasteClipboard ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
                                   QsciScintillaBase::SCI_PASTE);
 }
 
-void file_editor::selectAll ()
+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
+file_editor::do_undo ()
 {
   if (editor_tab_has_focus ())
     emit fetab_scintilla_command (m_tab_widget->currentWidget (),
@@ -1557,12 +1649,13 @@
 
 // Open a file, if not already open, and mark the current execution location
 // and/or a breakpoint with condition cond.
-void file_editor::request_open_file (const QString& openFileName,
-                                     const QString& encoding,
-                                     int line, bool debug_pointer,
-                                     bool breakpoint_marker, bool insert,
-                                     const QString& cond, int index,
-                                     const QString& bookmarks)
+void
+file_editor::request_open_file (const QString& openFileName,
+                                const QString& encoding,
+                                int line, bool debug_pointer,
+                                bool breakpoint_marker, bool insert,
+                                const QString& cond, int index,
+                                const QString& bookmarks)
 {
   gui_settings settings;
 
@@ -1764,72 +1857,86 @@
     }
 }
 
-void file_editor::request_preferences (bool)
+void
+file_editor::request_preferences (bool)
 {
   emit request_settings_dialog ("editor");
 }
 
-void file_editor::request_styles_preferences (bool)
+void
+file_editor::request_styles_preferences (bool)
 {
   emit request_settings_dialog ("editor_styles");
 }
 
-void file_editor::show_line_numbers (bool)
+void
+file_editor::show_line_numbers (bool)
 {
   toggle_preference (ed_show_line_numbers);
 }
 
-void file_editor::show_white_space (bool)
+void
+file_editor::show_white_space (bool)
 {
   toggle_preference (ed_show_white_space);
 }
 
-void file_editor::show_eol_chars (bool)
+void
+file_editor::show_eol_chars (bool)
 {
   toggle_preference (ed_show_eol_chars);
 }
 
-void file_editor::show_indent_guides (bool)
+void
+file_editor::show_indent_guides (bool)
 {
   toggle_preference (ed_show_indent_guides);
 }
 
-void file_editor::show_long_line (bool)
+void
+file_editor::show_long_line (bool)
 {
   toggle_preference (ed_long_line_marker);
 }
 
-void file_editor::show_toolbar (bool)
+void
+file_editor::show_toolbar (bool)
 {
   toggle_preference (ed_show_toolbar);
 }
 
-void file_editor::show_statusbar (bool)
+void
+file_editor::show_statusbar (bool)
 {
   toggle_preference (ed_show_edit_status_bar);
 }
 
-void file_editor::show_hscrollbar (bool)
+void
+file_editor::show_hscrollbar (bool)
 {
   toggle_preference (ed_show_hscroll_bar);
 }
 
-void file_editor::zoom_in (bool)
+void
+file_editor::zoom_in (bool)
 {
   emit fetab_zoom_in (m_tab_widget->currentWidget ());
 }
 
-void file_editor::zoom_out (bool)
+void
+file_editor::zoom_out (bool)
 {
   emit fetab_zoom_out (m_tab_widget->currentWidget ());
 }
 
-void file_editor::zoom_normal (bool)
+void
+file_editor::zoom_normal (bool)
 {
   emit fetab_zoom_normal (m_tab_widget->currentWidget ());
 }
 
-void file_editor::create_context_menu (QMenu *menu)
+void
+file_editor::create_context_menu (QMenu *menu)
 {
   // remove all standard actions from scintilla
   QList<QAction *> all_actions = menu->actions ();
@@ -1856,7 +1963,8 @@
   menu->addAction (m_run_selection_action);
 }
 
-void file_editor::edit_status_update (bool undo, bool redo)
+void
+file_editor::edit_status_update (bool undo, bool redo)
 {
   if (m_undo_action)
     m_undo_action->setEnabled (undo);
@@ -1864,7 +1972,8 @@
 }
 
 // handler for the close event
-void file_editor::closeEvent (QCloseEvent *e)
+void
+file_editor::closeEvent (QCloseEvent *e)
 {
   gui_settings settings;
 
@@ -1890,7 +1999,8 @@
   octave_dock_widget::closeEvent (e);
 }
 
-void file_editor::dragEnterEvent (QDragEnterEvent *e)
+void
+file_editor::dragEnterEvent (QDragEnterEvent *e)
 {
   if (e->mimeData ()->hasUrls ())
     {
@@ -1898,7 +2008,8 @@
     }
 }
 
-void file_editor::dropEvent (QDropEvent *e)
+void
+file_editor::dropEvent (QDropEvent *e)
 {
   if (e->mimeData ()->hasUrls ())
     {
@@ -1907,7 +2018,8 @@
     }
 }
 
-bool file_editor::is_editor_console_tabbed ()
+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?
@@ -1930,7 +2042,8 @@
   return false;
 }
 
-void file_editor::construct ()
+void
+file_editor::construct ()
 {
   QWidget *editor_widget = new QWidget (this);
 
@@ -2420,7 +2533,8 @@
 }
 
 // Slot when autocompletion list was cancelled
-void file_editor::handle_autoc_cancelled ()
+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 +2558,8 @@
     qsci->undo ();
 }
 
-file_editor_tab *file_editor::reset_focus ()
+file_editor_tab *
+file_editor::reset_focus ()
 {
   // Reset the focus of the tab and the related edit area
   file_editor_tab *f
@@ -2502,7 +2617,7 @@
            this, &file_editor::handle_mru_add_file);
 
   connect (f, &file_editor_tab::request_open_file,
-           this, [=] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); });
+           this, [this] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); });
 
   connect (f, &file_editor_tab::edit_area_changed,
            this, &file_editor::edit_area_changed);
@@ -2512,13 +2627,13 @@
 
   // Signals from the file_editor or main-win non-trivial operations
   connect (this, &file_editor::fetab_settings_changed,
-           f, [=] () { f->notice_settings (); });
+           f, [f] () { f->notice_settings (); });
 
   connect (this, &file_editor::fetab_change_request,
            f, &file_editor_tab::change_editor_state);
 
-  connect (this, QOverload<const QWidget *, const QString&, bool>::of (&file_editor::fetab_save_file),
-           f, QOverload<const QWidget *, const QString&, bool>::of (&file_editor_tab::save_file));
+  connect (this, qOverload<const QWidget *, const QString&, bool> (&file_editor::fetab_save_file),
+           f, qOverload<const QWidget *, const QString&, bool> (&file_editor_tab::save_file));
 
   // Signals from the file_editor trivial operations
   connect (this, &file_editor::fetab_recover_from_exit,
@@ -2540,11 +2655,11 @@
   connect (this, &file_editor::fetab_context_edit,
            f, &file_editor_tab::context_edit);
 
-  connect (this, QOverload<const QWidget *>::of (&file_editor::fetab_save_file),
-           f, QOverload<const QWidget *>::of (&file_editor_tab::save_file));
+  connect (this, qOverload<const QWidget *> (&file_editor::fetab_save_file),
+           f, qOverload<const QWidget *> (&file_editor_tab::save_file));
 
   connect (this, &file_editor::fetab_save_file_as,
-           f, QOverload<const QWidget *>::of (&file_editor_tab::save_file_as));
+           f, qOverload<const QWidget *> (&file_editor_tab::save_file_as));
 
   connect (this, &file_editor::fetab_print_file,
            f, &file_editor_tab::print_file);
@@ -2644,17 +2759,18 @@
   // Any interpreter_event signal from a file_editor_tab_widget is
   // handled the same as for the parent main_window object.
 
-  connect (f, QOverload<const fcn_callback&>::of (&file_editor_tab::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&file_editor::interpreter_event));
-
-  connect (f, QOverload<const meth_callback&>::of (&file_editor_tab::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&file_editor::interpreter_event));
+  connect (f, qOverload<const fcn_callback&> (&file_editor_tab::interpreter_event),
+           this, qOverload<const fcn_callback&> (&file_editor::interpreter_event));
+
+  connect (f, qOverload<const meth_callback&> (&file_editor_tab::interpreter_event),
+           this, qOverload<const meth_callback&> (&file_editor::interpreter_event));
 
   return f;
 }
 
-void file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn,
-                                       int index)
+void
+file_editor::add_file_editor_tab (file_editor_tab *f, const QString& fn,
+                                  int index)
 {
   if (index == -1)
     m_tab_widget->addTab (f, fn);
@@ -2666,7 +2782,8 @@
   check_actions ();
 }
 
-void file_editor::mru_menu_update ()
+void
+file_editor::mru_menu_update ()
 {
   int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles));
 
@@ -2705,14 +2822,15 @@
   settings.sync ();
 }
 
-bool file_editor::call_custom_editor (const QString& file_name, int line)
+bool
+file_editor::call_custom_editor (const QString& file_name, int line)
 {
   // Check if the user wants to use a custom file editor.
 
   gui_settings settings;
 
   if (settings.value (global_use_custom_editor.settings_key (),
-                       global_use_custom_editor.def ()).toBool ())
+                      global_use_custom_editor.def ()).toBool ())
     {
       // use the external editor interface for handling the call
       emit request_open_file_external (file_name, line);
@@ -2727,7 +2845,8 @@
   return false;
 }
 
-void file_editor::toggle_preference (const gui_pref& preference)
+void
+file_editor::toggle_preference (const gui_pref& preference)
 {
   gui_settings settings;
 
@@ -2737,8 +2856,9 @@
 }
 
 // Function for closing the files in a removed directory
-void file_editor::handle_dir_remove (const QString& old_name,
-                                     const QString& new_name)
+void
+file_editor::handle_dir_remove (const QString& old_name,
+                                const QString& new_name)
 {
   QDir old_dir (old_name);
   removed_file_data f_data;
@@ -2805,7 +2925,8 @@
     }
 }
 
-bool file_editor::editor_tab_has_focus ()
+bool
+file_editor::editor_tab_has_focus ()
 {
   QWidget *foc_w = focusWidget ();
   if (foc_w && foc_w->inherits ("octave::octave_qscintilla"))
@@ -2814,7 +2935,8 @@
 }
 
 // Check whether this file is already open in the editor.
-file_editor_tab *file_editor::find_tab_widget (const QString& file)
+file_editor_tab *
+file_editor::find_tab_widget (const QString& file)
 {
   std::string std_file = file.toStdString ();
 
@@ -2838,16 +2960,18 @@
   return nullptr;
 }
 
-QAction * file_editor::add_action (QMenu *menu, const QString& text,
-                                   const char *member,
-                                   QWidget *receiver)
+QAction *
+file_editor::add_action (QMenu *menu, const QString& text,
+                         const char *member,
+                         QWidget *receiver)
 {
   return add_action (menu, QIcon (), text, member, receiver);
 }
 
-QAction * file_editor::add_action (QMenu *menu, const QIcon& icon,
-                                   const QString& text, const char *member,
-                                   QWidget *receiver)
+QAction *
+file_editor::add_action (QMenu *menu, const QIcon& icon,
+                         const QString& text, const char *member,
+                         QWidget *receiver)
 {
   QAction *a;
   QWidget *r = this;
@@ -2869,7 +2993,8 @@
   return a;
 }
 
-QMenu* file_editor::add_menu (QMenuBar *p, QString name)
+QMenu *
+file_editor::add_menu (QMenuBar *p, QString name)
 {
   QMenu *menu = p->addMenu (name);
 
--- a/libgui/src/m-editor/file-editor.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/file-editor.h	Fri Apr 12 15:10:26 2024 +0200
@@ -124,7 +124,7 @@
 
   void check_actions ();
   void empty_script (bool startup, bool visible);
-  void restore_session ();
+  void restore_session (bool visible = true);
 
 signals:
 
--- a/libgui/src/m-editor/find-dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/find-dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -108,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"));
@@ -198,12 +198,13 @@
 
   setWindowModality (Qt::NonModal);
 
-  setAttribute(Qt::WA_ShowWithoutActivating);
-  setAttribute(Qt::WA_DeleteOnClose);
+  setAttribute (Qt::WA_ShowWithoutActivating);
+  setAttribute (Qt::WA_DeleteOnClose);
 }
 
 // The edit_area has changed: update relevant data of the file dialog
-void find_dialog::update_edit_area (octave_qscintilla *edit_area)
+void
+find_dialog::update_edit_area (octave_qscintilla *edit_area)
 {
   m_edit_area = edit_area;
   m_search_selection_check_box->setEnabled (edit_area->hasSelectedText ());
@@ -213,7 +214,8 @@
            Qt::UniqueConnection);
 }
 
-void find_dialog::save_settings ()
+void
+find_dialog::save_settings ()
 {
   gui_settings settings;
 
@@ -260,7 +262,8 @@
   settings.sync ();
 }
 
-void find_dialog::restore_settings (QPoint ed_bottom_right)
+void
+find_dialog::restore_settings (QPoint ed_bottom_right)
 {
   gui_settings settings;
 
@@ -305,7 +308,8 @@
 }
 
 // set text of "search from start" depending on backward search
-void find_dialog::handle_backward_search_changed (int backward)
+void
+find_dialog::handle_backward_search_changed (int backward)
 {
   if (backward)
     m_from_start_check_box->setText (tr ("Search from end"));
@@ -314,7 +318,8 @@
 }
 
 // search text has changed: reset the search
-void find_dialog::handle_search_text_changed ()
+void
+find_dialog::handle_search_text_changed ()
 {
   // Return if nothing has changed
   if (m_search_line_edit->currentText () == m_search_line_edit->itemText (0))
@@ -327,7 +332,8 @@
 }
 
 // replaced text has changed: reset the search
-void find_dialog::handle_replace_text_changed ()
+void
+find_dialog::handle_replace_text_changed ()
 {
   // Return if nothing has changed
   if (m_replace_line_edit->currentText () == m_replace_line_edit->itemText (0))
@@ -337,7 +343,8 @@
 }
 
 // Update the mru list
-void find_dialog::mru_update (QComboBox *mru)
+void
+find_dialog::mru_update (QComboBox *mru)
 {
   // Remove possible empty entries from the mru list
   int index;
@@ -363,13 +370,15 @@
   mru->setCurrentIndex (0);
 }
 
-void find_dialog::handle_sel_search_changed (int selected)
+void
+find_dialog::handle_sel_search_changed (int selected)
 {
   m_from_start_check_box->setEnabled (! selected);
   m_find_result_available = false;
 }
 
-void find_dialog::handle_selection_changed (bool has_selected)
+void
+find_dialog::handle_selection_changed (bool has_selected)
 {
   if (m_rep_active)
     return;
@@ -379,7 +388,8 @@
 }
 
 // initialize search text with selected text if this is in one single line
-void find_dialog::init_search_text ()
+void
+find_dialog::init_search_text ()
 {
   if (m_edit_area && m_edit_area->hasSelectedText ())
     {
@@ -398,17 +408,20 @@
   m_find_next_button->setDefault (true);
 }
 
-void find_dialog::find_next ()
+void
+find_dialog::find_next ()
 {
   find (! m_backward_check_box->isChecked ());
 }
 
-void find_dialog::find_prev ()
+void
+find_dialog::find_prev ()
 {
   find (m_backward_check_box->isChecked ());
 }
 
-void find_dialog::find (bool forward)
+void
+find_dialog::find (bool forward)
 {
   if (! m_edit_area)
     return;
@@ -561,7 +574,8 @@
 
 }
 
-void find_dialog::do_replace ()
+void
+find_dialog::do_replace ()
 {
   if (m_edit_area)
     {
@@ -580,7 +594,8 @@
     }
 }
 
-void find_dialog::replace ()
+void
+find_dialog::replace ()
 {
   if (m_edit_area)
     {
@@ -594,7 +609,8 @@
     }
 }
 
-void find_dialog::replace_all ()
+void
+find_dialog::replace_all ()
 {
   int line, col;
 
@@ -629,19 +645,22 @@
     }
 }
 
-void find_dialog::no_matches_message ()
+void
+find_dialog::no_matches_message ()
 {
   QMessageBox msg_box (QMessageBox::Information, tr ("Find Result"),
                        tr ("No more matches found"), QMessageBox::Ok, this);
   msg_box.exec ();
 }
 
-void find_dialog::reject ()
+void
+find_dialog::reject ()
 {
   close ();
 }
 
-void find_dialog::closeEvent (QCloseEvent *e)
+void
+find_dialog::closeEvent (QCloseEvent *e)
 {
   save_settings ();
   e->accept ();
@@ -649,7 +668,8 @@
 
 // Show and hide with (re-)storing position, otherwise there is always
 // a small shift each time the dialog is shown again
-void find_dialog::set_visible (bool visible)
+void
+find_dialog::set_visible (bool visible)
 {
   if (visible)
     {
--- a/libgui/src/m-editor/marker.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/marker.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -36,7 +36,7 @@
 marker::marker (QsciScintilla *area, int original_linenr,
                 editor_markers type, int editor_linenr,
                 const QString& condition)
-: QObject ()
+  : QObject ()
 {
   construct (area, original_linenr, type, editor_linenr, condition);
 }
@@ -48,9 +48,10 @@
   construct (area, original_linenr, type, original_linenr - 1, condition);
 }
 
-void marker::construct (QsciScintilla *area, int original_linenr,
-                        editor_markers type, int editor_linenr,
-                        const QString& condition)
+void
+marker::construct (QsciScintilla *area, int original_linenr,
+                   editor_markers type, int editor_linenr,
+                   const QString& condition)
 {
   m_edit_area = area;
   m_original_linenr = original_linenr;
@@ -59,7 +60,8 @@
   m_condition = condition;
 }
 
-void marker::handle_remove_via_original_linenr (int linenr)
+void
+marker::handle_remove_via_original_linenr (int linenr)
 {
   if (m_original_linenr == linenr)
     {
@@ -68,7 +70,8 @@
     }
 }
 
-void marker::handle_request_remove_via_editor_linenr (int linenr)
+void
+marker::handle_request_remove_via_editor_linenr (int linenr)
 {
   // Get line number from the edit area and if it matches
   // the requested line number, remove.
@@ -81,14 +84,16 @@
     }
 }
 
-void marker::handle_remove ()
+void
+marker::handle_remove ()
 {
   m_edit_area->markerDeleteHandle (m_mhandle);
   delete this;
 }
 
-void marker::handle_find_translation (int linenr, int& translation_linenr,
-                                      marker *&bp)
+void
+marker::handle_find_translation (int linenr, int& translation_linenr,
+                                 marker *&bp)
 {
   if (m_original_linenr == linenr)
     {
@@ -97,8 +102,9 @@
     }
 }
 
-void marker::handle_find_just_before (int linenr, int& original_linenr,
-                                      int& editor_linenr)
+void
+marker::handle_find_just_before (int linenr, int& original_linenr,
+                                 int& editor_linenr)
 {
   if (m_original_linenr < linenr && m_original_linenr >= original_linenr)
     {
@@ -107,8 +113,9 @@
     }
 }
 
-void marker::handle_find_just_after (int linenr, int& original_linenr,
-                                     int& editor_linenr)
+void
+marker::handle_find_just_after (int linenr, int& original_linenr,
+                                int& editor_linenr)
 {
   if (m_original_linenr > linenr && m_original_linenr <= original_linenr)
     {
@@ -117,14 +124,15 @@
     }
 }
 
-void marker::handle_report_editor_linenr (QIntList& lines,
-                                          QStringList& conditions)
+void
+marker::handle_report_editor_linenr (QIntList& lines, QStringList& conditions)
 {
   lines << m_edit_area->markerLine (m_mhandle);
   conditions << m_condition;
 }
 
-void marker::handle_marker_line_deleted (int mhandle)
+void
+marker::handle_marker_line_deleted (int mhandle)
 {
   // FUTURE SUPPORT: There really should be a signal in QsciScintilla
   // called markerLineDeleted (int mhandle) because there is no way
@@ -144,7 +152,8 @@
     }
 }
 
-void marker::handle_marker_line_undeleted (int mhandle)
+void
+marker::handle_marker_line_undeleted (int mhandle)
 {
   // FUTURE SUPPORT: There really should be a signal in QsciScintilla
   // called markerLineUndeleted (int mhandle) because there is no way
--- a/libgui/src/m-editor/marker.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/marker.h	Fri Apr 12 15:10:26 2024 +0200
@@ -51,15 +51,15 @@
   // If multiple markers are on the same line, the first one listed
   // is drawn at the back, so big ones should be first.
   enum editor_markers
-    {
-      breakpoint,
-      cond_break,
-      unsure_breakpoint,
-      bookmark,
-      debugger_position,
-      unsure_debugger_position,
-      selection
-    };
+  {
+    breakpoint,
+    cond_break,
+    unsure_breakpoint,
+    bookmark,
+    debugger_position,
+    unsure_debugger_position,
+    selection
+  };
 
   marker (QsciScintilla *edit_area, int original_linenr,
           editor_markers marker_type, const QString& condition = "");
--- a/libgui/src/m-editor/octave-qscintilla.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -232,13 +232,15 @@
   emit status_update (isUndoAvailable (), isRedoAvailable ());
 }
 
-void octave_qscintilla::setCursorPosition (int line, int col)
+void
+octave_qscintilla::setCursorPosition (int line, int col)
 {
   QsciScintilla::setCursorPosition (line, col);
   emit update_rowcol_indicator_signal (line, col);
 }
 
-void octave_qscintilla::set_selection_marker_color (const QColor& c)
+void
+octave_qscintilla::set_selection_marker_color (const QColor& c)
 {
   QColor ic = c;
   ic.setAlphaF (0.45);
@@ -250,7 +252,8 @@
 }
 
 // context menu requested
-void octave_qscintilla::contextMenuEvent (QContextMenuEvent *e)
+void
+octave_qscintilla::contextMenuEvent (QContextMenuEvent *e)
 {
 #if defined (HAVE_QSCI_VERSION_2_6_0)
   QPoint global_pos, local_pos;                         // the menu's position
@@ -333,14 +336,15 @@
 }
 
 // common function with flag for documentation
-void octave_qscintilla::contextmenu_help_doc (bool documentation)
+void
+octave_qscintilla::contextmenu_help_doc (bool documentation)
 {
   if (documentation)
     {
       std::string name = m_word_at_cursor.toStdString ();
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([name] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -352,14 +356,16 @@
 }
 
 // call edit the function related to the current word
-void octave_qscintilla::context_edit ()
+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
+octave_qscintilla::context_run ()
 {
   if (hasSelectedText ())
     {
@@ -371,8 +377,9 @@
     }
 }
 
-void octave_qscintilla::get_global_textcursor_pos (QPoint *global_pos,
-                                                   QPoint *local_pos)
+void
+octave_qscintilla::get_global_textcursor_pos (QPoint *global_pos,
+    QPoint *local_pos)
 {
   long position = SendScintilla (SCI_GETCURRENTPOS);
   long point_x  = SendScintilla (SCI_POINTXFROMPOSITION, 0, position);
@@ -382,7 +389,8 @@
 }
 
 // determine the actual word and whether we are in an octave or matlab script
-bool octave_qscintilla::get_actual_word ()
+bool
+octave_qscintilla::get_actual_word ()
 {
   QPoint global_pos, local_pos;
   get_global_textcursor_pos (&global_pos, &local_pos);
@@ -393,7 +401,8 @@
 }
 
 // helper function for clearing all indicators of a specific style
-void octave_qscintilla::clear_selection_markers ()
+void
+octave_qscintilla::clear_selection_markers ()
 {
   int end_pos = text ().length ();
   int end_line, end_col;
@@ -403,7 +412,8 @@
   markerDeleteAll (marker::selection);
 }
 
-QString octave_qscintilla::eol_string ()
+QString
+octave_qscintilla::eol_string ()
 {
   switch (eolMode ())
     {
@@ -421,7 +431,8 @@
 
 // Function returning the true cursor position where the tab length
 // is taken into account.
-void octave_qscintilla::get_current_position (int *pos, int *line, int *col)
+void
+octave_qscintilla::get_current_position (int *pos, int *line, int *col)
 {
   *pos = SendScintilla (QsciScintillaBase::SCI_GETCURRENTPOS);
   *line = SendScintilla (QsciScintillaBase::SCI_LINEFROMPOSITION, *pos);
@@ -429,7 +440,8 @@
 }
 
 // Function returning the comment string of the current lexer
-QStringList octave_qscintilla::comment_string (bool comment)
+QStringList
+octave_qscintilla::comment_string (bool comment)
 {
   int lexer = SendScintilla (SCI_GETLEXER);
 
@@ -494,7 +506,8 @@
 }
 
 // provide the style at a specific position
-int octave_qscintilla::get_style (int pos)
+int
+octave_qscintilla::get_style (int pos)
 {
   int position;
   if (pos < 0)
@@ -507,7 +520,8 @@
 }
 
 // Is a specific cursor position in a line or block comment?
-int octave_qscintilla::is_style_comment (int pos)
+int
+octave_qscintilla::is_style_comment (int pos)
 {
   int lexer = SendScintilla (QsciScintillaBase::SCI_GETLEXER);
   int style = get_style (pos);
@@ -549,8 +563,9 @@
 }
 
 // Do smart indentation after if, for, ...
-void octave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close,
-                                      int line, int ind_char_width)
+void
+octave_qscintilla::smart_indent (bool do_smart_indent, int do_auto_close,
+                                 int line, int ind_char_width)
 {
   QString prevline = text (line);
 
@@ -665,8 +680,9 @@
 }
 
 // Do smart indentation of current selection or line.
-void octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom,
-                                                            int lineTo)
+void
+octave_qscintilla::smart_indent_line_or_selected_text (int lineFrom,
+    int lineTo)
 {
   QRegularExpression blank_line_regexp {"^[\t ]*$"};
 
@@ -787,7 +803,8 @@
     }
 }
 
-void octave_qscintilla::set_word_selection (const QString& word)
+void
+octave_qscintilla::set_word_selection (const QString& word)
 {
   m_selection = word;
 
@@ -809,7 +826,8 @@
     }
 }
 
-void octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2)
+void
+octave_qscintilla::show_selection_markers (int l1, int c1, int l2, int c2)
 {
   fillIndicatorRange (l1, c1, l2, c2, m_indicator_id);
 
@@ -817,28 +835,33 @@
     markerAdd (l1, marker::selection);
 }
 
-void octave_qscintilla::contextmenu_help (bool)
+void
+octave_qscintilla::contextmenu_help (bool)
 {
   contextmenu_help_doc (false);
 }
 
-void octave_qscintilla::contextmenu_doc (bool)
+void
+octave_qscintilla::contextmenu_doc (bool)
 {
   contextmenu_help_doc (true);
 }
 
-void octave_qscintilla::context_help_doc (bool documentation)
+void
+octave_qscintilla::context_help_doc (bool documentation)
 {
   if (get_actual_word ())
     contextmenu_help_doc (documentation);
 }
 
-void octave_qscintilla::contextmenu_edit (bool)
+void
+octave_qscintilla::contextmenu_edit (bool)
 {
   emit context_menu_edit_signal (m_word_at_cursor);
 }
 
-void octave_qscintilla::contextmenu_run_temp_error ()
+void
+octave_qscintilla::contextmenu_run_temp_error ()
 {
   QMessageBox::critical (this, tr ("Octave Editor"),
                          tr ("Creating temporary files failed.\n"
@@ -847,7 +870,8 @@
                              "\"Run Selection\" requires temporary files.").arg (QDir::tempPath ()));
 }
 
-void octave_qscintilla::contextmenu_run (bool)
+void
+octave_qscintilla::contextmenu_run (bool)
 {
   // Take selected code and extend it by commands for echoing each
   // evaluated line and for adding the line to the history (use script)
@@ -914,7 +938,7 @@
 
   // Add commands to the history
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([tmp_hist] (interpreter& interp)
       {
         // INTERPRETER THREAD
 
@@ -941,7 +965,7 @@
 
   // Let the interpreter execute the tmp file
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_oq, tmp_file, tmp_hist, show_dbg_file] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1010,7 +1034,7 @@
                    for (int i = 0; i < rx_list.length (); i++)
                      {
                        rx = QRegularExpression {rx_list.at (i)};
-                       QRegularExpressionMatch match = rx.match(new_msg);
+                       QRegularExpressionMatch match = rx.match (new_msg);
                        if (match.hasMatch ())
                          {
                            err_line = match.captured (1).toInt ();
@@ -1079,7 +1103,7 @@
     tmp_hist->remove ();
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([dbg, auto_repeat] (interpreter& interp)
      {
        // INTERPRETER THREAD
        if (dbg)
@@ -1090,7 +1114,8 @@
 // wrappers for dbstop related context menu items
 
 // FIXME: Why can't the data be sent as the argument to the function???
-void octave_qscintilla::contextmenu_break_condition (bool)
+void
+octave_qscintilla::contextmenu_break_condition (bool)
 {
 #if defined (HAVE_QSCI_VERSION_2_6_0)
   QAction *action = qobject_cast<QAction *>(sender ());
@@ -1104,7 +1129,8 @@
 #endif
 }
 
-void octave_qscintilla::contextmenu_break_once (const QPoint& local_pos)
+void
+octave_qscintilla::contextmenu_break_once (const QPoint& local_pos)
 {
 #if defined (HAVE_QSCI_VERSION_2_6_0)
   emit context_menu_break_once (lineAt (local_pos));
@@ -1113,12 +1139,14 @@
 #endif
 }
 
-void octave_qscintilla::text_changed ()
+void
+octave_qscintilla::text_changed ()
 {
   emit status_update (isUndoAvailable (), isRedoAvailable ());
 }
 
-void octave_qscintilla::cursor_position_changed (int line, int col)
+void
+octave_qscintilla::cursor_position_changed (int line, int col)
 {
   // Clear the selection if we move away from it.  We have to check the
   // position, because we allow entering text at the point of the
@@ -1131,14 +1159,16 @@
 }
 
 // when edit area gets focus update information on undo/redo actions
-void octave_qscintilla::focusInEvent (QFocusEvent *focusEvent)
+void
+octave_qscintilla::focusInEvent (QFocusEvent *focusEvent)
 {
   emit status_update (isUndoAvailable (), isRedoAvailable ());
 
   QsciScintilla::focusInEvent (focusEvent);
 }
 
-void octave_qscintilla::show_replace_action_tooltip ()
+void
+octave_qscintilla::show_replace_action_tooltip ()
 {
   int pos;
   get_current_position (&pos, &m_selection_line, &m_selection_col);
@@ -1167,8 +1197,9 @@
   QToolTip::showText (global_pos, msg);
 }
 
-void octave_qscintilla::replace_all (const QString& o_str, const QString& n_str,
-                                     bool re, bool cs, bool wo)
+void
+octave_qscintilla::replace_all (const QString& o_str, const QString& n_str,
+                                bool re, bool cs, bool wo)
 {
   // get the resulting cursor position
   int pos, line, col, nline, ncol;
@@ -1208,25 +1239,27 @@
   setCursorPosition (line, col);
 }
 
-bool octave_qscintilla::event (QEvent *e)
+bool
+octave_qscintilla::event (QEvent *e)
 {
-  if (m_debug_mode && e->type() == QEvent::ToolTip)
+  if (m_debug_mode && e->type () == QEvent::ToolTip)
     {
       // 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());
+      QString symbol = wordAtPoint (help_e->pos ());
 
       emit show_symbol_tooltip_signal (help_e->globalPos (), symbol);
 
       return true;
     }
 
-  return QsciScintilla::event(e);
+  return QsciScintilla::event (e);
 }
 
-void octave_qscintilla::keyPressEvent (QKeyEvent *key_event)
+void
+octave_qscintilla::keyPressEvent (QKeyEvent *key_event)
 {
   if (m_selection.isEmpty ())
     QsciScintilla::keyPressEvent (key_event);
@@ -1283,8 +1316,9 @@
     }
 }
 
-void octave_qscintilla::auto_close (int auto_endif, int linenr,
-                                    const QString& line, QString& first_word)
+void
+octave_qscintilla::auto_close (int auto_endif, int linenr,
+                               const QString& line, QString& first_word)
 {
   // Insert an "end" for an "if" etc., if needed.
   // (Use of "while" allows "return" to skip the rest.
@@ -1367,7 +1401,8 @@
   setIndentation (linenr + 2, indentation (linenr));
 }
 
-void octave_qscintilla::dragEnterEvent (QDragEnterEvent *e)
+void
+octave_qscintilla::dragEnterEvent (QDragEnterEvent *e)
 {
   // if is not dragging a url, pass to qscintilla to handle,
   // otherwise ignore it so that it will be handled by
@@ -1378,16 +1413,18 @@
     }
   else
     {
-      e->ignore();
+      e->ignore ();
     }
 }
 
-void octave_qscintilla::handle_enter_debug_mode ()
+void
+octave_qscintilla::handle_enter_debug_mode ()
 {
   m_debug_mode = true;
 }
 
-void octave_qscintilla::handle_exit_debug_mode ()
+void
+octave_qscintilla::handle_exit_debug_mode ()
 {
   m_debug_mode = false;
 }
--- a/libgui/src/m-editor/octave-qscintilla.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/octave-qscintilla.h	Fri Apr 12 15:10:26 2024 +0200
@@ -50,11 +50,11 @@
   ~octave_qscintilla () = default;
 
   enum
-    {
-      ST_NONE = 0,
-      ST_LINE_COMMENT,
-      ST_BLOCK_COMMENT
-    };
+  {
+    ST_NONE = 0,
+    ST_LINE_COMMENT,
+    ST_BLOCK_COMMENT
+  };
 
   virtual void contextMenuEvent (QContextMenuEvent *e);
   virtual void setCursorPosition (int line, int col);
--- a/libgui/src/m-editor/octave-txt-lexer.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/m-editor/octave-txt-lexer.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -43,12 +43,14 @@
     return QString ();
 };
 
-const char * octave_txt_lexer::language () const
+const char *
+octave_txt_lexer::language () const
 {
   return "Text";
 }
 
-const char * octave_txt_lexer::lexer () const
+const char *
+octave_txt_lexer::lexer () const
 {
   return "text";
 }
--- a/libgui/src/main-window.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/main-window.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -200,7 +200,8 @@
 
 main_window::~main_window () { }
 
-void main_window::adopt_dock_widgets ()
+void
+main_window::adopt_dock_widgets ()
 {
   adopt_terminal_widget ();
   adopt_documentation_widget ();
@@ -213,7 +214,8 @@
   m_previous_dock = m_command_window;
 }
 
-void main_window::adopt_terminal_widget ()
+void
+main_window::adopt_terminal_widget ()
 {
   m_command_window = m_octave_qobj.terminal_widget (this);
 
@@ -256,7 +258,7 @@
                this, &main_window::edit_mfile);
 
       connect (cmd_widget, &QTerminal::request_open_file_signal,
-               this, QOverload<const QString&, const QString&, int>::of (&main_window::open_file_signal));
+               this, qOverload<const QString&, const QString&, int> (&main_window::open_file_signal));
 
       connect (cmd_widget, &QTerminal::set_screen_size_signal,
                this, &main_window::set_screen_size);
@@ -271,21 +273,23 @@
     }
 }
 
-void main_window::adopt_documentation_widget ()
+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
+main_window::adopt_file_browser_widget ()
 {
   m_file_browser_window = m_octave_qobj.file_browser_widget (this);
 
   make_dock_widget_connections (m_file_browser_window);
 
   connect (m_file_browser_window, &files_dock_widget::open_file,
-           this, QOverload<const QString&>::of (&main_window::open_file_signal));
+           this, qOverload<const QString&> (&main_window::open_file_signal));
   connect (m_file_browser_window,
            &files_dock_widget::displayed_directory_changed,
            this, &main_window::set_current_working_directory);
@@ -306,7 +310,8 @@
            this, &main_window::find_files);
 }
 
-void main_window::adopt_history_widget ()
+void
+main_window::adopt_history_widget ()
 {
   m_history_window = m_octave_qobj.history_widget (this);
 
@@ -319,7 +324,8 @@
            this, &main_window::execute_command_in_terminal);
 }
 
-void main_window::adopt_workspace_widget ()
+void
+main_window::adopt_workspace_widget ()
 {
   m_workspace_window = m_octave_qobj.workspace_widget (this);
 
@@ -329,7 +335,8 @@
            this, &main_window::execute_command_in_terminal);
 }
 
-void main_window::adopt_editor_widget ()
+void
+main_window::adopt_editor_widget ()
 {
   interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
@@ -350,7 +357,7 @@
            &workspace_model::show_symbol_tooltip);
 
   connect (editor, &file_editor::request_settings_dialog,
-           this, QOverload<const QString&>::of (&main_window::process_settings_dialog_request));
+           this, qOverload<const QString&> (&main_window::process_settings_dialog_request));
 
   connect (editor, &file_editor::request_dbcont_signal,
            this, &main_window::debug_continue);
@@ -437,14 +444,16 @@
            m_active_editor, SLOT (handle_edit_file_request (const QString&)));
 }
 
-void main_window::adopt_variable_editor_widget ()
+void
+main_window::adopt_variable_editor_widget ()
 {
   m_variable_editor_window = m_octave_qobj.variable_editor_widget (this);
 
   make_dock_widget_connections (m_variable_editor_window);
 }
 
-void main_window::make_dock_widget_connections (octave_dock_widget *dw)
+void
+main_window::make_dock_widget_connections (octave_dock_widget *dw)
 {
   connect (this, &main_window::init_window_menu,
            dw, &octave_dock_widget::init_window_menu_entry);
@@ -468,17 +477,20 @@
            dw, &octave_dock_widget::save_settings);
 }
 
-bool main_window::command_window_has_focus () const
+bool
+main_window::command_window_has_focus () const
 {
   return m_command_window->has_focus ();
 }
 
-void main_window::focus_command_window ()
+void
+main_window::focus_command_window ()
 {
   m_command_window->activate ();
 }
 
-void main_window::focus_window (const QString& win_name)
+void
+main_window::focus_window (const QString& win_name)
 {
   if (win_name == "command")
     m_command_window->activate ();
@@ -490,7 +502,8 @@
     m_file_browser_window->activate ();
 }
 
-bool main_window::confirm_shutdown ()
+bool
+main_window::confirm_shutdown ()
 {
   bool closenow = true;
 
@@ -518,7 +531,8 @@
 }
 
 // catch focus changes and determine the active dock widget
-void main_window::focus_changed (QWidget *, QWidget *new_widget)
+void
+main_window::focus_changed (QWidget *, QWidget *new_widget)
 {
   // If there is no new widget or the new widget is a menu bar
   // (when pressing <alt>), we can return immediately and reset the
@@ -631,17 +645,20 @@
     }
 }
 
-void main_window::request_reload_settings ()
+void
+main_window::request_reload_settings ()
 {
   emit settings_changed ();
 }
 
-void main_window::report_status_message (const QString& statusMessage)
+void
+main_window::report_status_message (const QString& statusMessage)
 {
   m_status_bar->showMessage (statusMessage, 1000);
 }
 
-void main_window::handle_save_workspace_request ()
+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.
@@ -658,7 +675,7 @@
   if (! file.isEmpty ())
     {
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([file] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -667,7 +684,8 @@
     }
 }
 
-void main_window::handle_load_workspace_request (const QString& file_arg)
+void
+main_window::handle_load_workspace_request (const QString& file_arg)
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = 0;  // No options by default.
@@ -686,7 +704,7 @@
   if (! file.isEmpty ())
     {
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([file] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -701,14 +719,15 @@
     }
 }
 
-void main_window::handle_open_any_request (const QString& file_arg)
+void
+main_window::handle_open_any_request (const QString& file_arg)
 {
   if (! file_arg.isEmpty ())
     {
       std::string file = file_arg.toStdString ();
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([file] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -725,7 +744,8 @@
     }
 }
 
-void main_window::handle_clear_workspace_request ()
+void
+main_window::handle_clear_workspace_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
@@ -736,7 +756,8 @@
      });
 }
 
-void main_window::handle_clear_command_window_request ()
+void
+main_window::handle_clear_command_window_request ()
 {
   emit interpreter_event
     ([] ()
@@ -748,7 +769,8 @@
      });
 }
 
-void main_window::handle_clear_history_request ()
+void
+main_window::handle_clear_history_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
@@ -761,7 +783,8 @@
      });
 }
 
-void main_window::handle_undo_request ()
+void
+main_window::handle_undo_request ()
 {
   if (command_window_has_focus ())
     {
@@ -778,11 +801,12 @@
     emit undo_signal ();
 }
 
-void main_window::modify_path (const QStringList& dir_list,
-                               bool rm, bool subdirs)
+void
+main_window::modify_path (const QStringList& dir_list,
+                          bool rm, bool subdirs)
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([dir_list, subdirs, rm] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -791,7 +815,7 @@
       // Loop over all directories in order to get all subdirs
       for (octave_idx_type i = 0; i < dir_list.length (); i++)
         {
-          std::string dir = dir_list.at(i).toStdString ();
+          std::string dir = dir_list.at (i).toStdString ();
 
           if (subdirs)
             paths.append (Fgenpath (ovl (dir)));
@@ -806,12 +830,14 @@
     });
 }
 
-void main_window::edit_mfile (const QString& name, int line)
+void
+main_window::edit_mfile (const QString& name, int line)
 {
   handle_edit_mfile_request (name, QString (), QString (), line);
 }
 
-void main_window::file_remove_proxy (const QString& o, const QString& n)
+void
+main_window::file_remove_proxy (const QString& o, const QString& n)
 {
   interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
@@ -832,33 +858,39 @@
   qt_link->wake_all ();
 }
 
-void main_window::open_online_documentation_page ()
+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
+main_window::open_bug_tracker_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/bugs.html"));
 }
 
-void main_window::open_octave_packages_page ()
+void
+main_window::open_octave_packages_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://packages.octave.org/index.html"));
 }
 
-void main_window::open_contribute_page ()
+void
+main_window::open_contribute_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/contribute.html"));
 }
 
-void main_window::open_donate_page ()
+void
+main_window::open_donate_page ()
 {
   QDesktopServices::openUrl (QUrl ("https://octave.org/donate.html"));
 }
 
-void main_window::process_settings_dialog_request (const QString& desired_tab)
+void
+main_window::process_settings_dialog_request (const QString& desired_tab)
 {
   if (m_settings_dlg)  // m_settings_dlg is a guarded pointer!
     {
@@ -874,7 +906,8 @@
            this, &main_window::request_reload_settings);
 }
 
-void main_window::show_about_octave ()
+void
+main_window::show_about_octave ()
 {
   std::string message
     = octave_name_version_copyright_copying_warranty_and_bugs (true);
@@ -883,7 +916,8 @@
                       QString::fromStdString (message));
 }
 
-void main_window::notice_settings (bool update_by_worker)
+void
+main_window::notice_settings (bool update_by_worker)
 {
   gui_settings settings;
 
@@ -894,14 +928,14 @@
   if (preferred_style == global_style.def ().toString ())
     preferred_style = m_default_style;
 
-  QApplication* qapp = m_octave_qobj.qapplication();
+  QApplication *qapp = m_octave_qobj.qapplication ();
 
   if (preferred_style == global_extra_styles.at (EXTRA_STYLE_FUSION_DARK))
     {
-      QStyle *new_style = QStyleFactory::create (QStringLiteral("Fusion"));
+      QStyle *new_style = QStyleFactory::create (QStringLiteral ("Fusion"));
       if (new_style)
         qapp->setStyle (new_style);
-      qapp->setPalette (getFusionDarkPalette());
+      qapp->setPalette (getFusionDarkPalette ());
       qapp->setStyleSheet ("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }");
     }
   else
@@ -991,34 +1025,36 @@
 
 }
 
-QPalette main_window::getFusionDarkPalette()
+QPalette
+main_window::getFusionDarkPalette ()
 {
   QPalette darkPalette;
-  darkPalette.setColor(QPalette::Window, QColor(53, 53, 53));
-  darkPalette.setColor(QPalette::WindowText, Qt::white);
-  darkPalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
-  darkPalette.setColor(QPalette::Base, QColor(42, 42, 42));
-  darkPalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
-  darkPalette.setColor(QPalette::ToolTipBase, Qt::white);
-  darkPalette.setColor(QPalette::ToolTipText, Qt::white);
-  darkPalette.setColor(QPalette::Text, Qt::white);
-  darkPalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
-  darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35));
-  darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
-  darkPalette.setColor(QPalette::Button, QColor(53, 53, 53));
-  darkPalette.setColor(QPalette::ButtonText, Qt::white);
-  darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
-  darkPalette.setColor(QPalette::BrightText, Qt::red);
-  darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
-  darkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
-  darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
-  darkPalette.setColor(QPalette::HighlightedText, Qt::white);
-  darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
+  darkPalette.setColor (QPalette::Window, QColor (53, 53, 53));
+  darkPalette.setColor (QPalette::WindowText, Qt::white);
+  darkPalette.setColor (QPalette::Disabled, QPalette::WindowText, QColor (127, 127, 127));
+  darkPalette.setColor (QPalette::Base, QColor (42, 42, 42));
+  darkPalette.setColor (QPalette::AlternateBase, QColor (66, 66, 66));
+  darkPalette.setColor (QPalette::ToolTipBase, Qt::white);
+  darkPalette.setColor (QPalette::ToolTipText, Qt::white);
+  darkPalette.setColor (QPalette::Text, Qt::white);
+  darkPalette.setColor (QPalette::Disabled, QPalette::Text, QColor (127, 127, 127));
+  darkPalette.setColor (QPalette::Dark, QColor (35, 35, 35));
+  darkPalette.setColor (QPalette::Shadow, QColor (20, 20, 20));
+  darkPalette.setColor (QPalette::Button, QColor (53, 53, 53));
+  darkPalette.setColor (QPalette::ButtonText, Qt::white);
+  darkPalette.setColor (QPalette::Disabled, QPalette::ButtonText, QColor (127, 127, 127));
+  darkPalette.setColor (QPalette::BrightText, Qt::red);
+  darkPalette.setColor (QPalette::Link, QColor (42, 130, 218));
+  darkPalette.setColor (QPalette::Highlight, QColor (42, 130, 218));
+  darkPalette.setColor (QPalette::Disabled, QPalette::Highlight, QColor (80, 80, 80));
+  darkPalette.setColor (QPalette::HighlightedText, Qt::white);
+  darkPalette.setColor (QPalette::Disabled, QPalette::HighlightedText, QColor (127, 127, 127));
 
   return darkPalette;
 }
 
-void main_window::prepare_to_exit ()
+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
@@ -1036,12 +1072,14 @@
   m_active_dock = nullptr;
 }
 
-void main_window::go_to_previous_widget ()
+void
+main_window::go_to_previous_widget ()
 {
   m_previous_dock->activate ();
 }
 
-void main_window::update_octave_directory (const QString& dir)
+void
+main_window::update_octave_directory (const QString& dir)
 {
   // Remove existing entry, if any, then add new directory at top and
   // mark it as the current directory.  Finally, update the file list
@@ -1056,7 +1094,8 @@
   m_current_directory_combo_box->setCurrentIndex (0);
 }
 
-void main_window::browse_for_directory ()
+void
+main_window::browse_for_directory ()
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly;
@@ -1078,7 +1117,8 @@
   focus_command_window ();
 }
 
-void main_window::set_current_working_directory (const QString& dir)
+void
+main_window::set_current_working_directory (const QString& dir)
 {
   // Change to dir if it is an existing directory.
 
@@ -1089,7 +1129,7 @@
   if (fileInfo.exists () && fileInfo.isDir ())
     {
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([xdir] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -1098,7 +1138,8 @@
     }
 }
 
-void main_window::change_directory_up ()
+void
+main_window::change_directory_up ()
 {
   set_current_working_directory ("..");
 }
@@ -1107,7 +1148,8 @@
 // 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
+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
@@ -1121,7 +1163,8 @@
     set_current_working_directory (dir);
 }
 
-void main_window::execute_command_in_terminal (const QString& command)
+void
+main_window::execute_command_in_terminal (const QString& command)
 {
   if (m_octave_qobj.experimental_terminal_widget ())
     {
@@ -1130,7 +1173,7 @@
   else
     {
       emit interpreter_event
-        ([=] ()
+        ([command] ()
          {
            // INTERPRETER THREAD
 
@@ -1147,10 +1190,11 @@
   focus_console_after_command ();
 }
 
-void main_window::run_file_in_terminal (const QFileInfo& info)
+void
+main_window::run_file_in_terminal (const QFileInfo& info)
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([info] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1191,7 +1235,8 @@
   focus_console_after_command ();
 }
 
-void main_window::handle_new_figure_request ()
+void
+main_window::handle_new_figure_request ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
@@ -1203,7 +1248,8 @@
      });
 }
 
-void main_window::handle_enter_debugger ()
+void
+main_window::handle_enter_debugger ()
 {
   setWindowTitle ("Octave (Debugging)");
 
@@ -1214,7 +1260,8 @@
   m_debug_quit->setEnabled (true);
 }
 
-void main_window::handle_exit_debugger ()
+void
+main_window::handle_exit_debugger ()
 {
   setWindowTitle ("Octave");
 
@@ -1225,10 +1272,11 @@
   m_debug_quit->setEnabled (false);
 }
 
-void main_window::debug_continue ()
+void
+main_window::debug_continue ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1239,10 +1287,11 @@
      });
 }
 
-void main_window::debug_step_into ()
+void
+main_window::debug_step_into ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1253,14 +1302,15 @@
      });
 }
 
-void main_window::debug_step_over ()
+void
+main_window::debug_step_over ()
 {
   if (m_debug_quit->isEnabled ())
     {
       // We are in debug mode, just call dbstep.
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([this] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -1278,10 +1328,11 @@
     }
 }
 
-void main_window::debug_step_out ()
+void
+main_window::debug_step_out ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1292,7 +1343,8 @@
      });
 }
 
-void main_window::debug_quit ()
+void
+main_window::debug_quit ()
 {
   emit interpreter_event
     ([] (interpreter& interp)
@@ -1311,7 +1363,8 @@
 // These are moved from editor to here for also using them when octave
 // is built without qscintilla
 //
-void main_window::request_open_file ()
+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.
@@ -1320,7 +1373,7 @@
 
   bool is_internal = m_editor_window
                      && ! settings.value (global_use_custom_editor.settings_key (),
-                                           global_use_custom_editor.def ()).toBool ();
+                                          global_use_custom_editor.def ()).toBool ();
 
   // Create a NonModal message.
 
@@ -1328,35 +1381,37 @@
   if (is_internal)
     p = m_editor_window;
 
-  QFileDialog *fileDialog = new QFileDialog (p);
+  QFileDialog fileDialog (p);
 
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   if (! settings.bool_value (global_use_native_dialogs))
-    fileDialog->setOption(QFileDialog::DontUseNativeDialog);
-
-  fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)"));
-
-  fileDialog->setAcceptMode (QFileDialog::AcceptOpen);
-  fileDialog->setViewMode (QFileDialog::Detail);
-  fileDialog->setFileMode (QFileDialog::ExistingFiles);
-  fileDialog->setDirectory (m_current_directory_combo_box->itemText (0));
-
-  connect (fileDialog, &QFileDialog::filesSelected,
-           this, &main_window::request_open_files);
-
-  fileDialog->setWindowModality (Qt::NonModal);
-  fileDialog->setAttribute (Qt::WA_DeleteOnClose);
-  fileDialog->show ();
+    fileDialog.setOption (QFileDialog::DontUseNativeDialog);
+
+  fileDialog.setNameFilter (tr ("Octave Files (*.m);;All Files (*)"));
+
+  fileDialog.setAcceptMode (QFileDialog::AcceptOpen);
+  fileDialog.setViewMode (QFileDialog::Detail);
+  fileDialog.setFileMode (QFileDialog::ExistingFiles);
+  fileDialog.setDirectory (m_current_directory_combo_box->itemText (0));
+
+  if (fileDialog.exec ())
+    {
+      QStringList open_file_names = fileDialog.selectedFiles ();
+      for (int i = 0; i < open_file_names.count (); i++)
+        emit open_file_signal (open_file_names.at (i), m_file_encoding, -1);
+    }
 }
 
 // Create a new script
-void main_window::request_new_script (const QString& commands)
+void
+main_window::request_new_script (const QString& commands)
 {
   emit new_file_signal (commands);
 }
 
 // Create a new function and open it
-void main_window::request_new_function (bool)
+void
+main_window::request_new_function (bool)
 {
   bool ok;
   // Get the name of the new function: Parent of the input dialog is the
@@ -1367,7 +1422,7 @@
   gui_settings settings;
 
   if (! p || settings.value (global_use_custom_editor.settings_key (),
-                              global_use_custom_editor.def ()).toBool ())
+                             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);
@@ -1390,10 +1445,11 @@
     }
 }
 
-void main_window::handle_edit_mfile_request (const QString& fname,
-                                             const QString& ffile,
-                                             const QString& curr_dir,
-                                             int line)
+void
+main_window::handle_edit_mfile_request (const QString& fname,
+                                        const QString& ffile,
+                                        const QString& curr_dir,
+                                        int line)
 {
   // The interpreter_event callback function below emits a signal.
   // Because we don't control when that happens, use a guarded pointer
@@ -1402,7 +1458,7 @@
   QPointer<main_window> this_mw (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_mw, fname, ffile, curr_dir, line] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -1491,7 +1547,8 @@
      });
 }
 
-void main_window::warning_function_not_found (const QString& message)
+void
+main_window::warning_function_not_found (const QString& message)
 {
   QMessageBox *msgBox = new QMessageBox (QMessageBox::Critical,
                                          tr ("Octave Editor"),
@@ -1501,8 +1558,9 @@
   msgBox->show ();
 }
 
-void main_window::handle_insert_debugger_pointer_request (const QString& file,
-                                                          int line)
+void
+main_window::handle_insert_debugger_pointer_request (const QString& file,
+    int line)
 {
   bool cmd_focus = command_window_has_focus ();
 
@@ -1512,8 +1570,9 @@
     focus_command_window ();
 }
 
-void main_window::handle_delete_debugger_pointer_request (const QString& file,
-                                                          int line)
+void
+main_window::handle_delete_debugger_pointer_request (const QString& file,
+    int line)
 {
   bool cmd_focus = command_window_has_focus ();
 
@@ -1523,10 +1582,11 @@
     focus_command_window ();
 }
 
-void main_window::handle_update_breakpoint_marker_request (bool insert,
-                                                           const QString& file,
-                                                           int line,
-                                                           const QString& cond)
+void
+main_window::handle_update_breakpoint_marker_request (bool insert,
+    const QString& file,
+    int line,
+    const QString& cond)
 {
   bool cmd_focus = command_window_has_focus ();
 
@@ -1536,7 +1596,8 @@
     focus_command_window ();
 }
 
-void main_window::read_settings ()
+void
+main_window::read_settings ()
 {
   gui_settings settings;
 
@@ -1552,12 +1613,14 @@
   emit settings_changed ();
 }
 
-void main_window::init_terminal_size ()
+void
+main_window::init_terminal_size ()
 {
   emit init_terminal_size_signal ();
 }
 
-void main_window::set_window_layout ()
+void
+main_window::set_window_layout ()
 {
   gui_settings settings;
 
@@ -1573,7 +1636,7 @@
       return;
     }
 
-  if (isMaximized())
+  if (isMaximized ())
     {
       // If the window state is restored to maximized layout, the
       // horizontal layout is not preserved. This cann be avoided by
@@ -1590,10 +1653,10 @@
       setGeometry (av_geom);  // Set (correct) available geometry
 
       // Force full title bar
-      setWindowFlags(Qt::WindowTitleHint
-                     | Qt::WindowMinMaxButtonsHint
-                     | Qt::WindowSystemMenuHint
-                     | Qt::WindowCloseButtonHint);
+      setWindowFlags (Qt::WindowTitleHint
+                      | Qt::WindowMinMaxButtonsHint
+                      | Qt::WindowSystemMenuHint
+                      | Qt::WindowCloseButtonHint);
     }
 
   if (! restoreState (settings.byte_array_value (mw_state)))
@@ -1654,7 +1717,8 @@
   show ();
 }
 
-void main_window::write_settings ()
+void
+main_window::write_settings ()
 {
   gui_settings settings;
 
@@ -1670,7 +1734,8 @@
   settings.sync ();
 }
 
-void main_window::copyClipboard ()
+void
+main_window::copyClipboard ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1685,7 +1750,8 @@
     emit copyClipboard_signal ();
 }
 
-void main_window::pasteClipboard ()
+void
+main_window::pasteClipboard ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1701,7 +1767,8 @@
     emit pasteClipboard_signal ();
 }
 
-void main_window::selectAll ()
+void
+main_window::selectAll ()
 {
   if (m_current_directory_combo_box->hasFocus ())
     {
@@ -1715,8 +1782,9 @@
     emit selectAll_signal ();
 }
 
-void main_window::handle_gui_status_update (const QString& feature,
-                                            const QString& status)
+void
+main_window::handle_gui_status_update (const QString& feature,
+                                       const QString& status)
 {
   // Put actions that are required for updating a gui features here
 
@@ -1730,7 +1798,8 @@
     }
 }
 
-void main_window::handle_octave_ready ()
+void
+main_window::handle_octave_ready ()
 {
   // actions after the startup files are executed
 
@@ -1770,7 +1839,10 @@
       // 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 ();
+      bool ed_visible =
+        settings.value (dw_is_visible.settings_key ().arg (m_editor_window->objectName ()),
+                        dw_is_visible.def ()).toBool ();
+      m_editor_window->restore_session (ed_visible);
 #endif
     }
 
@@ -1786,7 +1858,7 @@
       QPointer<main_window> this_mw (this);
 
       emit interpreter_event
-        ([=] (interpreter& interp)
+        ([this, this_mw] (interpreter& interp)
         {
           // INTERPRETER_THREAD
 
@@ -1810,7 +1882,8 @@
   focus_command_window ();  // make sure that the command window has focus
 }
 
-void main_window::handle_set_path_dialog_request ()
+void
+main_window::handle_set_path_dialog_request ()
 {
   if (m_set_path_dlg)  // m_set_path_dlg is a guarded pointer!
     return;
@@ -1824,11 +1897,11 @@
   // Any interpreter_event signal from a set_path_dialog object is
   // handled the same as for the main_window object.
 
-  connect (m_set_path_dlg, QOverload<const fcn_callback&>::of (&set_path_dialog::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&main_window::interpreter_event));
-
-  connect (m_set_path_dlg, QOverload<const meth_callback&>::of (&set_path_dialog::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&main_window::interpreter_event));
+  connect (m_set_path_dlg, qOverload<const fcn_callback&> (&set_path_dialog::interpreter_event),
+           this, qOverload<const fcn_callback&> (&main_window::interpreter_event));
+
+  connect (m_set_path_dlg, qOverload<const meth_callback&> (&set_path_dialog::interpreter_event),
+           this, qOverload<const meth_callback&> (&main_window::interpreter_event));
 
   connect (m_set_path_dlg, &set_path_dialog::modify_path_signal,
            this, &main_window::modify_path);
@@ -1846,7 +1919,8 @@
   m_set_path_dlg->update_model ();
 }
 
-void main_window::find_files (const QString& start_dir)
+void
+main_window::find_files (const QString& start_dir)
 {
 
   if (! m_find_files_dlg)
@@ -1860,7 +1934,7 @@
                m_file_browser_window, &files_dock_widget::set_current_directory);
 
       connect (m_find_files_dlg, &find_files_dialog::file_selected,
-               this, QOverload<const QString&>::of (&main_window::open_file_signal));
+               this, qOverload<const QString&> (&main_window::open_file_signal));
 
       m_find_files_dlg->setWindowModality (Qt::NonModal);
     }
@@ -1876,10 +1950,11 @@
 
 }
 
-void main_window::set_screen_size (int ht, int wd)
+void
+main_window::set_screen_size (int ht, int wd)
 {
   emit interpreter_event
-    ([=] ()
+    ([ht, wd] ()
      {
        // INTERPRETER THREAD
 
@@ -1887,7 +1962,8 @@
      });
 }
 
-void main_window::clipboard_has_changed ()
+void
+main_window::clipboard_has_changed ()
 {
   if (m_clipboard->text ().isEmpty ())
     {
@@ -1901,12 +1977,14 @@
     }
 }
 
-void main_window::clear_clipboard ()
+void
+main_window::clear_clipboard ()
 {
   m_clipboard->clear (QClipboard::Clipboard);
 }
 
-void main_window::disable_menu_shortcuts (bool disable)
+void
+main_window::disable_menu_shortcuts (bool disable)
 {
   QHash<QMenu *, QStringList>::const_iterator i = m_hash_menu_text.constBegin ();
 
@@ -1917,7 +1995,8 @@
     }
 }
 
-void main_window::restore_create_file_setting ()
+void
+main_window::restore_create_file_setting ()
 {
   // restore the new files creation setting
 
@@ -1928,51 +2007,47 @@
               this, SLOT (restore_create_file_setting ()));
 }
 
-void main_window::set_file_encoding (const QString& new_encoding)
+void
+main_window::set_file_encoding (const QString& new_encoding)
 {
   m_file_encoding = new_encoding;
 }
 
-// The following slot is called after files have been selected in the
-// open file dialog, possibly with a new selected encoding stored in
-// m_file_encoding
-void main_window::request_open_files (const QStringList& open_file_names)
-{
-  for (int i = 0; i < open_file_names.count (); i++)
-    emit open_file_signal (open_file_names.at (i), m_file_encoding, -1);
-}
-
-void main_window::profiler_session ()
+void
+main_window::profiler_session ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([] (interpreter& interp)
       {
         // INTERPRETER THREAD
         F__profiler_enable__ (interp, ovl (true));
       });
 }
 
-void main_window::profiler_session_resume ()
+void
+main_window::profiler_session_resume ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([] (interpreter& interp)
       {
         // INTERPRETER THREAD
         F__profiler_enable__ (interp, ovl (true));
       });
 }
 
-void main_window::profiler_stop ()
+void
+main_window::profiler_stop ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([] (interpreter& interp)
       {
         // INTERPRETER THREAD
         F__profiler_enable__ (interp, ovl (false));
       });
 }
 
-void main_window::handle_profiler_status_update (bool active)
+void
+main_window::handle_profiler_status_update (bool active)
 {
   m_profiler_start->setEnabled (! active);
   m_profiler_resume->setEnabled (! active);
@@ -1984,7 +2059,8 @@
   m_profiler_status_indicator->set_state (state);
 }
 
-void main_window::profiler_show ()
+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"
@@ -1993,7 +2069,8 @@
   execute_command_in_terminal ("profshow");
 }
 
-void main_window::closeEvent (QCloseEvent *e)
+void
+main_window::closeEvent (QCloseEvent *e)
 {
   write_settings ();
 
@@ -2026,7 +2103,8 @@
     e->ignore ();
 }
 
-void main_window::construct_central_widget ()
+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
@@ -2042,7 +2120,8 @@
 
 // Main subroutine of the constructor
 
-void main_window::construct ()
+void
+main_window::construct ()
 {
   setWindowIcon (QIcon (dw_icon_set_names["NONE"]));
 
@@ -2064,7 +2143,7 @@
 
   // Default argument requires wrapper.
   connect (this, &main_window::settings_changed,
-           this, [=] () { notice_settings (); });
+           this, [this] () { notice_settings (); });
 
   // Connections for signals from the interpreter thread where the slot
   // should be executed by the gui thread
@@ -2080,16 +2159,17 @@
   connect (qt_link, &qt_interpreter_events::file_remove_signal,
            this, &main_window::file_remove_proxy);
 
-  connect (this, QOverload<const fcn_callback&>::of (&main_window::interpreter_event),
-           &m_octave_qobj, QOverload<const fcn_callback&>::of (&base_qobject::interpreter_event));
-
-  connect (this, QOverload<const meth_callback&>::of (&main_window::interpreter_event),
-           &m_octave_qobj, QOverload<const meth_callback&>::of (&base_qobject::interpreter_event));
+  connect (this, qOverload<const fcn_callback&> (&main_window::interpreter_event),
+           &m_octave_qobj, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));
+
+  connect (this, qOverload<const meth_callback&> (&main_window::interpreter_event),
+           &m_octave_qobj, qOverload<const meth_callback&> (&base_qobject::interpreter_event));
 
   configure_shortcuts ();
 }
 
-void main_window::construct_octave_qt_link ()
+void
+main_window::construct_octave_qt_link ()
 {
   interpreter_qobject *interp_qobj = m_octave_qobj.interpreter_qobj ();
 
@@ -2114,7 +2194,7 @@
            this, &main_window::handle_exit_debugger);
 
   connect (qt_link, &qt_interpreter_events::show_preferences_signal,
-           this, [=] () { process_settings_dialog_request (); });
+           this, [this] () { process_settings_dialog_request (); });
 
   connect (qt_link, &qt_interpreter_events::insert_debugger_pointer_signal,
            this, &main_window::handle_insert_debugger_pointer_request);
@@ -2132,9 +2212,10 @@
            this, &main_window::update_gui_lexer_signal);
 }
 
-QAction* main_window::add_action (QMenu *menu, const QIcon& icon,
-                                  const QString& text, const char *member,
-                                  const QWidget *receiver)
+QAction *
+main_window::add_action (QMenu *menu, const QIcon& icon,
+                         const QString& text, const char *member,
+                         const QWidget *receiver)
 {
   QAction *a;
 
@@ -2148,7 +2229,8 @@
   return a;
 }
 
-QMenu* main_window::m_add_menu (QMenuBar *p, QString name)
+QMenu *
+main_window::m_add_menu (QMenuBar *p, QString name)
 {
   QMenu *menu = p->addMenu (name);
 
@@ -2166,7 +2248,8 @@
   return menu;
 }
 
-void main_window::construct_menu_bar ()
+void
+main_window::construct_menu_bar ()
 {
   QMenuBar *menu_bar = menuBar ();
 
@@ -2187,7 +2270,8 @@
 #if defined (HAVE_QSCINTILLA)
   // call the editor to add actions which should also be available in the
   // editor's menu and tool bar
-  QList<QAction *> shared_actions = {
+  QList<QAction *> shared_actions =
+  {
     m_new_script_action,
     m_new_function_action,
     m_open_action,
@@ -2201,7 +2285,8 @@
 #endif
 }
 
-void main_window::construct_file_menu (QMenuBar *p)
+void
+main_window::construct_file_menu (QMenuBar *p)
 {
   QMenu *file_menu = m_add_menu (p, tr ("&File"));
 
@@ -2248,7 +2333,8 @@
            SLOT (request_open_file (const QString&, const QString&, int)));
 }
 
-void main_window::construct_new_menu (QMenu *p)
+void
+main_window::construct_new_menu (QMenu *p)
 {
   QMenu *new_menu = p->addMenu (tr ("New"));
 
@@ -2267,7 +2353,8 @@
                   SLOT (handle_new_figure_request ()), this);
 }
 
-void main_window::construct_edit_menu (QMenuBar *p)
+void
+main_window::construct_edit_menu (QMenuBar *p)
 {
   QMenu *edit_menu = m_add_menu (p, tr ("&Edit"));
 
@@ -2325,7 +2412,7 @@
                             tr ("Preferences..."));
 
   connect (m_find_files_action, &QAction::triggered,
-           this, [=] () { find_files (); });
+           this, [this] () { find_files (); });
 
   connect (m_clear_command_window_action, &QAction::triggered,
            this, &main_window::handle_clear_command_window_request);
@@ -2348,16 +2435,17 @@
 #endif
 
   connect (m_preferences_action, &QAction::triggered,
-           this, [=] () { process_settings_dialog_request (); });
+           this, [this] () { process_settings_dialog_request (); });
 
   connect (m_set_path_action, &QAction::triggered,
            this, &main_window::handle_set_path_dialog_request);
 
 }
 
-QAction * main_window::construct_debug_menu_item (const char *icon,
-                                                  const QString& item,
-                                                  const char *member)
+QAction *
+main_window::construct_debug_menu_item (const char *icon,
+                                        const QString& item,
+                                        const char *member)
 {
   gui_settings settings;
 
@@ -2374,7 +2462,8 @@
   return action;
 }
 
-void main_window::construct_debug_menu (QMenuBar *p)
+void
+main_window::construct_debug_menu (QMenuBar *p)
 {
   m_debug_menu = m_add_menu (p, tr ("De&bug"));
 
@@ -2404,25 +2493,27 @@
                                  SLOT (debug_quit ()));
 }
 
-void main_window::construct_tools_menu (QMenuBar *p)
+void
+main_window::construct_tools_menu (QMenuBar *p)
 {
   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 Profiler Data"), SLOT (profiler_show ()));
+                                tr ("&Show Profiler Data"), SLOT (profiler_show ()));
 }
 
-void main_window::editor_tabs_changed (bool have_tabs, bool is_octave)
+void
+main_window::editor_tabs_changed (bool have_tabs, bool is_octave)
 {
   // Set state of actions which depend on the existence of editor tabs
   m_editor_has_tabs = have_tabs;
@@ -2430,10 +2521,11 @@
   m_debug_step_over->setEnabled (have_tabs && is_octave);
 }
 
-QAction * main_window::construct_window_menu_item (QMenu *p,
-                                                   const QString& item,
-                                                   bool checkable,
-                                                   QWidget *widget)
+QAction *
+main_window::construct_window_menu_item (QMenu *p,
+    const QString& item,
+    bool checkable,
+    QWidget *widget)
 {
   QAction *action = p->addAction (QIcon (), item);
 
@@ -2467,7 +2559,8 @@
   return action;
 }
 
-void main_window::construct_window_menu (QMenuBar *p)
+void
+main_window::construct_window_menu (QMenuBar *p)
 {
   QMenu *window_menu = m_add_menu (p, tr ("&Window"));
 
@@ -2518,7 +2611,7 @@
   window_menu->addSeparator ();
 
   m_previous_dock_action = add_action (window_menu, QIcon (),
-                                         tr ("Previous Widget"), SLOT (go_to_previous_widget ()));
+                                       tr ("Previous Widget"), SLOT (go_to_previous_widget ()));
 
   window_menu->addSeparator ();
 
@@ -2526,7 +2619,8 @@
                                        tr ("Reset Default Window Layout"), SLOT (reset_windows ()));
 }
 
-void main_window::construct_help_menu (QMenuBar *p)
+void
+main_window::construct_help_menu (QMenuBar *p)
 {
   QMenu *help_menu = m_add_menu (p, tr ("&Help"));
 
@@ -2552,7 +2646,8 @@
                                       tr ("About Octave"), SLOT (show_about_octave ()));
 }
 
-void main_window::construct_documentation_menu (QMenu *p)
+void
+main_window::construct_documentation_menu (QMenu *p)
 {
   QMenu *doc_menu = p->addMenu (tr ("Documentation"));
 
@@ -2563,28 +2658,26 @@
                                     tr ("Online"), SLOT (open_online_documentation_page ()));
 }
 
-void main_window::construct_news_menu (QMenuBar *p)
+void
+main_window::construct_news_menu (QMenuBar *p)
 {
   QMenu *news_menu = m_add_menu (p, tr ("&News"));
 
   m_release_notes_action
     = news_menu->addAction (QIcon (), tr ("Release Notes"),
-                            [=] () {
-                              emit show_release_notes_signal ();
-                            });
+                            [this] () { emit show_release_notes_signal (); });
   addAction (m_release_notes_action);
   m_release_notes_action->setShortcutContext (Qt::ApplicationShortcut);
 
   m_current_news_action
     = news_menu->addAction (QIcon (), tr ("Community News"),
-                            [=] () {
-                              emit show_community_news_signal (-1);
-                            });
+                            [this] () { emit show_community_news_signal (-1); });
   addAction (m_current_news_action);
   m_current_news_action->setShortcutContext (Qt::ApplicationShortcut);
 }
 
-void main_window::construct_tool_bar ()
+void
+main_window::construct_tool_bar ()
 {
   m_main_tool_bar = addToolBar (tr ("Toolbar"));
   m_main_tool_bar->setStyleSheet (m_main_tool_bar->styleSheet ()
@@ -2649,7 +2742,8 @@
            this, &main_window::handle_undo_request);
 }
 
-void main_window::focus_console_after_command ()
+void
+main_window::focus_console_after_command ()
 {
   gui_settings settings;
 
@@ -2657,7 +2751,8 @@
     focus_command_window ();
 }
 
-void main_window::configure_shortcuts ()
+void
+main_window::configure_shortcuts ()
 {
   gui_settings settings;
 
@@ -2732,7 +2827,8 @@
   settings.set_shortcut (m_current_news_action, sc_main_news_community_news, enable);
 }
 
-QList<octave_dock_widget *> main_window::dock_widget_list ()
+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));
@@ -2747,7 +2843,8 @@
   return list;
 }
 
-void main_window::update_default_encoding (const QString& default_encoding)
+void
+main_window::update_default_encoding (const QString& default_encoding)
 {
   m_default_encoding = default_encoding;
   std::string mfile_encoding = m_default_encoding.toStdString ();
@@ -2755,7 +2852,7 @@
     mfile_encoding = "SYSTEM";
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([mfile_encoding] (interpreter& interp)
      {
        // INTERPRETER THREAD
 
@@ -2763,7 +2860,8 @@
      });
 }
 
-void main_window::resize_dock (QDockWidget *dw, int width, int height)
+void
+main_window::resize_dock (QDockWidget *dw, int width, int height)
 {
   // resizeDockWidget was added to Qt in Qt 5.6
   if (width >= 0)
@@ -2773,7 +2871,8 @@
 }
 
 // The default main window size relative to the desktop size
-void main_window::set_default_geometry ()
+void
+main_window::set_default_geometry ()
 {
   int win_x, win_y;
   get_screen_geometry (win_x, win_y);
@@ -2782,7 +2881,8 @@
   resize (2*win_x/3, 7*win_y/8);
 }
 
-void main_window::reset_windows ()
+void
+main_window::reset_windows ()
 {
   // Slot for resetting the window layout to the default one
   hide ();
@@ -2799,13 +2899,14 @@
   // connections so that the event loop can do what it needs to do.
   // But I haven't been able to find the magic sequence.
 
-  QTimer::singleShot (250, this, [=] () { do_reset_windows (true, true, true); });
+  QTimer::singleShot (250, this, [this] () { do_reset_windows (true, true, true); });
 }
 
 // Create the default layout of the main window. Do not use
 // restoreState () and restoreGeometry () with default values since
 // this might lead to problems when the Qt version changes
-void main_window::do_reset_windows (bool show, bool save, bool force_all)
+void
+main_window::do_reset_windows (bool show, bool save, bool force_all)
 {
   // Set main window default geometry and store its width for
   // later resizing the command window
--- a/libgui/src/main-window.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/main-window.h	Fri Apr 12 15:10:26 2024 +0200
@@ -159,7 +159,7 @@
                                         = QString ());
   void show_about_octave ();
   void notice_settings (bool update_by_worker = false);
-  QPalette getFusionDarkPalette();
+  QPalette getFusionDarkPalette ();
   void prepare_to_exit ();
   void go_to_previous_widget ();
   void reset_windows ();
@@ -247,7 +247,7 @@
   void disable_menu_shortcuts (bool disable);
   void restore_create_file_setting ();
   void set_file_encoding (const QString& new_encoding);
-  void request_open_files (const QStringList& open_file_names);
+//  void request_open_files (const QStringList& open_file_names);
 
   void warning_function_not_found (const QString& message);
 
--- a/libgui/src/octave-dock-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/octave-dock-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -185,7 +185,7 @@
                   ).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 ((icon_size*2)/3).arg ((icon_size*7)/3);
 }
 
 octave_dock_widget::octave_dock_widget (const QString& obj_name, QWidget *p)
@@ -215,7 +215,7 @@
   connect (this, &octave_dock_widget::queue_make_window,
            this, &octave_dock_widget::make_window, Qt::QueuedConnection);
   connect (this, &octave_dock_widget::queue_make_widget,
-           this, [=] () { make_widget (); }, Qt::QueuedConnection);
+           this, [this] () { make_widget (); }, Qt::QueuedConnection);
 
   gui_settings settings;
 
@@ -513,6 +513,7 @@
   QRect default_floating_size = QRect (x+16, y+32, w/3, h/2);
 
   QRect default_dock_size;
+  QString key_ext;
   if (m_main_window)
     {
       // We have a main window, dock size depends on size of main window
@@ -523,11 +524,12 @@
     {
       // No main window, default dock size should never be used
       default_dock_size = QRect (0, 0, w/10, h/10);
+      key_ext = settings_no_mainwin;
     }
 
   m_recent_float_geom
-    = settings.value (dw_float_geometry.settings_key ().arg (objectName ()),
-                       default_floating_size).toRect ();
+    = settings.value (dw_float_geometry.settings_key ().arg (objectName ()) + key_ext,
+                      default_floating_size).toRect ();
 
   adjust_to_screen (m_recent_float_geom, default_floating_size);
 
@@ -535,7 +537,7 @@
   // saveGeomety to new QRect setting (see comment for restoring size
   // of docked widgets)
   QVariant dock_geom
-    = settings.value (dw_dock_geometry.settings_key ().arg (objectName ()),
+    = settings.value (dw_dock_geometry.settings_key ().arg (objectName ()) + key_ext,
                       default_dock_size);
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
   if (dock_geom.canConvert (QMetaType (QMetaType::QRect)))
@@ -588,20 +590,25 @@
 
   store_geometry ();
 
+  QString key_ext;
+  if (! m_main_window)
+    key_ext = settings_no_mainwin;
+
   // conditional needed?
   if (! m_recent_float_geom.isNull ())
-    settings.setValue (dw_float_geometry.settings_key ().arg (name), m_recent_float_geom);
+    settings.setValue (dw_float_geometry.settings_key ().arg (name) + key_ext, m_recent_float_geom);
 
   if (! m_recent_dock_geom.isEmpty ())
-    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.setValue (dw_dock_geometry.settings_key ().arg (name) + key_ext, m_recent_dock_geom);
+  settings.setValue (dw_is_visible.settings_key ().arg (name) + key_ext, isVisible ()); // store visibility
+  settings.setValue (dw_is_floating.settings_key ().arg (name) + key_ext, isFloating ()); // store floating
+  settings.setValue (dw_is_minimized.settings_key ().arg (name) + key_ext, isMinimized ()); // store minimized
 
   settings.sync ();
 }
 
-bool octave_dock_widget::eventFilter (QObject *obj, QEvent *e)
+bool
+octave_dock_widget::eventFilter (QObject *obj, QEvent *e)
 {
   // Ignore double clicks into window decoration elements
   if (e->type () == QEvent::NonClientAreaMouseButtonDblClick)
@@ -657,7 +664,8 @@
   emit active_changed (false);
 }
 
-void octave_dock_widget::activate ()
+void
+octave_dock_widget::activate ()
 {
   if (! isVisible ())
     setVisible (true);
@@ -667,7 +675,8 @@
   raise ();
 }
 
-void octave_dock_widget::handle_visibility (bool visible)
+void
+octave_dock_widget::handle_visibility (bool visible)
 {
   if (visible)
     {
--- a/libgui/src/octave-qobject.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/octave-qobject.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -75,7 +75,8 @@
 
 // Bug #55940 (Disable App Nap on Mac)
 #if defined (Q_OS_MAC)
-static void disable_app_nap ()
+static void
+disable_app_nap ()
 {
   Class process_info_class;
   SEL process_info_selector;
@@ -141,7 +142,8 @@
 //! Reimplement QApplication::notify.  Octave's own exceptions are
 //! caught and rethrown in the interpreter thread.
 
-bool octave_qapplication::notify (QObject *receiver, QEvent *ev)
+bool
+octave_qapplication::notify (QObject *receiver, QEvent *ev)
 {
   try
     {
@@ -150,7 +152,7 @@
   catch (execution_exception& ee)
     {
       emit interpreter_event
-        ([=] ()
+        ([ee] ()
          {
            // INTERPRETER THREAD
            throw ee;
@@ -237,11 +239,11 @@
   // Handle any interpreter_event signal from the octave_qapplication
   // object here.
 
-  connect (m_qapplication, QOverload<const fcn_callback&>::of (&octave_qapplication::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&base_qobject::interpreter_event));
+  connect (m_qapplication, qOverload<const fcn_callback&> (&octave_qapplication::interpreter_event),
+           this, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));
 
-  connect (m_qapplication, QOverload<const meth_callback&>::of (&octave_qapplication::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&base_qobject::interpreter_event));
+  connect (m_qapplication, qOverload<const meth_callback&> (&octave_qapplication::interpreter_event),
+           this, qOverload<const meth_callback&> (&base_qobject::interpreter_event));
 
   if (m_app_context.experimental_terminal_widget ())
     {
@@ -386,7 +388,8 @@
   string_vector::delete_c_str_vec (m_argv);
 }
 
-void base_qobject::config_translators ()
+void
+base_qobject::config_translators ()
 {
   if (m_translators_installed)
     return;
@@ -402,7 +405,8 @@
   m_translators_installed = true;
 }
 
-void base_qobject::start_main_thread ()
+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
@@ -422,7 +426,8 @@
   m_main_thread->start ();
 }
 
-int base_qobject::exec ()
+int
+base_qobject::exec ()
 {
   int status = m_qapplication->exec ();
 
@@ -439,12 +444,14 @@
 
 // Provided for convenience.  Will be removed once we eliminate the
 // old terminal widget.
-bool base_qobject::experimental_terminal_widget () const
+bool
+base_qobject::experimental_terminal_widget () const
 {
   return m_app_context.experimental_terminal_widget ();
 }
 
-bool base_qobject::gui_running () const
+bool
+base_qobject::gui_running () const
 {
   return m_app_context.gui_running ();
 }
@@ -577,7 +584,7 @@
                m_history_widget, &history_dock_widget::clear_history);
 
       emit interpreter_event
-        ([=] (interpreter& interp) {
+        ([] (interpreter& interp) {
           // INTERPRETER THREAD
 
           event_manager& xevmgr = interp.get_event_manager ();
@@ -615,9 +622,9 @@
 
       connect (m_workspace_widget,
                &workspace_view::copy_variable_value_to_clipboard,
-               [=] (const QString& var_name) {
+               [this] (const QString& var_name) {
                  emit interpreter_event
-                   ([=] (interpreter& interp)
+                   ([var_name] (interpreter& interp)
                     {
                       // INTERPRETER THREAD
 
@@ -638,9 +645,9 @@
                });
 
       connect (m_workspace_widget, &workspace_view::rename_variable_signal,
-               [=] (const QString& old_name, const QString& new_name) {
+               [this] (const QString& old_name, const QString& new_name) {
                  emit interpreter_event
-                   ([=] (interpreter& interp) {
+                   ([old_name, new_name] (interpreter& interp) {
                      // INTERPRETER THREAD
 
                      symbol_scope scope = interp.get_current_scope ();
@@ -663,9 +670,9 @@
                });
 
       connect (m_workspace_widget, &workspace_view::edit_variable_signal,
-               [=] (const QString& var_name) {
+               [this] (const QString& var_name) {
                  emit interpreter_event
-                   ([=] (interpreter& interp) {
+                   ([var_name] (interpreter& interp) {
                      // INTERPRETER THREAD
 
                      std::string name = var_name.toStdString ();
@@ -678,7 +685,7 @@
                });
 
       emit interpreter_event
-        ([=] (interpreter& interp) {
+        ([] (interpreter& interp) {
           // INTERPRETER THREAD
 
           event_manager& xevmgr = interp.get_event_manager ();
@@ -725,7 +732,8 @@
   return m_variable_editor_widget;
 }
 
-QPointer<community_news> base_qobject::community_news_widget (int serial)
+QPointer<community_news>
+base_qobject::community_news_widget (int serial)
 {
   if (! m_community_news)
     m_community_news
@@ -734,7 +742,8 @@
   return m_community_news;
 }
 
-QPointer<release_notes> base_qobject::release_notes_widget ()
+QPointer<release_notes>
+base_qobject::release_notes_widget ()
 {
   if (! m_release_notes)
     m_release_notes = QPointer<release_notes> (new release_notes ());
@@ -742,7 +751,8 @@
   return m_release_notes;
 }
 
-bool base_qobject::confirm_shutdown ()
+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
@@ -751,7 +761,8 @@
   return m_main_window ? m_main_window->confirm_shutdown () : true;
 }
 
-void base_qobject::start_gui (bool gui_app)
+void
+base_qobject::start_gui (bool gui_app)
 {
   if (m_app_context.experimental_terminal_widget ())
     {
@@ -795,7 +806,8 @@
     }
 }
 
-void base_qobject::show_terminal_window ()
+void
+base_qobject::show_terminal_window ()
 {
   terminal_dock_widget *widget
     = (m_terminal_widget
@@ -808,7 +820,8 @@
     }
 }
 
-void base_qobject::show_documentation_window (const QString& file)
+void
+base_qobject::show_documentation_window (const QString& file)
 {
   documentation_dock_widget *widget
     = (m_documentation_widget
@@ -823,7 +836,8 @@
     }
 }
 
-void base_qobject::show_file_browser_window ()
+void
+base_qobject::show_file_browser_window ()
 {
   files_dock_widget *widget
     = m_file_browser_widget ? m_file_browser_widget : file_browser_widget ();
@@ -835,7 +849,8 @@
     }
 }
 
-void base_qobject::show_command_history_window ()
+void
+base_qobject::show_command_history_window ()
 {
   history_dock_widget *widget
     = m_history_widget ? m_history_widget : history_widget ();
@@ -847,7 +862,8 @@
     }
 }
 
-void base_qobject::show_workspace_window ()
+void
+base_qobject::show_workspace_window ()
 {
   workspace_view *widget
     = m_workspace_widget ? m_workspace_widget : workspace_widget ();
@@ -859,8 +875,9 @@
     }
 }
 
-void base_qobject::show_variable_editor_window (const QString& name,
-                                                const octave_value& value)
+void
+base_qobject::show_variable_editor_window (const QString& name,
+    const octave_value& value)
 {
   variable_editor *widget
     = (m_variable_editor_widget
@@ -876,7 +893,8 @@
   widget->edit_variable (name, value);
 }
 
-void base_qobject::handle_variable_editor_update ()
+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
@@ -896,7 +914,8 @@
      });
 }
 
-void base_qobject::show_community_news (int serial)
+void
+base_qobject::show_community_news (int serial)
 {
   // Ensure widget exists.
   community_news_widget (serial);
@@ -904,7 +923,8 @@
   m_community_news->display ();
 }
 
-void base_qobject::show_release_notes ()
+void
+base_qobject::show_release_notes ()
 {
   // Ensure widget exists.
   release_notes_widget ();
@@ -912,10 +932,11 @@
   m_release_notes->display ();
 }
 
-void base_qobject::execute_command (const QString& command)
+void
+base_qobject::execute_command (const QString& command)
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([command] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -930,7 +951,8 @@
     });
 }
 
-void base_qobject::close_gui ()
+void
+base_qobject::close_gui ()
 {
   if (m_app_context.experimental_terminal_widget ())
     {
@@ -941,7 +963,7 @@
       // returning to the command line?
 
       interpreter_event
-        ([=] (interpreter& interp)
+        ([] (interpreter& interp)
         {
           // INTERPRETER THREAD
 
@@ -957,12 +979,14 @@
     }
 }
 
-void base_qobject::interpreter_ready ()
+void
+base_qobject::interpreter_ready ()
 {
   m_interpreter_ready = true;
 }
 
-void base_qobject::interpreter_event (const fcn_callback& fcn)
+void
+base_qobject::interpreter_event (const fcn_callback& fcn)
 {
   // The following is a direct function call across threads.  It works
   // because it is accessing a thread-safe queue of events that
@@ -974,7 +998,8 @@
   m_interpreter_qobj->interpreter_event (fcn);
 }
 
-void base_qobject::interpreter_event (const meth_callback& meth)
+void
+base_qobject::interpreter_event (const meth_callback& meth)
 {
   // The following is a direct function call across threads.  It works
   // because it is accessing a thread-safe queue of events that
@@ -986,7 +1011,8 @@
   m_interpreter_qobj->interpreter_event (meth);
 }
 
-void base_qobject::interpreter_interrupt ()
+void
+base_qobject::interpreter_interrupt ()
 {
   m_interpreter_qobj->interrupt ();
 }
@@ -994,26 +1020,30 @@
 // 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
+base_qobject::interpreter_pause ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->pause ();
 }
 
-void base_qobject::interpreter_stop ()
+void
+base_qobject::interpreter_stop ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->stop ();
 }
 
-void base_qobject::interpreter_resume ()
+void
+base_qobject::interpreter_resume ()
 {
   if (m_app_context.experimental_terminal_widget ())
     m_interpreter_qobj->resume ();
 }
 
-void base_qobject::copy_image_to_clipboard (const QString& file,
-                                            bool remove_file)
+void
+base_qobject::copy_image_to_clipboard (const QString& file,
+                                       bool remove_file)
 {
   QClipboard *clipboard = QApplication::clipboard ();
 
--- a/libgui/src/octave-qobject.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/octave-qobject.h	Fri Apr 12 15:10:26 2024 +0200
@@ -194,11 +194,11 @@
 
   template <typename T> void connect_interpreter_events (T *widget)
   {
-    connect (widget, QOverload<const fcn_callback&>::of (&T::interpreter_event),
-             this, QOverload<const fcn_callback&>::of (&base_qobject::interpreter_event));
+    connect (widget, qOverload<const fcn_callback&> (&T::interpreter_event),
+             this, qOverload<const fcn_callback&> (&base_qobject::interpreter_event));
 
-    connect (widget, QOverload<const meth_callback&>::of (&T::interpreter_event),
-             this, QOverload<const meth_callback&>::of (&base_qobject::interpreter_event));
+    connect (widget, qOverload<const meth_callback&> (&T::interpreter_event),
+             this, qOverload<const meth_callback&> (&base_qobject::interpreter_event));
   }
 
 public slots:
--- a/libgui/src/qt-application.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/qt-application.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -78,7 +78,8 @@
   sysdep_init ();
 }
 
-bool qt_application::start_gui_p () 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.
@@ -86,7 +87,8 @@
   return experimental_terminal_widget () ? false : m_options.gui ();
 }
 
-int qt_application::execute ()
+int
+qt_application::execute ()
 {
   octave_block_interrupt_signal ();
 
--- a/libgui/src/qt-interpreter-events.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/qt-interpreter-events.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -133,13 +133,15 @@
            this, &qt_interpreter_events::gui_preference_slot);
 }
 
-void qt_interpreter_events::start_gui (bool gui_app)
+void
+qt_interpreter_events::start_gui (bool gui_app)
 {
   if (m_octave_qobj.experimental_terminal_widget ())
     emit start_gui_signal (gui_app);
 }
 
-void qt_interpreter_events::close_gui ()
+void
+qt_interpreter_events::close_gui ()
 {
   if (m_octave_qobj.experimental_terminal_widget ())
     emit close_gui_signal ();
@@ -246,72 +248,85 @@
   return answer.toStdString ();
 }
 
-void qt_interpreter_events::update_path_dialog ()
+void
+qt_interpreter_events::update_path_dialog ()
 {
   emit update_path_dialog_signal ();
 }
 
-void qt_interpreter_events::show_preferences ()
+void
+qt_interpreter_events::show_preferences ()
 {
   emit show_preferences_signal ();
 }
 
-void qt_interpreter_events::apply_preferences ()
+void
+qt_interpreter_events::apply_preferences ()
 {
   emit apply_new_settings ();
 }
 
-void qt_interpreter_events::show_terminal_window ()
+void
+qt_interpreter_events::show_terminal_window ()
 {
   emit show_terminal_window_signal ();
 }
 
-bool qt_interpreter_events::show_documentation (const std::string& file)
+bool
+qt_interpreter_events::show_documentation (const std::string& file)
 {
   emit show_documentation_signal (QString::fromStdString (file));
 
   return true;
 }
 
-void qt_interpreter_events::show_file_browser ()
+void
+qt_interpreter_events::show_file_browser ()
 {
   emit show_file_browser_signal ();
 }
 
-void qt_interpreter_events::show_command_history ()
+void
+qt_interpreter_events::show_command_history ()
 {
   emit show_command_history_signal ();
 }
 
-void qt_interpreter_events::show_workspace ()
+void
+qt_interpreter_events::show_workspace ()
 {
   emit show_workspace_signal ();
 }
 
-void qt_interpreter_events::show_community_news (int serial)
+void
+qt_interpreter_events::show_community_news (int serial)
 {
   emit show_community_news_signal (serial);
 }
 
-void qt_interpreter_events::show_release_notes ()
+void
+qt_interpreter_events::show_release_notes ()
 {
   emit show_release_notes_signal ();
 }
 
-bool qt_interpreter_events::edit_file (const std::string& file)
+bool
+qt_interpreter_events::edit_file (const std::string& file)
 {
   emit edit_file_signal (QString::fromStdString (file));
 
   return true;
 }
 
-void qt_interpreter_events::edit_variable (const std::string& expr,
-                                           const octave_value& val)
+void
+qt_interpreter_events::edit_variable (const std::string& expr,
+                                      const octave_value& val)
 {
   emit edit_variable_signal (QString::fromStdString (expr), val);
 }
 
-bool qt_interpreter_events::confirm_shutdown ()
+bool
+qt_interpreter_events::confirm_shutdown ()
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -323,7 +338,8 @@
   return m_result.toBool ();
 }
 
-bool qt_interpreter_events::prompt_new_edit_file (const std::string& file)
+bool
+qt_interpreter_events::prompt_new_edit_file (const std::string& file)
 {
   gui_settings settings;
 
@@ -392,7 +408,8 @@
   return retval;
 }
 
-uint8NDArray qt_interpreter_events::get_named_icon (const std::string& name)
+uint8NDArray
+qt_interpreter_events::get_named_icon (const std::string& name)
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -435,7 +452,8 @@
   return retval;
 }
 
-void qt_interpreter_events::get_named_icon_slot (const QString& name)
+void
+qt_interpreter_events::get_named_icon_slot (const QString& name)
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -466,14 +484,16 @@
   return pref.toStdString ();
 }
 
-bool qt_interpreter_events::copy_image_to_clipboard (const std::string& file)
+bool
+qt_interpreter_events::copy_image_to_clipboard (const std::string& file)
 {
   emit copy_image_to_clipboard_signal (QString::fromStdString (file), true);
 
   return true;
 }
 
-void qt_interpreter_events::focus_window (const std::string win_name)
+void
+qt_interpreter_events::focus_window (const std::string win_name)
 {
   emit focus_window_signal (QString::fromStdString (win_name));
 }
@@ -484,17 +504,20 @@
   emit execute_command_in_terminal_signal (QString::fromStdString (command));
 }
 
-void qt_interpreter_events::register_documentation (const std::string& file)
+void
+qt_interpreter_events::register_documentation (const std::string& file)
 {
   emit register_documentation_signal (QString::fromStdString (file));
 }
 
-void qt_interpreter_events::unregister_documentation (const std::string& file)
+void
+qt_interpreter_events::unregister_documentation (const std::string& file)
 {
   emit unregister_documentation_signal (QString::fromStdString (file));
 }
 
-void qt_interpreter_events::interpreter_output (const std::string& msg)
+void
+qt_interpreter_events::interpreter_output (const std::string& msg)
 {
   if (m_octave_qobj.experimental_terminal_widget ()
       && m_octave_qobj.have_terminal_window ())
@@ -506,8 +529,9 @@
     }
 }
 
-void qt_interpreter_events::display_exception (const execution_exception& ee,
-                                               bool beep)
+void
+qt_interpreter_events::display_exception (const execution_exception& ee,
+    bool beep)
 {
   if (m_octave_qobj.experimental_terminal_widget ()
       && m_octave_qobj.have_terminal_window ())
@@ -528,25 +552,29 @@
     }
 }
 
-void qt_interpreter_events::gui_status_update (const std::string& feature,
-                                               const std::string& status)
+void
+qt_interpreter_events::gui_status_update (const std::string& feature,
+    const std::string& status)
 {
   emit gui_status_update_signal (QString::fromStdString (feature),
                                  QString::fromStdString (status));
 }
 
-void qt_interpreter_events::update_gui_lexer ()
+void
+qt_interpreter_events::update_gui_lexer ()
 {
   emit update_gui_lexer_signal (true);
 }
 
-void qt_interpreter_events::directory_changed (const std::string& dir)
+void
+qt_interpreter_events::directory_changed (const std::string& dir)
 {
   emit directory_changed_signal (QString::fromStdString (dir));
 }
 
-void qt_interpreter_events::file_remove (const std::string& old_name,
-                                         const std::string& new_name)
+void
+qt_interpreter_events::file_remove (const std::string& old_name,
+                                    const std::string& new_name)
 {
   QMutexLocker autolock (&m_mutex);
 
@@ -558,14 +586,16 @@
   wait ();
 }
 
-void qt_interpreter_events::file_renamed (bool load_new)
+void
+qt_interpreter_events::file_renamed (bool load_new)
 {
   emit file_renamed_signal (load_new);
 }
 
-void qt_interpreter_events::set_workspace (bool top_level, bool debug,
-                                           const symbol_info_list& syminfo,
-                                           bool update_variable_editor)
+void
+qt_interpreter_events::set_workspace (bool top_level, bool debug,
+                                      const symbol_info_list& syminfo,
+                                      bool update_variable_editor)
 {
   if (! top_level && ! debug)
     return;
@@ -576,17 +606,20 @@
     emit refresh_variable_editor_signal ();
 }
 
-void qt_interpreter_events::clear_workspace ()
+void
+qt_interpreter_events::clear_workspace ()
 {
   emit clear_workspace_signal ();
 }
 
-void qt_interpreter_events::update_prompt (const std::string& prompt)
+void
+qt_interpreter_events::update_prompt (const std::string& prompt)
 {
   emit update_prompt_signal (QString::fromStdString (prompt));
 }
 
-void qt_interpreter_events::set_history (const string_vector& hist)
+void
+qt_interpreter_events::set_history (const string_vector& hist)
 {
   QStringList qt_hist;
 
@@ -596,25 +629,30 @@
   emit set_history_signal (qt_hist);
 }
 
-void qt_interpreter_events::append_history (const std::string& hist_entry)
+void
+qt_interpreter_events::append_history (const std::string& hist_entry)
 {
   emit append_history_signal (QString::fromStdString (hist_entry));
 }
 
-void qt_interpreter_events::clear_history ()
+void
+qt_interpreter_events::clear_history ()
 {
   emit clear_history_signal ();
 }
 
-void qt_interpreter_events::pre_input_event ()
+void
+qt_interpreter_events::pre_input_event ()
 { }
 
-void qt_interpreter_events::post_input_event ()
+void
+qt_interpreter_events::post_input_event ()
 { }
 
-void qt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/,
-                                                  const std::string& fcn_file_name,
-                                                  int line)
+void
+qt_interpreter_events::enter_debugger_event (const std::string& /*fcn_name*/,
+    const std::string& fcn_file_name,
+    int line)
 {
   if (fcn_file_name.empty ())
     return;
@@ -631,7 +669,8 @@
   delete_debugger_pointer (file, line);
 }
 
-void qt_interpreter_events::exit_debugger_event ()
+void
+qt_interpreter_events::exit_debugger_event ()
 {
   emit exit_debugger_signal ();
 }
@@ -639,10 +678,11 @@
 //! Display (if @c insert true) or remove the appropriate symbol for a
 //! breakpoint in @c file at @c line with condition @c cond.
 
-void qt_interpreter_events::update_breakpoint (bool insert,
-                                               const std::string& file,
-                                               int line,
-                                               const std::string& cond)
+void
+qt_interpreter_events::update_breakpoint (bool insert,
+                                          const std::string& file,
+                                          int line,
+                                          const std::string& cond)
 {
   emit update_breakpoint_marker_signal (insert, QString::fromStdString (file),
                                         line, QString::fromStdString (cond));
--- a/libgui/src/release-notes.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/release-notes.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -106,7 +106,8 @@
   move (20, 20);  // move to the top left corner
 }
 
-void release_notes::display ()
+void
+release_notes::display ()
 {
   if (! isVisible ())
     show ();
--- a/libgui/src/set-path-dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/set-path-dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -120,11 +120,11 @@
   // Any interpreter_event signal from a set_path_model object is
   // handled the same as for the parent set_path_dialog object.
 
-  connect (model, QOverload<const fcn_callback&>::of (&set_path_model::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&set_path_dialog::interpreter_event));
+  connect (model, qOverload<const fcn_callback&> (&set_path_model::interpreter_event),
+           this, qOverload<const fcn_callback&> (&set_path_dialog::interpreter_event));
 
-  connect (model, QOverload<const meth_callback&>::of (&set_path_model::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&set_path_dialog::interpreter_event));
+  connect (model, qOverload<const meth_callback&> (&set_path_model::interpreter_event),
+           this, qOverload<const meth_callback&> (&set_path_dialog::interpreter_event));
 
   m_path_list = new QListView (this);
   m_path_list->setWordWrap (false);
@@ -132,7 +132,7 @@
   m_path_list->setSelectionBehavior (QAbstractItemView::SelectRows);
   m_path_list->setSelectionMode (QAbstractItemView::ExtendedSelection);
   m_path_list->setAlternatingRowColors (true);
-  m_path_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+  m_path_list->setSizePolicy (QSizePolicy::Expanding, QSizePolicy::Expanding);
 
   // layout everything
   QDialogButtonBox *button_box = new QDialogButtonBox (Qt::Horizontal);
@@ -157,8 +157,8 @@
 
   // main layout
   QHBoxLayout *main_hboxlayout = new QHBoxLayout;
-  main_hboxlayout->addWidget(path_edit_layout);
-  main_hboxlayout->addWidget(m_path_list);
+  main_hboxlayout->addWidget (path_edit_layout);
+  main_hboxlayout->addWidget (m_path_list);
 
   QGridLayout *main_layout = new QGridLayout;
   main_layout->addWidget (m_info_label, 0, 0);
@@ -169,16 +169,18 @@
 
   gui_settings settings;
 
-  restoreGeometry (settings.value(pd_geometry.settings_key ()).toByteArray());
+  restoreGeometry (settings.value (pd_geometry.settings_key ()).toByteArray ());
 }
 
-void set_path_dialog::update_model ()
+void
+set_path_dialog::update_model ()
 {
   set_path_model *m = static_cast<set_path_model *> (m_path_list->model ());
   m->path_to_model ();
 }
 
-void set_path_dialog::add_dir_common (bool subdirs)
+void
+set_path_dialog::add_dir_common (bool subdirs)
 {
   QString dir
     = QFileDialog::getExistingDirectory (this, tr ("Open Directory"),
@@ -203,31 +205,35 @@
     }
 }
 
-void set_path_dialog::add_dir()
+void
+set_path_dialog::add_dir ()
 {
   add_dir_common (false);
 }
 
-void set_path_dialog::add_dir_subdirs ()
+void
+set_path_dialog::add_dir_subdirs ()
 {
   add_dir_common (true);
 }
 
-void set_path_dialog::rm_dir ()
+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 ();
-  QModelIndexList indexlist = selmodel->selectedIndexes();
+  QModelIndexList indexlist = selmodel->selectedIndexes ();
   m->rm_dir (indexlist);
 
   selmodel->clearSelection ();
 }
 
-void set_path_dialog::move_dir_up ()
+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 ();
-  QModelIndexList indexlist = selmodel->selectedIndexes();
+  QModelIndexList indexlist = selmodel->selectedIndexes ();
   m->move_dir_up (indexlist);
 
   // Update selection and view
@@ -243,11 +249,12 @@
   m_path_list->scrollTo (m->index (min_row));
 }
 
-void set_path_dialog::move_dir_down ()
+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 ();
-  QModelIndexList indexlist = selmodel->selectedIndexes();
+  QModelIndexList indexlist = selmodel->selectedIndexes ();
   m->move_dir_down (indexlist);
 
   // Update selection and view
@@ -263,11 +270,12 @@
   m_path_list->scrollTo (m->index (max_row));
 }
 
-void set_path_dialog::move_dir_top ()
+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 ();
-  QModelIndexList indexlist = selmodel->selectedIndexes();
+  QModelIndexList indexlist = selmodel->selectedIndexes ();
   m->move_dir_top (indexlist);
 
   // Update selection and view
@@ -278,11 +286,12 @@
   m_path_list->scrollTo (m->index (0));
 }
 
-void set_path_dialog::move_dir_bottom ()
+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 ();
-  QModelIndexList indexlist = selmodel->selectedIndexes();
+  QModelIndexList indexlist = selmodel->selectedIndexes ();
   m->move_dir_bottom (indexlist);
 
   // Update selection and view
@@ -295,14 +304,16 @@
   m_path_list->scrollTo (m->index (row_count - 1));
 }
 
-void set_path_dialog::save_settings ()
+void
+set_path_dialog::save_settings ()
 {
   gui_settings settings;
 
   settings.setValue (pd_geometry.settings_key (), saveGeometry ());
 }
 
-void set_path_dialog::closeEvent (QCloseEvent *e)
+void
+set_path_dialog::closeEvent (QCloseEvent *e)
 {
   save_settings ();
 
--- a/libgui/src/set-path-model.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/set-path-model.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,7 +46,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 set_path_model::set_path_model (QObject *p)
-: QAbstractListModel (p)
+  : QAbstractListModel (p)
 {
   connect (this, &set_path_model::update_data_signal,
            this, &set_path_model::update_data);
@@ -54,7 +54,8 @@
   m_revertible = false;
 }
 
-std::string set_path_model::to_string ()
+std::string
+set_path_model::to_string ()
 {
   std::string path_sep = directory_path::path_sep_str ();
 
@@ -73,12 +74,13 @@
   return path_str;
 }
 
-void set_path_model::model_to_path ()
+void
+set_path_model::model_to_path ()
 {
   std::string path_str = to_string ();
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([path_str] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -88,7 +90,8 @@
     });
 }
 
-void set_path_model::clear ()
+void
+set_path_model::clear ()
 {
   beginResetModel ();
 
@@ -97,7 +100,8 @@
   endResetModel ();
 }
 
-void set_path_model::save ()
+void
+set_path_model::save ()
 {
   model_to_path ();
 
@@ -110,7 +114,8 @@
     });
 }
 
-void set_path_model::revert ()
+void
+set_path_model::revert ()
 {
   clear ();
 
@@ -121,7 +126,8 @@
   model_to_path ();
 }
 
-void set_path_model::revert_last ()
+void
+set_path_model::revert_last ()
 {
   clear ();
 
@@ -132,13 +138,14 @@
   model_to_path ();
 }
 
-void set_path_model::add_dir (const QString& p)
+void
+set_path_model::add_dir (const QString& p)
 {
   m_last_dirs = m_dirs;
 
   beginInsertRows (QModelIndex (), m_dirs.size (), m_dirs.size ());
 
-  QList<QString>::Iterator it = m_dirs.begin();
+  QList<QString>::Iterator it = m_dirs.begin ();
 
   m_dirs.insert (it, p);
 
@@ -147,7 +154,8 @@
   model_to_path ();
 }
 
-void set_path_model::rm_dir (const QModelIndexList& indices)
+void
+set_path_model::rm_dir (const QModelIndexList& indices)
 {
   m_last_dirs = m_dirs;
 
@@ -163,7 +171,8 @@
   model_to_path ();
 }
 
-void set_path_model::move_dir_up (const QModelIndexList& indices)
+void
+set_path_model::move_dir_up (const QModelIndexList& indices)
 {
   m_last_dirs = m_dirs;
 
@@ -185,7 +194,8 @@
   model_to_path ();
 }
 
-void set_path_model::move_dir_down (const QModelIndexList& indices)
+void
+set_path_model::move_dir_down (const QModelIndexList& indices)
 {
   m_last_dirs = m_dirs;
 
@@ -208,7 +218,8 @@
   model_to_path ();
 }
 
-void set_path_model::move_dir_top (const QModelIndexList& indices)
+void
+set_path_model::move_dir_top (const QModelIndexList& indices)
 {
   m_last_dirs = m_dirs;
 
@@ -229,7 +240,8 @@
   model_to_path ();
 }
 
-void set_path_model::move_dir_bottom (const QModelIndexList& indices)
+void
+set_path_model::move_dir_bottom (const QModelIndexList& indices)
 {
   m_last_dirs = m_dirs;
 
@@ -252,12 +264,14 @@
   model_to_path ();
 }
 
-int set_path_model::rowCount (const QModelIndex&) const
+int
+set_path_model::rowCount (const QModelIndex&) const
 {
   return m_dirs.size ();
 }
 
-QVariant set_path_model::data (const QModelIndex& idx, int role) const
+QVariant
+set_path_model::data (const QModelIndex& idx, int role) const
 {
   QVariant retval;
   if (idx.isValid ())
@@ -281,7 +295,8 @@
   return retval;
 }
 
-void set_path_model::path_to_model ()
+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
@@ -290,7 +305,7 @@
   QPointer<set_path_model> this_spm (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_spm] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -315,7 +330,8 @@
   m_revertible = false;
 }
 
-void set_path_model::update_data (const QStringList& dirs)
+void
+set_path_model::update_data (const QStringList& dirs)
 {
   m_dirs = dirs;
 
--- a/libgui/src/settings-dialog.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/settings-dialog.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -78,7 +78,7 @@
   setupUi (this);
 
   QMessageBox *info = wait_message_box (
-                      tr ("Loading current preferences ... "), this);
+                        tr ("Loading current preferences ... "), this);
 
   read_settings (true);  // it's the first read, prepare everything
 
@@ -105,7 +105,8 @@
   show ();
 }
 
-void settings_dialog::read_settings (bool first)
+void
+settings_dialog::read_settings (bool first)
 {
   gui_settings settings;
 
@@ -137,7 +138,7 @@
   if (first)
     {
       // Global style
-      QStringList styles = QStyleFactory::keys();
+      QStringList styles = QStyleFactory::keys ();
       styles.append (global_extra_styles);
       combo_styles->addItems (styles);
       combo_styles->insertItem (0, global_style.def ().toString ());
@@ -343,10 +344,10 @@
                    m_rb_uncomment_strings[i], &QCheckBox::setDisabled);
         }
 
-      m_rb_comment_strings[i]->setText (ed_comment_strings.at(i));
+      m_rb_comment_strings[i]->setText (ed_comment_strings.at (i));
       m_rb_comment_strings[i]->setChecked (i == selected_comment_string);
 
-      m_rb_uncomment_strings[i]->setText (ed_comment_strings.at(i));
+      m_rb_uncomment_strings[i]->setText (ed_comment_strings.at (i));
       m_rb_uncomment_strings[i]->setAutoExclusive (false);
       m_rb_uncomment_strings[i]->setChecked ( 1 << i & selected_uncomment_string);
     }
@@ -436,7 +437,7 @@
     {
       proxy_type->addItems (global_proxy_all_types);
       // Connect relevant signals for dis-/enabling some elements
-      connect (proxy_type, QOverload<int>::of (&QComboBox::currentIndexChanged),
+      connect (proxy_type, qOverload<int> (&QComboBox::currentIndexChanged),
                this, &settings_dialog::proxy_items_update);
       connect (use_proxy_server, &QCheckBox::toggled,
                this, &settings_dialog::proxy_items_update);
@@ -490,7 +491,7 @@
   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 ()));
+                                       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 ());
@@ -559,7 +560,7 @@
       current_line_color->setObjectName (ed_highlight_current_line_color.settings_key ());
 
       QLabel *current_line_color_label
-        = new QLabel(tr ("Color of highlighted current line (magenta (255,0,255) for automatic color)"));
+        = 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);
@@ -578,7 +579,7 @@
       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); });
+               [this] () { update_editor_lexers (settings_reload_default_colors_flag); });
 
       // finally read the lexer colors using the update slot
       update_editor_lexers ();
@@ -603,7 +604,8 @@
 #endif
 }
 
-void settings_dialog::show_tab (const QString& tab)
+void
+settings_dialog::show_tab (const QString& tab)
 {
   gui_settings settings;
 
@@ -620,17 +622,20 @@
     }
 }
 
-void settings_dialog::get_octave_dir ()
+void
+settings_dialog::get_octave_dir ()
 {
   get_dir (le_octave_dir, tr ("Set Octave Startup Directory"));
 }
 
-void settings_dialog::get_file_browser_dir ()
+void
+settings_dialog::get_file_browser_dir ()
 {
   get_dir (le_file_browser_dir, tr ("Set File Browser Startup Directory"));
 }
 
-void settings_dialog::get_dir (QLineEdit *line_edit, const QString& title)
+void
+settings_dialog::get_dir (QLineEdit *line_edit, const QString& title)
 {
   // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved.
   int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks;
@@ -646,7 +651,8 @@
   line_edit->setText (dir);
 }
 
-void settings_dialog::button_clicked (QAbstractButton *button)
+void
+settings_dialog::button_clicked (QAbstractButton *button)
 {
   QDialogButtonBox::ButtonRole button_role = button_box->buttonRole (button);
 
@@ -682,7 +688,8 @@
     }
 }
 
-void settings_dialog::set_disabled_pref_file_browser_dir (bool disable)
+void
+settings_dialog::set_disabled_pref_file_browser_dir (bool disable)
 {
   cb_restore_file_browser_dir->setDisabled (disable);
 
@@ -699,7 +706,8 @@
 }
 
 // slot for updating enabled state of proxy settings
-void settings_dialog::proxy_items_update ()
+void
+settings_dialog::proxy_items_update ()
 {
   bool use_proxy = use_proxy_server->isChecked ();
 
@@ -731,7 +739,8 @@
 // gui_settings_object so that the user may choose to apply or cancel
 // the action.
 
-void settings_dialog::import_shortcut_set ()
+void
+settings_dialog::import_shortcut_set ()
 {
   if (! overwrite_all_shortcuts ())
     return;
@@ -755,7 +764,8 @@
 // choice to save current application settings or the modified values
 // in the dialog?
 
-void settings_dialog::export_shortcut_set ()
+void
+settings_dialog::export_shortcut_set ()
 {
   QString file = get_shortcuts_file_name (OSC_EXPORT);
 
@@ -772,7 +782,8 @@
 // gui_settings object so that the user may choose to apply or cancel
 // the action.
 
-void settings_dialog::default_shortcut_set ()
+void
+settings_dialog::default_shortcut_set ()
 {
   if (! overwrite_all_shortcuts ())
     return;
@@ -780,7 +791,8 @@
   shortcuts_treewidget->set_default_shortcuts ();
 }
 
-void settings_dialog::update_editor_lexers (int def)
+void
+settings_dialog::update_editor_lexers (int def)
 {
 #if defined (HAVE_QSCINTILLA)
 
@@ -859,7 +871,8 @@
 
 #if defined (HAVE_QSCINTILLA)
 
-void settings_dialog::update_lexer (QsciLexer *lexer, 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
@@ -961,12 +974,13 @@
 
 }
 
-void settings_dialog::get_lexer_settings (QsciLexer *lexer)
+void
+settings_dialog::get_lexer_settings (QsciLexer *lexer)
 {
   gui_settings settings;
 
   int styles[ed_max_lexer_styles];  // array for saving valid styles
-  // (enum is not continuous)
+                                    // (enum is not continuous)
   int max_style = settings.get_valid_lexer_styles (lexer, styles);
   QGridLayout *style_grid = new QGridLayout ();
   QVector<QLabel *> description (max_style);
@@ -1055,7 +1069,8 @@
   tabs_editor_lexers->setCurrentIndex (settings.int_value (sd_last_editor_styles_tab));
 }
 
-void settings_dialog::write_lexer_settings (QsciLexer *lexer)
+void
+settings_dialog::write_lexer_settings (QsciLexer *lexer)
 {
   gui_settings settings;
 
@@ -1070,7 +1085,7 @@
   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)
+                                    // (enum is not continuous)
 
   int max_style = settings.get_valid_lexer_styles (lexer, styles);
 
@@ -1084,7 +1099,7 @@
   color = findChild <color_picker *> (ed_highlight_current_line_color.settings_key ());
   if (color)
     settings.setValue (ed_highlight_current_line_color.settings_key ()
-                        + settings_color_modes_ext[mode], color->color ());
+                       + settings_color_modes_ext[mode], color->color ());
 
   QString default_font_name
     = settings.string_value (global_mono_font);
@@ -1161,7 +1176,8 @@
 
 #endif
 
-void settings_dialog::write_changed_settings ()
+void
+settings_dialog::write_changed_settings ()
 {
 
   gui_settings settings;
@@ -1391,7 +1407,8 @@
   settings.sync ();
 }
 
-void settings_dialog::read_workspace_colors ()
+void
+settings_dialog::read_workspace_colors ()
 {
   gui_settings settings;
 
@@ -1434,7 +1451,7 @@
   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,
@@ -1472,10 +1489,11 @@
   connect (cb_color_mode, &QCheckBox::stateChanged,
            this, &settings_dialog::update_workspace_colors);
   connect (pb_reload_default_colors, &QPushButton::clicked,
-           [=] () { update_workspace_colors (settings_reload_default_colors_flag); });
+           [this] () { update_workspace_colors (settings_reload_default_colors_flag); });
 }
 
-void settings_dialog::update_workspace_colors (int def)
+void
+settings_dialog::update_workspace_colors (int def)
 {
   QCheckBox *cb_color_mode
     = workspace_colors_box->findChild <QCheckBox *> (ws_color_mode.settings_key ());
@@ -1507,7 +1525,8 @@
     }
 }
 
-void settings_dialog::write_workspace_colors ()
+void
+settings_dialog::write_workspace_colors ()
 {
   gui_settings settings;
 
@@ -1535,7 +1554,8 @@
   settings.sync ();
 }
 
-void settings_dialog::read_terminal_colors ()
+void
+settings_dialog::read_terminal_colors ()
 {
   gui_settings settings;
 
@@ -1561,7 +1581,7 @@
   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);
       color[i] = new color_picker (setting_color);
@@ -1584,10 +1604,11 @@
   connect (cb_color_mode, &QCheckBox::stateChanged,
            this, &settings_dialog::update_terminal_colors);
   connect (pb_reload_default_colors, &QPushButton::clicked,
-           [=] () { update_terminal_colors (settings_reload_default_colors_flag); });
+           [this] () { update_terminal_colors (settings_reload_default_colors_flag); });
 }
 
-void settings_dialog::update_terminal_colors (int def)
+void
+settings_dialog::update_terminal_colors (int def)
 {
   QCheckBox *cb_color_mode
     = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.settings_key ());
@@ -1619,7 +1640,8 @@
     }
 }
 
-void settings_dialog::write_terminal_colors ()
+void
+settings_dialog::write_terminal_colors ()
 {
   QCheckBox *cb_color_mode
     = terminal_colors_box->findChild <QCheckBox *> (cs_color_mode.settings_key ());
@@ -1644,7 +1666,8 @@
   settings.sync ();
 }
 
-void settings_dialog::read_varedit_colors ()
+void
+settings_dialog::read_varedit_colors ()
 {
   gui_settings settings;
 
@@ -1670,7 +1693,7 @@
   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);
@@ -1694,10 +1717,11 @@
   connect (cb_color_mode, &QCheckBox::stateChanged,
            this, &settings_dialog::update_varedit_colors);
   connect (pb_reload_default_colors, &QPushButton::clicked,
-           [=] () { update_varedit_colors (settings_reload_default_colors_flag); });
+           [this] () { update_varedit_colors (settings_reload_default_colors_flag); });
 }
 
-void settings_dialog::update_varedit_colors (int def)
+void
+settings_dialog::update_varedit_colors (int def)
 {
   QCheckBox *cb_color_mode
     = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.settings_key ());
@@ -1729,7 +1753,8 @@
     }
 }
 
-void settings_dialog::write_varedit_colors ()
+void
+settings_dialog::write_varedit_colors ()
 {
   QCheckBox *cb_color_mode
     = varedit_colors_box->findChild <QCheckBox *> (ve_color_mode.settings_key ());
@@ -1754,7 +1779,8 @@
   settings.sync ();
 }
 
-QString settings_dialog::get_shortcuts_file_name (import_export_action action)
+QString
+settings_dialog::get_shortcuts_file_name (import_export_action action)
 {
   QString file;
 
@@ -1801,7 +1827,8 @@
 //   (XX) - already possible (cancel operation, cancel settings
 //          dialog, re-open settings dialog and export changes).
 
-bool settings_dialog::overwrite_all_shortcuts ()
+bool
+settings_dialog::overwrite_all_shortcuts ()
 {
   QMessageBox msg_box;
 
@@ -1840,7 +1867,8 @@
   return false;
 }
 
-QMessageBox* settings_dialog::wait_message_box (const QString& text, QWidget *p)
+QMessageBox *
+settings_dialog::wait_message_box (const QString& text, QWidget *p)
 {
   QMessageBox *info = new QMessageBox (p);
 
@@ -1860,7 +1888,8 @@
   return info;
 }
 
-void settings_dialog::close_wait_message_box (QMessageBox *mbox)
+void
+settings_dialog::close_wait_message_box (QMessageBox *mbox)
 {
   QApplication::restoreOverrideCursor ();
   mbox->close ();
--- a/libgui/src/shortcuts-tree-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/shortcuts-tree-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -54,7 +54,8 @@
 }
 
 // new keyPressEvent
-void enter_shortcut::keyPressEvent (QKeyEvent *e)
+void
+enter_shortcut::keyPressEvent (QKeyEvent *e)
 {
   if (! m_direct_shortcut)
     {
@@ -85,7 +86,8 @@
 }
 
 // slot for checkbox whether the shortcut is directly entered or not
-void enter_shortcut::handle_direct_shortcut (int state)
+void
+enter_shortcut::handle_direct_shortcut (int state)
 {
   if (state)
     m_direct_shortcut = true;  // the shortcut is directly entered
@@ -94,7 +96,8 @@
 }
 
 // slot for checkbox whether the shift modifier should be added
-void enter_shortcut::handle_shift_modifier (int state)
+void
+enter_shortcut::handle_shift_modifier (int state)
 {
   if (state)
     m_shift_modifier = true;  // the shortcut is directly entered
@@ -117,37 +120,44 @@
   set_actual_text (actual_text);
 }
 
-QString tree_widget_shortcut_item::settings_key () const
+QString
+tree_widget_shortcut_item::settings_key () const
 {
   return m_settings_key;
 }
 
-QString tree_widget_shortcut_item::description () const
+QString
+tree_widget_shortcut_item::description () const
 {
   return text (DESCRIPTION_COLUMN);
 }
 
-void tree_widget_shortcut_item::set_description (const QString& text)
+void
+tree_widget_shortcut_item::set_description (const QString& text)
 {
   setText (DESCRIPTION_COLUMN, text);
 }
 
-QString tree_widget_shortcut_item::default_text () const
+QString
+tree_widget_shortcut_item::default_text () const
 {
   return text (DEFAULT_COLUMN);
 }
 
-void tree_widget_shortcut_item::set_default_text (const QString& text)
+void
+tree_widget_shortcut_item::set_default_text (const QString& text)
 {
   setText (DEFAULT_COLUMN, text);
 }
 
-QString tree_widget_shortcut_item::actual_text () const
+QString
+tree_widget_shortcut_item::actual_text () const
 {
   return text (ACTUAL_COLUMN);
 }
 
-void tree_widget_shortcut_item::set_actual_text (const QString& text)
+void
+tree_widget_shortcut_item::set_actual_text (const QString& text)
 {
   setText (ACTUAL_COLUMN, text);
 }
@@ -262,7 +272,8 @@
   setFocusProxy (m_edit_actual);
 }
 
-void shortcut_edit_dialog::finished (int result)
+void
+shortcut_edit_dialog::finished (int result)
 {
   if (result == QDialog::Rejected)
     return;
@@ -273,7 +284,7 @@
   // 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.
+  // 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 ();
@@ -333,7 +344,8 @@
   m_shortcut_item->set_actual_text (actual_text);
 }
 
-void shortcut_edit_dialog::set_default_shortcut ()
+void
+shortcut_edit_dialog::set_default_shortcut ()
 {
   // Just remove user-set value so that the default will be used.
   m_edit_actual->setText ("");
@@ -504,8 +516,9 @@
   dialog->show ();
 }
 
-void shortcuts_tree_widget::update_widget_value (const QString& settings_key,
-                                                 const QString& sc_text)
+void
+shortcuts_tree_widget::update_widget_value (const QString& settings_key,
+    const QString& sc_text)
 {
   tree_widget_shortcut_item *item = get_item (settings_key);
 
@@ -546,8 +559,9 @@
   return item;
 }
 
-void shortcuts_tree_widget::update_settings_value (gui_settings& settings,
-                                                   const QString& settings_key)
+void
+shortcuts_tree_widget::update_settings_value (gui_settings& settings,
+    const QString& settings_key)
 {
   tree_widget_shortcut_item *item = get_item (settings_key);
 
@@ -557,7 +571,8 @@
 
 // Refresh the tree view with values from the settings object.
 
-void shortcuts_tree_widget::import_shortcuts (gui_settings& settings)
+void
+shortcuts_tree_widget::import_shortcuts (gui_settings& settings)
 {
   settings.beginGroup (sc_group);
 
@@ -609,7 +624,8 @@
 
 // Export all shortcuts from the tree view to the settings object.
 
-void shortcuts_tree_widget::export_shortcuts (gui_settings& settings)
+void
+shortcuts_tree_widget::export_shortcuts (gui_settings& settings)
 {
   settings.beginGroup (sc_group);
 
@@ -654,7 +670,8 @@
 // Clear all user-defined settings from the tree widget and the
 // application settings.
 
-void shortcuts_tree_widget::set_default_shortcuts ()
+void
+shortcuts_tree_widget::set_default_shortcuts ()
 {
   gui_settings settings;
 
@@ -701,7 +718,8 @@
 // For each key found in application settings object, transfer
 // corresponding setting to the application settings object.
 
-void shortcuts_tree_widget::write_settings ()
+void
+shortcuts_tree_widget::write_settings ()
 {
   gui_settings settings;
 
--- a/libgui/src/tab-bar.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/tab-bar.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -39,36 +39,42 @@
 //
 
 tab_bar::tab_bar (QWidget *p)
-: QTabBar (p), m_context_menu (new QMenu (this))
+  : QTabBar (p), m_context_menu (new QMenu (this))
 { }
 
-void tab_bar::set_rotated (int rotated)
+void
+tab_bar::set_rotated (int rotated)
 {
   m_rotated = rotated;
 }
 
 // slots for tab navigation
-void tab_bar::switch_left_tab ()
+void
+tab_bar::switch_left_tab ()
 {
   switch_tab (-1);
 }
 
-void tab_bar::switch_right_tab ()
+void
+tab_bar::switch_right_tab ()
 {
   switch_tab (1);
 }
 
-void tab_bar::move_tab_left ()
+void
+tab_bar::move_tab_left ()
 {
   switch_tab (-1, true);
 }
 
-void tab_bar::move_tab_right ()
+void
+tab_bar::move_tab_right ()
 {
   switch_tab (1, true);
 }
 
-void tab_bar::switch_tab (int direction, bool movetab)
+void
+tab_bar::switch_tab (int direction, bool movetab)
 {
   int tabs = count ();
 
@@ -91,7 +97,8 @@
     setCurrentIndex (new_pos);
 }
 
-void tab_bar::sort_tabs_alph ()
+void
+tab_bar::sort_tabs_alph ()
 {
   QString current_title = tabText (currentIndex ());
   int tab_with_focus = 0;
@@ -133,17 +140,19 @@
 // https://stackoverflow.com/a/50579369
 
 // Reimplemented size hint allowing rotated tabs
-QSize tab_bar::tabSizeHint (int idx) const
+QSize
+tab_bar::tabSizeHint (int idx) const
 {
   QSize s = QTabBar::tabSizeHint (idx);
   if (m_rotated)
-    s.transpose();
+    s.transpose ();
 
   return s;
 }
 
 // Reimplemented paint event allowing rotated tabs
-void tab_bar::paintEvent(QPaintEvent *e)
+void
+tab_bar::paintEvent (QPaintEvent *e)
 {
   // Just process the original event if not rotated
   if (! m_rotated)
@@ -153,14 +162,14 @@
   QStylePainter painter (this);
   QStyleOptionTab opt;
 
-  for (int idx = 0; idx < count(); idx++)
+  for (int idx = 0; idx < count (); idx++)
     {
       initStyleOption (&opt, idx);
       painter.drawControl (QStyle::CE_TabBarTabShape, opt);
       painter.save ();
 
-      QSize s = opt.rect.size();
-      s.transpose();
+      QSize s = opt.rect.size ();
+      s.transpose ();
       QRect rect (QPoint (), s);
       rect.moveCenter (opt.rect.center ());
       opt.rect = rect;
@@ -175,7 +184,8 @@
 }
 
 // Reimplement mouse event for filtering out the desired mouse clicks
-void tab_bar::mousePressEvent (QMouseEvent *me)
+void
+tab_bar::mousePressEvent (QMouseEvent *me)
 {
   QPoint click_pos;
   int clicked_idx = -1;
@@ -199,9 +209,9 @@
 
       // detect the mouse click
       if ((me->type () == QEvent::MouseButtonDblClick
-           && me->button() == Qt::LeftButton)
+           && me->button () == Qt::LeftButton)
           || (me->type () != QEvent::MouseButtonDblClick
-              && me->button() == Qt::MiddleButton))
+              && me->button () == Qt::MiddleButton))
         {
           // Middle click or double click -> close the tab
           // Make the clicked tab the current one and close it
@@ -215,7 +225,7 @@
             setCurrentIndex (current_idx);
         }
       else if (me->type () != QEvent::MouseButtonDblClick
-               && me->button() == Qt::RightButton)
+               && me->button () == Qt::RightButton)
         {
           // Right click, show context menu
           setCurrentIndex (clicked_idx);
@@ -273,7 +283,8 @@
 }
 
 // Slot if a menu entry in the context menu is activated
-void tab_bar::ctx_menu_activated (QAction *a)
+void
+tab_bar::ctx_menu_activated (QAction *a)
 {
   // If the index of the activated action is in the range of
   // the current tabs, set the related current tab. The basic actions
--- a/libgui/src/tab-bar.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/tab-bar.h	Fri Apr 12 15:10:26 2024 +0200
@@ -73,8 +73,8 @@
 
 protected:
 
-  void paintEvent(QPaintEvent *e);
-  void mousePressEvent(QMouseEvent *event);
+  void paintEvent (QPaintEvent *e);
+  void mousePressEvent (QMouseEvent *event);
 
 private:
 
--- a/libgui/src/terminal-dock-widget.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/terminal-dock-widget.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -72,10 +72,10 @@
                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
@@ -92,11 +92,11 @@
       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 fcn_callback&> (&QTerminal::interpreter_event),
+               this, qOverload<const fcn_callback&> (&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));
+      connect (widget, qOverload<const meth_callback&> (&QTerminal::interpreter_event),
+               this, qOverload<const meth_callback&> (&terminal_dock_widget::interpreter_event));
 
       m_terminal = widget;
     }
@@ -122,10 +122,10 @@
   font.setPointSize
     (settings.int_value (cs_font_size));
 
-  QFontMetrics metrics(font);
+  QFontMetrics metrics (font);
 
-  int win_x =  metrics.maxWidth()*80;
-  int win_y =  metrics.height()*25;
+  int win_x =  metrics.maxWidth ()*80;
+  int win_y =  metrics.height ()*25;
 
   int max_x = QGuiApplication::primaryScreen ()->availableGeometry ().width ();
   int max_y = QGuiApplication::primaryScreen ()->availableGeometry ().height ();
@@ -141,32 +141,37 @@
     make_window ();
 }
 
-bool terminal_dock_widget::has_focus () const
+bool
+terminal_dock_widget::has_focus () const
 {
   QWidget *w = widget ();
   return w->hasFocus ();
 }
 
-QTerminal * terminal_dock_widget::get_qterminal ()
+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 ()
+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 ()
+void
+terminal_dock_widget::notice_settings ()
 {
   emit settings_changed ();
 }
 
-void terminal_dock_widget::init_command_prompt ()
+void
+terminal_dock_widget::init_command_prompt ()
 {
   if (m_experimental_terminal_widget)
     {
@@ -178,7 +183,8 @@
     }
 }
 
-void terminal_dock_widget::init_control_d_shortcut_behavior ()
+void
+terminal_dock_widget::init_control_d_shortcut_behavior ()
 {
   gui_settings settings;
 
@@ -210,7 +216,7 @@
               break;
             }
         }
-   }
+    }
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libgui/src/variable-editor-model.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/variable-editor-model.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
@@ -179,7 +179,7 @@
     }
   else
     {
-      dim_vector dv = elt.dims ();
+      const dim_vector& dv = elt.dims ();
       str = "[" + dv.str () + " " + elt.class_name () + "]";
     }
 
@@ -294,7 +294,7 @@
       if (! lbl_txt.isEmpty ())
         lbl_txt += " ";
 
-      dim_vector dv = m_value.dims ();
+      const dim_vector& dv = m_value.dims ();
 
       lbl_txt += ("["
                   + QString::fromStdString (dv.str ())
@@ -1008,7 +1008,7 @@
   QPointer<variable_editor_model> this_vem (this);
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_vem, expr, nm, idx] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -1163,7 +1163,7 @@
   std::string expr = expr_arg.toStdString ();
 
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, expr] (interpreter& interp)
     {
       // INTERPRETER THREAD
 
@@ -1235,7 +1235,7 @@
 variable_editor_model::update_data_cache ()
 {
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this] (interpreter& interp)
     {
       // INTERPRETER_THREAD
 
@@ -1381,7 +1381,7 @@
 {
   if (requires_sub_editor (idx))
     {
-      QString name = QString::fromStdString(m_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	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/variable-editor-model.h	Fri Apr 12 15:10:26 2024 +0200
@@ -194,16 +194,16 @@
   Qt::ItemFlags flags (const QModelIndex& idx) const;
 
   bool insertRows (int row, int count,
-                   const QModelIndex& parent = QModelIndex());
+                   const QModelIndex& parent = QModelIndex ());
 
   bool removeRows (int row, int count,
-                   const QModelIndex& parent = QModelIndex());
+                   const QModelIndex& parent = QModelIndex ());
 
   bool insertColumns (int column, int count,
-                      const QModelIndex& parent = QModelIndex());
+                      const QModelIndex& parent = QModelIndex ());
 
   bool removeColumns (int column, int count,
-                      const QModelIndex& parent = QModelIndex());
+                      const QModelIndex& parent = QModelIndex ());
 
   // Is cell at idx complex enough to require a sub editor?
 
--- a/libgui/src/variable-editor.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/variable-editor.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
@@ -75,7 +75,7 @@
 
   QSignalMapper *plot_mapper = new QSignalMapper (menu);
 
-  for (int i = 0; i < list.size(); ++i)
+  for (int i = 0; i < list.size (); ++i)
     plot_mapper->setMapping
       (menu->addAction (list.at (i), plot_mapper, SLOT (map ())), list.at (i));
 
@@ -277,7 +277,7 @@
 
       emit variable_focused_signal (objectName ());
     }
-  else if (old == focusWidget())
+  else if (old == focusWidget ())
     {
       if (titleBarWidget () != nullptr)
         {
@@ -291,7 +291,8 @@
     }
 }
 
-void variable_dock_widget::resizeEvent (QResizeEvent *)
+void
+variable_dock_widget::resizeEvent (QResizeEvent *)
 {
   if (m_frame)
     m_frame->resize (size ());
@@ -464,7 +465,7 @@
 
   // No format given, test save default options
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([this, this_ves, format_string] (interpreter& interp)
       {
         // INTERPRETER THREAD
 
@@ -519,7 +520,7 @@
 
   // Let the interpreter thread do the saving
   emit interpreter_event
-    ([=] (interpreter& interp)
+    ([file, name, format] (interpreter& interp)
       {
         // INTERPRETER THREAD
 
@@ -601,7 +602,7 @@
 
   QVector<int> vect;
   vect << from_row + 1 << to_row + 1 << from_col + 1 << to_col + 1;
-  QList<int> range = QList<int>::fromVector(vect);
+  QList<int> range = QList<int>::fromVector (vect);
 
   return range;
 }
@@ -1063,7 +1064,8 @@
   installEventFilter (this);
 }
 
-bool HoverToolButton::eventFilter (QObject *obj, QEvent *ev)
+bool
+HoverToolButton::eventFilter (QObject *obj, QEvent *ev)
 {
   if (ev->type () == QEvent::HoverEnter)
     emit hovered_signal ();
@@ -1079,7 +1081,8 @@
   installEventFilter (this);
 }
 
-bool ReturnFocusToolButton::eventFilter (QObject *obj, QEvent *ev)
+bool
+ReturnFocusToolButton::eventFilter (QObject *obj, QEvent *ev)
 {
 
   if (ev->type () == QEvent::MouseButtonRelease && isDown ())
@@ -1103,7 +1106,8 @@
   installEventFilter (this);
 }
 
-bool ReturnFocusMenu::eventFilter (QObject *obj, QEvent *ev)
+bool
+ReturnFocusMenu::eventFilter (QObject *obj, QEvent *ev)
 {
   if (ev->type () == QEvent::MouseButtonRelease && underMouse ())
     {
@@ -1175,7 +1179,8 @@
     make_window ();
 }
 
-void variable_editor::focusInEvent (QFocusEvent *ev)
+void
+variable_editor::focusInEvent (QFocusEvent *ev)
 {
   octave_dock_widget::focusInEvent (ev);
 
@@ -1209,7 +1214,7 @@
                 }
             }
           if (! focus_set)
-            setFocus();
+            setFocus ();
         }
     }
 }
@@ -1222,7 +1227,7 @@
   for (long long int i = 0; i < m_variables.size (); i++)
     {
       if (m_variables.at (i) != nullptr)
-        disconnect (m_variables.at (i), SIGNAL (destroyed (QObject*)), 0, 0);
+        disconnect (m_variables.at (i), SIGNAL (destroyed (QObject *)), 0, 0);
     }
 }
 
@@ -1292,18 +1297,18 @@
 
   // Any interpreter_event signal from a variable_editor_stack object is
   // handled the same as for the parent variable_editor object.
-  connect (stack, QOverload<const fcn_callback&>::of (&variable_editor_stack::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&variable_editor::interpreter_event));
+  connect (stack, qOverload<const fcn_callback&> (&variable_editor_stack::interpreter_event),
+           this, qOverload<const fcn_callback&> (&variable_editor::interpreter_event));
 
-  connect (stack, QOverload<const meth_callback&>::of (&variable_editor_stack::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&variable_editor::interpreter_event));
+  connect (stack, qOverload<const meth_callback&> (&variable_editor_stack::interpreter_event),
+           this, qOverload<const meth_callback&> (&variable_editor::interpreter_event));
 
   connect (stack, &variable_editor_stack::edit_variable_signal,
            this, &variable_editor::edit_variable);
   connect (this, &variable_editor::level_up_signal,
            stack, &variable_editor_stack::levelUp);
   connect (this, &variable_editor::save_signal,
-           stack, [=] () { stack->save (); });
+           stack, [stack] () { stack->save (); });
 
   variable_editor_view *edit_view = stack->edit_view ();
 
@@ -1368,11 +1373,11 @@
   // Any interpreter_event signal from a variable_editor_model object is
   // handled the same as for the parent variable_editor object.
 
-  connect (model, QOverload<const fcn_callback&>::of (&variable_editor_model::interpreter_event),
-           this, QOverload<const fcn_callback&>::of (&variable_editor::interpreter_event));
+  connect (model, qOverload<const fcn_callback&> (&variable_editor_model::interpreter_event),
+           this, qOverload<const fcn_callback&> (&variable_editor::interpreter_event));
 
-  connect (model, QOverload<const meth_callback&>::of (&variable_editor_model::interpreter_event),
-           this, QOverload<const meth_callback&>::of (&variable_editor::interpreter_event));
+  connect (model, qOverload<const meth_callback&> (&variable_editor_model::interpreter_event),
+           this, qOverload<const meth_callback&> (&variable_editor::interpreter_event));
 
   // Must supply a title for a QLabel to be created.  Calling set_title()
   // more than once will add more QLabels.  Could change octave_dock_widget
@@ -1620,7 +1625,8 @@
 
 // Also updates the font.
 
-void variable_editor::update_colors ()
+void
+variable_editor::update_colors ()
 {
   m_stylesheet = "";
 
@@ -1671,7 +1677,7 @@
                                       const char *member)
 {
   QAction *action = new QAction (icon, text, this);
-  connect(action, SIGNAL (triggered ()), receiver, member);
+  connect (action, SIGNAL (triggered ()), receiver, member);
   QToolButton *button = new ReturnFocusToolButton (m_tool_bar);
   button->setDefaultAction (action);
   button->setText (text);
@@ -1697,7 +1703,7 @@
                                        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"));
+  m_save_action->setStatusTip (tr("Save variable to a file"));
 
   QAction *action = new QAction (settings.icon ("document-save-as"),
                                  tr ("Save in format ..."), m_tool_bar);
@@ -1728,15 +1734,15 @@
 
   action = add_tool_bar_button (settings.icon ("edit-cut"), tr ("Cut"),
                                 this, SLOT (cutClipboard ()));
-  action->setStatusTip(tr("Cut data to clipboard"));
+  action->setStatusTip (tr("Cut data to clipboard"));
 
   action = add_tool_bar_button (settings.icon ("edit-copy"), tr ("Copy"),
                                 this, SLOT (copyClipboard ()));
-  action->setStatusTip(tr("Copy data to clipboard"));
+  action->setStatusTip (tr("Copy data to clipboard"));
 
   action = add_tool_bar_button (settings.icon ("edit-paste"), tr ("Paste"),
                                 this, SLOT (pasteClipboard ()));
-  action->setStatusTip(tr("Paste clipboard into variable data"));
+  action->setStatusTip (tr("Paste clipboard into variable data"));
 
   m_tool_bar->addSeparator ();
 
@@ -1770,7 +1776,7 @@
 
   action = add_tool_bar_button (settings.icon ("go-up"), tr ("Up"), this,
                                 SLOT (levelUp ()));
-  action->setStatusTip(tr("Go one level up in variable hierarchy"));
+  action->setStatusTip (tr("Go one level up in variable hierarchy"));
 
   // The QToolButton mouse-clicks change active window, so connect all
   // HoverToolButton and ReturnFocusToolButton objects to the mechanism
@@ -1806,7 +1812,7 @@
                this, &variable_editor::restore_hovered_focus_variable);
     }
 
-  m_tool_bar->setAttribute(Qt::WA_ShowWithoutActivating);
+  m_tool_bar->setAttribute (Qt::WA_ShowWithoutActivating);
   m_tool_bar->setFocusPolicy (Qt::NoFocus);
 
   // Disabled when no tab is present.
--- a/libgui/src/variable-editor.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/variable-editor.h	Fri Apr 12 15:10:26 2024 +0200
@@ -394,7 +394,7 @@
 
   void construct_tool_bar ();
 
-  QList<variable_dock_widget*> m_variables;
+  QList<variable_dock_widget *> m_variables;
 
   QString m_current_focus_vname;
 
--- a/libgui/src/welcome-wizard.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/welcome-wizard.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -33,8 +33,8 @@
 #include <QVBoxLayout>
 
 #if defined (OCTAVE_USE_WINDOWS_API)
-  #define WIN32_LEAN_AND_MEAN
-  #include <windows.h>
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
 #endif
 
 #include "gui-preferences-dw.h"
@@ -91,7 +91,8 @@
 #endif
 }
 
-void welcome_wizard::adjust_size ()
+void
+welcome_wizard::adjust_size ()
 {
   // Get adjusted size for the current page
   adjustSize ();
@@ -106,12 +107,14 @@
     m_max_width = sz.width ();
 }
 
-void welcome_wizard::handle_web_connect_option (int state)
+void
+welcome_wizard::handle_web_connect_option (int state)
 {
   m_allow_web_connect_state = state == Qt::Checked;
 }
 
-void welcome_wizard::show_page ()
+void
+welcome_wizard::show_page ()
 {
   delete m_current_page;
   delete layout ();
@@ -124,21 +127,24 @@
   new_layout->addWidget (m_current_page);
 }
 
-void welcome_wizard::previous_page ()
+void
+welcome_wizard::previous_page ()
 {
   --m_page_list_iterator;
 
   show_page ();
 }
 
-void welcome_wizard::next_page ()
+void
+welcome_wizard::next_page ()
 {
   ++m_page_list_iterator;
 
   show_page ();
 }
 
-void welcome_wizard::accept ()
+void
+welcome_wizard::accept ()
 {
   // Create default settings file.
 
--- a/libgui/src/workspace-model.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/workspace-model.h	Fri Apr 12 15:10:26 2024 +0200
@@ -77,7 +77,7 @@
 signals:
 
   void model_changed ();
-  void prompt_variable_editor();
+  void prompt_variable_editor ();
 
 public slots:
 
--- a/libgui/src/workspace-view.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/workspace-view.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -39,6 +39,7 @@
 #include <QMessageBox>
 #include <QPushButton>
 #include <QSignalMapper>
+#include <QTimer>
 #include <QVBoxLayout>
 
 #include "gui-preferences-ws.h"
@@ -107,9 +108,6 @@
 
   //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);
@@ -151,12 +149,30 @@
 
   if (! p)
     make_window ();
+
+  // Initialize column order and width of the workspace. From this post,
+  // https://www.qtcentre.org/threads/26675-QTableView-saving-restoring-columns-widths
+  // this might fail if done directly in the constructor. This effect shows
+  // up in the GUI since Qt 6.6.x. As a solution, the following timer ensures
+  // that the header is restored when the event loop is idle.
+  QTimer::singleShot (0, this, SLOT(restore_header_state ()));
 }
 
-void workspace_view::setModel (workspace_model *model)
+void
+workspace_view::restore_header_state ()
+{
+  gui_settings settings;
+
+  if (settings.contains (ws_column_state.settings_key ()))
+    m_view->horizontalHeader ()->restoreState
+      (settings.value (ws_column_state.settings_key ()).toByteArray ());
+}
+
+void
+workspace_view::setModel (workspace_model *model)
 {
   m_filter_model.setSourceModel (model);
-  m_filter_model.setFilterKeyColumn(0);
+  m_filter_model.setFilterKeyColumn (0);
 
   m_view->setModel (&m_filter_model);
 
@@ -231,7 +247,8 @@
   octave_dock_widget::save_settings ();
 }
 
-void workspace_view::set_filter_focus (bool focus)
+void
+workspace_view::set_filter_focus (bool focus)
 {
   if (focus)
     {
--- a/libgui/src/workspace-view.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libgui/src/workspace-view.h	Fri Apr 12 15:10:26 2024 +0200
@@ -78,6 +78,7 @@
 
 protected slots:
 
+  void restore_header_state ();
   void filter_update (const QString& expression);
   void filter_activate (bool enable);
   void update_filter_history ();
--- a/libinterp/corefcn/Cell.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/Cell.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -72,7 +72,7 @@
     {
       resize (dim_vector (n, 1));
 
-      octave_value *dst = fortran_vec ();
+      octave_value *dst = rwdata ();
       auto p = sl.begin ();
 
       for (octave_idx_type i = 0; i < n; i++)
@@ -85,7 +85,7 @@
 {
   octave_idx_type n = sa.numel ();
 
-  octave_value *dst = fortran_vec ();
+  octave_value *dst = rwdata ();
   const std::string *src = sa.data ();
 
   for (octave_idx_type i = 0; i < n; i++)
@@ -344,7 +344,7 @@
 Cell::map (ctype_mapper fcn) const
 {
   Cell retval (dims ());
-  octave_value *r = retval.fortran_vec ();
+  octave_value *r = retval.rwdata ();
 
   const octave_value *p = data ();
 
--- a/libinterp/corefcn/Cell.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/Cell.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 
 class octave_value_list;
 
-class
-OCTINTERP_API
-Cell : public Array<octave_value>
+class OCTINTERP_API Cell : public Array<octave_value>
 {
 public:
 
--- a/libinterp/corefcn/__betainc__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__betainc__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -79,7 +79,7 @@
 
       // Initialize variables used in algorithm
       static const float tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon ();
+      static constexpr float eps = std::numeric_limits<float>::epsilon ();
       float xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;
       int j, maxit;
       maxit = 200;
@@ -150,7 +150,7 @@
 
       // Initialize variables used in algorithm
       static const double tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon ();
+      static constexpr double eps = std::numeric_limits<double>::epsilon ();
       double xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;
       int j, maxit;
       maxit = 200;
--- a/libinterp/corefcn/__dsearchn__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__dsearchn__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,9 +57,9 @@
   octave_idx_type nxi = xi.columns ();
 
   ColumnVector idx (nxi);
-  double *pidx = idx.fortran_vec ();
+  double *pidx = idx.rwdata ();
   ColumnVector dist (nxi);
-  double *pdist = dist.fortran_vec ();
+  double *pdist = dist.rwdata ();
 
 #define DIST(dd, y, yi, m)                      \
   dd = 0.0;                                     \
--- a/libinterp/corefcn/__eigs__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__eigs__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -345,7 +345,7 @@
           if (tmp.numel () != 1)
             error ("eigs: OPTS.issym must be a scalar value");
 
-          symmetric = tmp.xbool_value ("eigs: OPTS.issym must be a logical value");
+          symmetric = tmp.ybool_value ("eigs: OPTS.issym must be a logical value");
           sym_tested = true;
         }
 
@@ -358,7 +358,7 @@
               if (tmp.numel () != 1)
                 error ("eigs: OPTS.isreal must be a scalar value");
 
-              a_is_complex = ! tmp.xbool_value ("eigs: OPTS.isreal must be a logical value");
+              a_is_complex = ! tmp.ybool_value ("eigs: OPTS.isreal must be a logical value");
             }
         }
 
--- a/libinterp/corefcn/__expint__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__expint__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -65,7 +65,7 @@
 
       // Initialize variables used in algorithm
       static const FloatComplex tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon ();
+      static constexpr float eps = std::numeric_limits<float>::epsilon ();
       const FloatComplex cone (1.0, 0.0);
       const FloatComplex czero (0.0, 0.0);
       const int maxit = 100;
@@ -123,7 +123,7 @@
 
       // Initialize variables used in algorithm
       static const Complex tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon ();
+      static constexpr double eps = std::numeric_limits<double>::epsilon ();
       const Complex cone (1.0, 0.0);
       const Complex czero (0.0, 0.0);
       const int maxit = 200;
--- a/libinterp/corefcn/__gammainc__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__gammainc__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -71,7 +71,7 @@
 
       // Initialize variables used in algorithm
       static const float tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon();
+      static constexpr float eps = std::numeric_limits<float>::epsilon();
       float y, Cj, Dj, bj, aj, Deltaj;
       int j, maxit;
       maxit = 200;
@@ -126,7 +126,7 @@
 
       // Initialize variables used in algorithm
       static const double tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon();
+      static constexpr double eps = std::numeric_limits<double>::epsilon();
       double y, Cj, Dj, bj, aj, Deltaj;
       int j, maxit;
       maxit = 200;
--- a/libinterp/corefcn/__ichol__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__ichol__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -254,11 +254,11 @@
   max_len = sm.nnz ();
   max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;
   Array <octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));
-  octave_idx_type *cidx_l = cidx_out_l.fortran_vec ();
+  octave_idx_type *cidx_l = cidx_out_l.rwdata ();
   Array <octave_idx_type> ridx_out_l (dim_vector (max_len, 1));
-  octave_idx_type *ridx_l = ridx_out_l.fortran_vec ();
+  octave_idx_type *ridx_l = ridx_out_l.rwdata ();
   Array <T> data_out_l (dim_vector (max_len, 1));
-  T *data_l = data_out_l.fortran_vec ();
+  T *data_l = data_out_l.rwdata ();
 
   // Working arrays
   OCTAVE_LOCAL_BUFFER (T, w_data, n);
@@ -332,9 +332,9 @@
         {
           max_len += (0.1 * max_len) > n ? 0.1 * max_len : n;
           data_out_l.resize (dim_vector (max_len, 1));
-          data_l = data_out_l.fortran_vec ();
+          data_l = data_out_l.rwdata ();
           ridx_out_l.resize (dim_vector (max_len, 1));
-          ridx_l = ridx_out_l.fortran_vec ();
+          ridx_l = ridx_out_l.rwdata ();
         }
 
       // The sorting of the nonzero elements of the working column can be
@@ -445,7 +445,7 @@
       RowVector sm_col_norms = xcolnorms (sm_l, 1);
       ichol_t <SparseMatrix,
               double, ichol_mult_real, ichol_checkpivot_real>
-              (sm_l, L, sm_col_norms.fortran_vec (), droptol, michol);
+              (sm_l, L, sm_col_norms.rwdata (), droptol, michol);
 
       return ovl (L);
     }
@@ -457,7 +457,7 @@
       Array <Complex> cols_norm = xcolnorms (sm_l, 1);
       ichol_t <SparseComplexMatrix,
               Complex, ichol_mult_complex, ichol_checkpivot_complex>
-              (sm_l, L, cols_norm.fortran_vec (),
+              (sm_l, L, cols_norm.rwdata (),
                Complex (droptol), michol);
 
       return ovl (L);
--- a/libinterp/corefcn/__ilu__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__ilu__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -220,15 +220,15 @@
 
   // L output arrays
   Array <octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));
-  octave_idx_type *ridx_l = ridx_out_l.fortran_vec ();
+  octave_idx_type *ridx_l = ridx_out_l.rwdata ();
   Array <T> data_out_l (dim_vector (max_len_l, 1));
-  T *data_l = data_out_l.fortran_vec ();
+  T *data_l = data_out_l.rwdata ();
 
   // U output arrays
   Array <octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));
-  octave_idx_type *ridx_u = ridx_out_u.fortran_vec ();
+  octave_idx_type *ridx_u = ridx_out_u.rwdata ();
   Array <T> data_out_u (dim_vector (max_len_u, 1));
-  T *data_u = data_out_u.fortran_vec ();
+  T *data_u = data_out_u.rwdata ();
 
   // Working arrays
   OCTAVE_LOCAL_BUFFER (octave_idx_type, cidx_l, n + 1);
@@ -293,18 +293,18 @@
         {
           max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
           data_out_u.resize (dim_vector (max_len_u, 1));
-          data_u = data_out_u.fortran_vec ();
+          data_u = data_out_u.rwdata ();
           ridx_out_u.resize (dim_vector (max_len_u, 1));
-          ridx_u = ridx_out_u.fortran_vec ();
+          ridx_u = ridx_out_u.rwdata ();
         }
 
       if ((max_len_l - total_len_l) < n)
         {
           max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
           data_out_l.resize (dim_vector (max_len_l, 1));
-          data_l = data_out_l.fortran_vec ();
+          data_l = data_out_l.rwdata ();
           ridx_out_l.resize (dim_vector (max_len_l, 1));
-          ridx_l = ridx_out_l.fortran_vec ();
+          ridx_l = ridx_out_l.rwdata ();
         }
 
       // Expand the working row into the U output data structures
@@ -487,8 +487,8 @@
       RowVector sm_col_norms = xcolnorms (sm);
       ColumnVector sm_row_norms = xrownorms (sm);
       ilu_crout <SparseMatrix, double> (sm_l, sm_u, L, U,
-                                        sm_col_norms.fortran_vec (),
-                                        sm_row_norms.fortran_vec (),
+                                        sm_col_norms.rwdata (),
+                                        sm_row_norms.rwdata (),
                                         droptol, milu);
 
       SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));
@@ -505,8 +505,8 @@
       Array<Complex> rows_norm = xrownorms (sm);
 
       ilu_crout <SparseComplexMatrix, Complex> (sm_l, sm_u, L, U,
-          cols_norm.fortran_vec (),
-          rows_norm.fortran_vec (),
+          cols_norm.rwdata (),
+          rows_norm.rwdata (),
           Complex (droptol), milu);
 
       SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));
@@ -563,19 +563,19 @@
 
   // Extract pointers to the arrays for faster access inside loops
   Array <octave_idx_type> cidx_out_l (dim_vector (n + 1, 1));
-  octave_idx_type *cidx_l = cidx_out_l.fortran_vec ();
+  octave_idx_type *cidx_l = cidx_out_l.rwdata ();
   Array <octave_idx_type> ridx_out_l (dim_vector (max_len_l, 1));
-  octave_idx_type *ridx_l = ridx_out_l.fortran_vec ();
+  octave_idx_type *ridx_l = ridx_out_l.rwdata ();
   Array <T> data_out_l (dim_vector (max_len_l, 1));
-  T *data_l = data_out_l.fortran_vec ();
+  T *data_l = data_out_l.rwdata ();
 
   // Data for U
   Array <octave_idx_type> cidx_out_u (dim_vector (n + 1, 1));
-  octave_idx_type *cidx_u = cidx_out_u.fortran_vec ();
+  octave_idx_type *cidx_u = cidx_out_u.rwdata ();
   Array <octave_idx_type> ridx_out_u (dim_vector (max_len_u, 1));
-  octave_idx_type *ridx_u = ridx_out_u.fortran_vec ();
+  octave_idx_type *ridx_u = ridx_out_u.rwdata ();
   Array <T> data_out_u (dim_vector (max_len_u, 1));
-  T *data_u = data_out_u.fortran_vec ();
+  T *data_u = data_out_u.rwdata ();
 
   // Working arrays and permutation arrays
   octave_idx_type w_len_u, w_len_l;
@@ -585,7 +585,7 @@
   std::set <octave_idx_type>::iterator it, it2;
   OCTAVE_LOCAL_BUFFER (T, w_data, n);
   OCTAVE_LOCAL_BUFFER (octave_idx_type, iperm, n);
-  octave_idx_type *perm = perm_vec.fortran_vec ();
+  octave_idx_type *perm = perm_vec.rwdata ();
   OCTAVE_LOCAL_BUFFER (octave_idx_type, uptr, n);
 
   // Initialize working and permutation arrays
@@ -770,18 +770,18 @@
         {
           max_len_u += (0.1 * max_len_u) > n ? 0.1 * max_len_u : n;
           data_out_u.resize (dim_vector (max_len_u, 1));
-          data_u = data_out_u.fortran_vec ();
+          data_u = data_out_u.rwdata ();
           ridx_out_u.resize (dim_vector (max_len_u, 1));
-          ridx_u = ridx_out_u.fortran_vec ();
+          ridx_u = ridx_out_u.rwdata ();
         }
 
       if ((max_len_l - total_len_l) < n)
         {
           max_len_l += (0.1 * max_len_l) > n ? 0.1 * max_len_l : n;
           data_out_l.resize (dim_vector (max_len_l, 1));
-          data_l = data_out_l.fortran_vec ();
+          data_l = data_out_l.rwdata ();
           ridx_out_l.resize (dim_vector (max_len_l, 1));
-          ridx_l = ridx_out_l.fortran_vec ();
+          ridx_l = ridx_out_l.rwdata ();
         }
 
       // Expand working vector into U.
@@ -935,7 +935,7 @@
       Array <octave_idx_type> perm (dim_vector (sm.cols (), 1));
 
       ilu_tp <SparseMatrix, double> (sm, L, U, nnz_u, nnz_l,
-                                     rc_norm.fortran_vec (),
+                                     rc_norm.rwdata (),
                                      perm, droptol, thresh, milu, udiag);
 
       SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));
@@ -976,7 +976,7 @@
       Array <octave_idx_type> perm (dim_vector (sm.cols (), 1));
 
       ilu_tp <SparseComplexMatrix, Complex>
-      (sm, L, U, nnz_u, nnz_l, rc_norm.fortran_vec (), perm,
+      (sm, L, U, nnz_u, nnz_l, rc_norm.rwdata (), perm,
        Complex (droptol), Complex (thresh), milu, udiag);
 
       SparseMatrix speye (DiagMatrix (L.cols (), L.cols (), 1.0));
--- a/libinterp/corefcn/__isprimelarge__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__isprimelarge__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -242,7 +242,7 @@
 
       if (g > 1)  // found GCD ==> exit loop properly
         {
-          error_unless (n % g == 0);  // theoretical possibility of GCD error
+          panic_unless (n % g == 0);  // theoretical possibility of GCD error
           return g;
         }
     }
--- a/libinterp/corefcn/__lin_interpn__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__lin_interpn__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -212,7 +212,7 @@
   OCTAVE_LOCAL_BUFFER (octave_idx_type, scale, n);
 
   const DT *v = V.data ();
-  DT *vi = Vi.fortran_vec ();
+  DT *vi = Vi.rwdata ();
   octave_idx_type Ni = Vi.numel ();
 
   // offset in memory of each dimension
--- a/libinterp/corefcn/__magick_read__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__magick_read__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -176,8 +176,7 @@
   return output;
 }
 
-class
-image_region
+class image_region
 {
 public:
 
@@ -301,7 +300,7 @@
   const octave_idx_type def_elem = frameidx(0);
 
   T img       = T (dim_vector (nRows, nCols, 1, nFrames));
-  P *img_fvec = img.fortran_vec ();
+  P *img_fvec = img.rwdata ();
 
   const octave_idx_type row_start = region.row_start ();
   const octave_idx_type col_start = region.col_start ();
@@ -359,7 +358,7 @@
               const double *amap_fvec = amap.data ();
 
               NDArray alpha (dim_vector (nRows, nCols, 1, nFrames));
-              double *alpha_fvec = alpha.fortran_vec ();
+              double *alpha_fvec = alpha.rwdata ();
 
               // GraphicsMagick stores the alpha values inverted, i.e.,
               // 1 for transparent and 0 for opaque so we fix that here.
@@ -527,7 +526,7 @@
     case Magick::GrayscaleType:         // Grayscale image
       {
         img = T (dim_vector (nRows, nCols, 1, nFrames));
-        P *img_fvec = img.fortran_vec ();
+        P *img_fvec = img.rwdata ();
 
         octave_idx_type idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
@@ -555,8 +554,8 @@
       {
         img = T (dim_vector (nRows, nCols, 1, nFrames));
         T alpha (dim_vector (nRows, nCols, 1, nFrames));
-        P *img_fvec = img.fortran_vec ();
-        P *a_fvec   = alpha.fortran_vec ();
+        P *img_fvec = img.rwdata ();
+        P *a_fvec   = alpha.rwdata ();
 
         octave_idx_type idx = 0;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
@@ -587,7 +586,7 @@
     case Magick::TrueColorType:         // Truecolor image
       {
         img = T (dim_vector (nRows, nCols, 3, nFrames));
-        P *img_fvec = img.fortran_vec ();
+        P *img_fvec = img.rwdata ();
 
         const octave_idx_type frame_stride = color_stride * 3;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
@@ -625,8 +624,8 @@
       {
         img = T (dim_vector (nRows, nCols, 3, nFrames));
         T alpha (dim_vector (nRows, nCols, 1, nFrames));
-        P *img_fvec = img.fortran_vec ();
-        P *a_fvec   = alpha.fortran_vec ();
+        P *img_fvec = img.rwdata ();
+        P *a_fvec   = alpha.rwdata ();
 
         const octave_idx_type frame_stride = color_stride * 3;
 
@@ -668,7 +667,7 @@
     case Magick::ColorSeparationType:  // Cyan/Magenta/Yellow/Black (CMYK) image
       {
         img = T (dim_vector (nRows, nCols, 4, nFrames));
-        P *img_fvec = img.fortran_vec ();
+        P *img_fvec = img.rwdata ();
 
         const octave_idx_type frame_stride = color_stride * 4;
         for (octave_idx_type frame = 0; frame < nFrames; frame++)
@@ -708,8 +707,8 @@
       {
         img = T (dim_vector (nRows, nCols, 4, nFrames));
         T alpha (dim_vector (nRows, nCols, 1, nFrames));
-        P *img_fvec = img.fortran_vec ();
-        P *a_fvec   = alpha.fortran_vec ();
+        P *img_fvec = img.rwdata ();
+        P *a_fvec   = alpha.rwdata ();
 
         const octave_idx_type frame_stride = color_stride * 4;
 
@@ -969,7 +968,7 @@
   typedef typename T::element_type P;
   uint32NDArray out (img.dims ());
 
-  octave_uint32 *out_fvec = out.fortran_vec ();
+  octave_uint32 *out_fvec = out.rwdata ();
   const P       *img_fvec = img.data ();
 
   const octave_uint32 max = octave_uint32::max ();
@@ -1877,7 +1876,9 @@
       octave_idx_type n = 0;
       while (std::getline (sstream, sub, char (',')))
         {
-          sscanf (sub.c_str (), "%f", &number);
+          if (sscanf (sub.c_str (), "%f", &number) != 1)
+            error ("fill_exif_ints: failed to read EXIF value as float");
+
           values(n++) = number;
         }
       map.setfield (key, octave_value (values));
@@ -1901,7 +1902,9 @@
       octave_idx_type n = 0;
       while (std::getline (sstream, sub, ','))
         {
-          sscanf (sub.c_str (), "%i/%i", &numerator, &denominator);
+          if (sscanf (sub.c_str (), "%i/%i", &numerator, &denominator) != 2)
+            error ("fill_exif_floats: failed to read EXIF numerator/demoninator pair");
+
           values(n++) = double (numerator) / double (denominator);
         }
       map.setfield (key, octave_value (values));
@@ -2090,7 +2093,7 @@
         // be all zeros.  So rather than send a matrix of zeros, we will
         // check for that, and send an empty vector instead.
         RowVector chromaticities (8);
-        double *chroma_fvec = chromaticities.fortran_vec ();
+        double *chroma_fvec = chromaticities.rwdata ();
         img.chromaWhitePoint    (&chroma_fvec[0], &chroma_fvec[1]);
         img.chromaRedPrimary    (&chroma_fvec[2], &chroma_fvec[3]);
         img.chromaGreenPrimary  (&chroma_fvec[4], &chroma_fvec[5]);
--- a/libinterp/corefcn/__pchip_deriv__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/__pchip_deriv__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -75,14 +75,14 @@
 
               F77_INT ierr;
               const F77_INT incfd = (rows ? to_f77_int (2*nyr) : 2);
-              volatile const octave_idx_type inc = (rows ? 2 : 2*nyr);
-              volatile octave_idx_type k = 0;
+              const octave_idx_type inc = (rows ? 2 : 2*nyr);
+              octave_idx_type k = 0;
 
-              for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
+              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
                 {
                   F77_XFCN (pchim, PCHIM, (nx, xvec.data (),
                                            reinterpret_cast<float const *> (ymat.data ()) + k * inc,
-                                           reinterpret_cast<float *> (dmat.fortran_vec ()) + k * inc,
+                                           reinterpret_cast<float *> (dmat.rwdata ()) + k * inc,
                                            incfd, ierr));
 
                   if (ierr < 0)
@@ -91,7 +91,7 @@
 
                   F77_XFCN (pchim, PCHIM, (nx, xvec.data (),
                                            reinterpret_cast<float const *> (ymat.data ()) + 1 + k * inc,
-                                           reinterpret_cast<float *> (dmat.fortran_vec ()) + 1 + k * inc,
+                                           reinterpret_cast<float *> (dmat.rwdata ()) + 1 + k * inc,
                                            incfd, ierr));
 
                   if (ierr < 0)
@@ -117,14 +117,14 @@
 
               F77_INT ierr;
               const F77_INT incfd = (rows ? to_f77_int (nyr) : 1);
-              volatile const octave_idx_type inc = (rows ? 1 : nyr);
-              volatile octave_idx_type k = 0;
+              const octave_idx_type inc = (rows ? 1 : nyr);
+              octave_idx_type k = 0;
 
-              for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
+              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
                 {
                   F77_XFCN (pchim, PCHIM, (nx, xvec.data (),
                                            ymat.data () + k * inc,
-                                           dmat.fortran_vec () + k * inc,
+                                           dmat.rwdata () + k * inc,
                                            incfd, ierr));
 
                   k++;
@@ -158,14 +158,14 @@
 
               F77_INT ierr;
               const F77_INT incfd = (rows ? to_f77_int (2*nyr) : 2);
-              volatile const octave_idx_type inc = (rows ? 2 : 2*nyr);
-              volatile octave_idx_type k = 0;
+              const octave_idx_type inc = (rows ? 2 : 2*nyr);
+              octave_idx_type k = 0;
 
-              for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
+              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
                 {
                   F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),
                                              reinterpret_cast<double const *> (ymat.data ()) + k * inc,
-                                             reinterpret_cast<double *> (dmat.fortran_vec ()) + k * inc,
+                                             reinterpret_cast<double *> (dmat.rwdata ()) + k * inc,
                                              incfd, ierr));
 
                   if (ierr < 0)
@@ -174,7 +174,7 @@
 
                   F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),
                                              reinterpret_cast<double const *> (ymat.data ()) + 1 + k * inc,
-                                             reinterpret_cast<double *> (dmat.fortran_vec ()) + 1 + k * inc,
+                                             reinterpret_cast<double *> (dmat.rwdata ()) + 1 + k * inc,
                                              incfd, ierr));
 
                   if (ierr < 0)
@@ -200,14 +200,14 @@
 
               F77_INT ierr;
               const F77_INT incfd = (rows ? to_f77_int (nyr) : 1);
-              volatile const octave_idx_type inc = (rows ? 1 : nyr);
-              volatile octave_idx_type k = 0;
+              const octave_idx_type inc = (rows ? 1 : nyr);
+              octave_idx_type k = 0;
 
-              for (volatile octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
+              for (octave_idx_type i = (rows ? nyr : nyc); i > 0; i--)
                 {
                   F77_XFCN (dpchim, DPCHIM, (nx, xvec.data (),
                                              ymat.data () + k * inc,
-                                             dmat.fortran_vec () + k * inc,
+                                             dmat.rwdata () + k * inc,
                                              incfd, ierr));
                   k++;
 
--- a/libinterp/corefcn/amd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/amd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -147,7 +147,7 @@
 
   OCTAVE_LOCAL_BUFFER (suitesparse_integer, P, n_col);
   Matrix xinfo (AMD_INFO, 1);
-  double *Info = xinfo.fortran_vec ();
+  double *Info = xinfo.rwdata ();
 
   // FIXME: how can we manage the memory allocation of amd
   //        in a cleaner manner?
--- a/libinterp/corefcn/auto-shlib.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/auto-shlib.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 // time.  When deriving new classes, you can either use it as a field or
 // as a parent (with multiple inheritance).
 
-class
-OCTINTERP_API
-auto_shlib : public dynamic_library
+class OCTINTERP_API auto_shlib : public dynamic_library
 {
 public:
 
--- a/libinterp/corefcn/base-text-renderer.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/base-text-renderer.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,8 +40,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-base_text_renderer : public text_processor
+class base_text_renderer : public text_processor
 {
 public:
 
--- a/libinterp/corefcn/besselj.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/besselj.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -153,8 +153,8 @@
         }
       else
         {
-          dim_vector dv0 = args(0).dims ();
-          dim_vector dv1 = args(1).dims ();
+          const dim_vector& dv0 = args(0).dims ();
+          const dim_vector& dv1 = args(1).dims ();
 
           bool args0_is_row_vector = (dv0(1) == dv0.numel ());
           bool args1_is_col_vector = (dv1(0) == dv1.numel ());
@@ -244,8 +244,8 @@
         }
       else
         {
-          dim_vector dv0 = args(0).dims ();
-          dim_vector dv1 = args(1).dims ();
+          const dim_vector& dv0 = args(0).dims ();
+          const dim_vector& dv1 = args(1).dims ();
 
           bool args0_is_row_vector = (dv0(1) == dv0.numel ());
           bool args1_is_col_vector = (dv1(0) == dv1.numel ());
@@ -598,7 +598,7 @@
     }
   else
     {
-      octave_idx_type kind = args(1).xint_value ("besselh: invalid value of K");
+      octave_idx_type kind = args(1).yint_value ("besselh: invalid value of K");
 
       octave_value_list tmp_args;
 
@@ -687,13 +687,13 @@
   int kind = 0;
   if (nargin > 1)
     {
-      kind = args(0).xint_value ("airy: K must be an integer value");
+      kind = args(0).yint_value ("airy: K must be an integer value");
 
       if (kind < 0 || kind > 3)
         error ("airy: K must be 0, 1, 2, or 3");
     }
 
-  bool scale = (nargin == 3) && args(2).xbool_value ("airy: scale option must be a logical value");
+  bool scale = (nargin == 3) && args(2).ybool_value ("airy: scale option must be a logical value");
 
   int idx = (nargin == 1 ? 0 : 1);
 
--- a/libinterp/corefcn/bitfcns.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/bitfcns.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -89,8 +89,8 @@
 
   bool is_scalar_op = (nelx == 1 || nely == 1);
 
-  dim_vector dvx = x.dims ();
-  dim_vector dvy = y.dims ();
+  const dim_vector& dvx = x.dims ();
+  const dim_vector& dvy = y.dims ();
 
   bool is_array_op = (dvx == dvy);
 
@@ -475,8 +475,8 @@
                                                                         \
   bool is_scalar_op = (m_nel == 1 || n_nel == 1);                       \
                                                                         \
-  dim_vector m_dv = m.dims ();                                          \
-  dim_vector n_dv = n.dims ();                                          \
+  const dim_vector& m_dv = m.dims ();                                   \
+  const dim_vector& n_dv = n.dims ();                                   \
                                                                         \
   bool is_array_op = (m_dv == n_dv);                                    \
                                                                         \
@@ -583,7 +583,7 @@
       if (args(2).numel () > 1)
         error ("bitshift: N must be a scalar integer");
 
-      nbits = args(2).xint_value ("bitshift: N must be an integer");
+      nbits = args(2).yint_value ("bitshift: N must be an integer");
 
       if (nbits < 0)
         error ("bitshift: N must be positive");
--- a/libinterp/corefcn/c-file-ptr-stream.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/c-file-ptr-stream.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,8 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-c_file_ptr_buf : public std::streambuf
+class c_file_ptr_buf : public std::streambuf
 {
 public:
 
@@ -106,8 +105,7 @@
 // FIXME: the following three classes could probably share some code...
 
 template <typename STREAM_T, typename FILE_T, typename BUF_T>
-class
-c_file_ptr_stream : public STREAM_T
+class c_file_ptr_stream : public STREAM_T
 {
 public:
 
@@ -148,8 +146,7 @@
 
 #if defined (HAVE_ZLIB)
 
-class
-c_zfile_ptr_buf : public std::streambuf
+class c_zfile_ptr_buf : public std::streambuf
 {
 public:
 
--- a/libinterp/corefcn/call-stack.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/call-stack.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -1054,7 +1054,7 @@
 
       push (tmp_scope);
 
-      unwind_action restore_scope ([=] () { pop (); });
+      unwind_action restore_scope ([this] () { pop (); });
 
       interpreter& interp = m_evaluator.get_interpreter ();
 
@@ -1142,7 +1142,7 @@
                   symbol_info syminf (nm, value, is_formal, is_global,
                                       is_persistent);
 
-                  symbol_stats.append (syminf);
+                  symbol_stats.push_back (syminf);
                 }
               else
                 symbol_names.push_back (nm);
--- a/libinterp/corefcn/call-stack.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/call-stack.h	Fri Apr 12 15:10:26 2024 +0200
@@ -50,9 +50,7 @@
 class symbol_info_list;
 class unwind_protect;
 
-class
-OCTINTERP_API
-call_stack
+class OCTINTERP_API call_stack
 {
 public:
 
--- a/libinterp/corefcn/cellfun.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/cellfun.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -197,7 +197,7 @@
 
       for (octave_idx_type count = 0; count < k; count++)
         {
-          dim_vector dv = f_args.elem (count).dims ();
+          const dim_vector& dv = f_args.elem (count).dims ();
           if (d < dv.ndims ())
             result(count) = static_cast<double> (dv(d));
           else
@@ -1789,7 +1789,7 @@
   if (! dimv.isempty ())
     error ("num2cell (A, dim) not implemented for class objects");
 
-  dim_vector dv = get_object_dims (array);
+  const dim_vector& dv = get_object_dims (array);
 
   retval.resize (dv);
 
@@ -1990,8 +1990,9 @@
 do_mat2cell_2d (const Array2D& a, const Array<octave_idx_type> *d, int nd)
 {
   Cell retval;
-  error_unless (nd == 1 || nd == 2);
-  error_unless (a.ndims () == 2);
+
+  panic_unless (nd == 1 || nd == 2);
+  panic_unless (a.ndims () == 2);
 
   if (mat2cell_mismatch (a.dims (), d, nd))
     return retval;
@@ -2047,7 +2048,8 @@
 do_mat2cell_nd (const ArrayND& a, const Array<octave_idx_type> *d, int nd)
 {
   Cell retval;
-  error_unless (nd >= 1);
+
+  panic_unless (nd >= 1);
 
   if (mat2cell_mismatch (a.dims (), d, nd))
     return retval;
@@ -2129,7 +2131,8 @@
 do_mat2cell (octave_value& a, const Array<octave_idx_type> *d, int nd)
 {
   Cell retval;
-  error_unless (nd >= 1);
+
+  panic_unless (nd >= 1);
 
   if (mat2cell_mismatch (a.dims (), d, nd))
     return retval;
--- a/libinterp/corefcn/chol.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/chol.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -1187,9 +1187,9 @@
 positive definite matrix @w{@var{A} = @var{R}'*@var{R}}, @var{R}@tie{}upper
 triangular, return the Cholesky@tie{}factorization of
 @w{@var{A}(p,p)}, where @w{p} is the permutation @*
-@code{p = [1:i-1, shift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*
+@code{p = [1:i-1, circshift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*
  or @*
-@code{p = [1:j-1, shift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*
+@code{p = [1:j-1, circshift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*
 
 @seealso{chol, cholupdate, cholinsert, choldelete}
 @end deftypefn */)
@@ -1276,13 +1276,13 @@
 %!test
 %! R = chol (A);
 %!
-%! i = 1;  j = 3;  p = [1:i-1, shift(i:j,-1), j+1:4];
+%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
 %! assert (norm (R1'*R1 - A(p,p), Inf), 0, 1e1*eps);
 %!
-%! j = 1;  i = 3;  p = [1:j-1, shift(j:i,+1), i+1:4];
+%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1) - R1, Inf), 0);
@@ -1291,13 +1291,13 @@
 %!test
 %! R = chol (Ac);
 %!
-%! i = 1;  j = 3;  p = [1:i-1, shift(i:j,-1), j+1:4];
+%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
 %! assert (norm (R1'*R1 - Ac(p,p), Inf), 0, 1e1*eps);
 %!
-%! j = 1;  i = 3;  p = [1:j-1, shift(j:i,+1), i+1:4];
+%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
@@ -1306,13 +1306,13 @@
 %!test
 %! R = chol (single (A));
 %!
-%! i = 1;  j = 3;  p = [1:i-1, shift(i:j,-1), j+1:4];
+%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
 %! assert (norm (R1'*R1 - single (A(p,p)), Inf), 0, 1e1* eps ("single"));
 %!
-%! j = 1;  i = 3;  p = [1:j-1, shift(j:i,+1), i+1:4];
+%! j = 1;  i = 3;  p = [1:j-1, circshift(j:i,+1), i+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
@@ -1321,13 +1321,13 @@
 %!test
 %! R = chol (single (Ac));
 %!
-%! i = 1;  j = 3;  p = [1:i-1, shift(i:j,-1), j+1:4];
+%! i = 1;  j = 3;  p = [1:i-1, circshift(i:j,-1), j+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
 %! assert (norm (R1'*R1 - single (Ac(p,p)), Inf), 0, 1e1* eps ("single"));
 %!
-%! j = 1; i = 3; p = [1:j-1, shift(j:i,+1), i+1:4];
+%! j = 1; i = 3; p = [1:j-1, circshift(j:i,+1), i+1:4];
 %! R1 = cholshift (R, i, j);
 %!
 %! assert (norm (triu (R1)-R1, Inf), 0);
--- a/libinterp/corefcn/conv2.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/conv2.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -435,7 +435,8 @@
 %! c = convn (a, b, "full");
 %!assert (convn (a, b, "same"), c(2:11,2:11,2:11))
 %!test <39314>
-%! assert (convn (a, b, "valid"), c(3:10,3:10,3:10));
+%! assert (all ((convn (a, b, "valid") == c(3:10,3:10,3:10))(:)),
+%!         "central part of convn 'full' differs from convn 'valid'");
 %!
 %!test
 %! old_state = rand ("state");
@@ -447,7 +448,8 @@
 %! c = convn (a, b, "full");
 %!assert (convn (a, b, "same"), c(2:11,2:11,:))
 %!test <39314>
-%! assert (convn (a, b, "valid"), c(3:10,3:10,:));
+%! assert (all ((convn (a, b, "valid") == c(3:10,3:10,:))(:)),
+%!         "central part of convn 'full' differs from convn 'valid'");
 %!
 %!test
 %! old_state = rand ("state");
@@ -470,7 +472,8 @@
 %! c = convn (a, b, "full");
 %!assert (convn (a, b, "same"), c(3:12,2:16,2:8,2:9,:))
 %!test <39314>
-%! assert (convn (a, b, "valid"), c(4:10,3:15,2:7,3:8,:));
+%! assert (all ((convn (a, b, "valid") == c(4:10,3:15,2:7,3:8,:))(:)),
+%!         "central part of convn 'full' differs from convn 'valid'");
 
 %!test
 %! a = reshape (floor (magic (16) /10), [4 8 4 2]);
--- a/libinterp/corefcn/daspk.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/daspk.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -68,7 +68,7 @@
 {
   ColumnVector retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
@@ -119,7 +119,7 @@
 {
   Matrix retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
--- a/libinterp/corefcn/dasrt.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/dasrt.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,7 +69,7 @@
 {
   ColumnVector retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
@@ -159,7 +159,7 @@
 {
   Matrix retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
--- a/libinterp/corefcn/dassl.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/dassl.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -67,7 +67,7 @@
 {
   ColumnVector retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
@@ -118,7 +118,7 @@
 {
   Matrix retval;
 
-  error_unless (x.numel () == xdot.numel ());
+  panic_unless (x.numel () == xdot.numel ());
 
   octave_value_list args;
 
--- a/libinterp/corefcn/data.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/data.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -96,7 +96,7 @@
     print_usage ();
 
   int dim = (nargin == 1 ? -1
-             : args(1).xint_value ("all: DIM must be an integer")-1);
+             : args(1).yint_value ("all: DIM must be an integer")-1);
 
   if (dim < -1)
     error ("all: invalid dimension argument = %d", dim + 1);
@@ -161,7 +161,7 @@
     print_usage ();
 
   int dim = (nargin == 1 ? -1
-             : args(1).xint_value ("any: DIM must be an integer")-1);
+             : args(1).yint_value ("any: DIM must be an integer")-1);
 
   if (dim < -1)
     error ("any: invalid dimension argument = %d", dim + 1);
@@ -656,8 +656,23 @@
 
 #undef MAKE_INT_BRANCH
 
-        default:
-          panic_impossible ();
+          case btyp_double:
+          case btyp_float:
+          case btyp_complex:
+          case btyp_float_complex:
+          case btyp_bool:
+          case btyp_char:
+          case btyp_struct:
+          case btyp_cell:
+          case btyp_func_handle:
+          case btyp_unknown:
+            error ("rem: unexpected: found %s instead of integer - please report this bug", btyp_class_name[btyp0].c_str ());
+            break;
+
+          // We should have handled all possible enum values above.
+          // Rely on compiler diagnostics to warn if we haven't.  For
+          // example, GCC's -Wswitch option, enabled by -Wall, will
+          // provide a warning.
         }
     }
   else if (args(0).is_single_type () || args(1).is_single_type ())
@@ -840,8 +855,23 @@
 
 #undef MAKE_INT_BRANCH
 
-        default:
-          panic_impossible ();
+          case btyp_double:
+          case btyp_float:
+          case btyp_complex:
+          case btyp_float_complex:
+          case btyp_bool:
+          case btyp_char:
+          case btyp_struct:
+          case btyp_cell:
+          case btyp_func_handle:
+          case btyp_unknown:
+            error ("mod: unexpected: found %s instead of integer - please report this bug", btyp_class_name[btyp0].c_str ());
+            break;
+
+          // We should have handled all possible enum values above.
+          // Rely on compiler diagnostics to warn if we haven't.  For
+          // example, GCC's -Wswitch option, enabled by -Wall, will
+          // provide a warning.
         }
     }
   else if (args(0).is_single_type () || args(1).is_single_type ())
@@ -1237,7 +1267,7 @@
     retval = args(0).diag ();
   else if (nargin == 2)
     {
-      octave_idx_type k = args(1).xidx_type_value ("diag: invalid argument K");
+      octave_idx_type k = args(1).yidx_type_value ("diag: invalid argument K");
 
       retval = args(0).diag (k);
     }
@@ -1248,8 +1278,8 @@
       if (arg0.ndims () != 2 || (arg0.rows () != 1 && arg0.columns () != 1))
         error ("diag: V must be a vector");
 
-      octave_idx_type m = args(1).xidx_type_value ("diag: invalid dimension M");
-      octave_idx_type n = args(2).xidx_type_value ("diag: invalid dimension N");
+      octave_idx_type m = args(1).yidx_type_value ("diag: invalid dimension M");
+      octave_idx_type n = args(2).yidx_type_value ("diag: invalid dimension N");
 
       retval = arg0.diag (m, n);
     }
@@ -2006,7 +2036,7 @@
               // the right type.
               tmp = cat_op (tmp, args(j), ra_idx);
 
-              dim_vector dv_tmp = args(j).dims ();
+              const dim_vector& dv_tmp = args(j).dims ();
 
               if (dim >= dv_len)
                 {
@@ -2345,7 +2375,7 @@
   if (args.length () == 0)
     print_usage ();
 
-  int dim = args(0).xint_value ("cat: DIM must be an integer") - 1;
+  int dim = args(0).yint_value ("cat: DIM must be an integer") - 1;
 
   if (dim < 0)
     error ("cat: DIM must be a valid dimension");
@@ -2938,11 +2968,11 @@
 
   if (nargin >= 1)
     {
-      dim_vector a_dims = args(0).dims ();
+      const dim_vector& a_dims = args(0).dims ();
 
       for (int i = 1; i < nargin; ++i)
         {
-          dim_vector b_dims = args(i).dims ();
+          const dim_vector& b_dims = args(i).dims ();
 
           if (a_dims != b_dims)
             return ovl (false);
@@ -3004,9 +3034,14 @@
 DEFUN (rows, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{nr} =} rows (@var{A})
+@deftypefnx () {@var{nr} =} height (@var{A})
 Return the number of rows of @var{A}.
 
 This is equivalent to @code{size (@var{A}, 1)}.
+
+Programming Note: @code{height} is an alias for @code{rows} and can be
+used interchangeably.
+
 @seealso{columns, size, length, numel, isscalar, isvector, ismatrix}
 @end deftypefn */)
 {
@@ -3019,6 +3054,8 @@
   return ovl ((octave_value (args(0)).size ())(0));
 }
 
+DEFALIAS (height, rows);
+
 /*
 %!assert (rows (ones (2,5)), 2)
 %!assert (rows (ones (5,2)), 5)
@@ -3049,9 +3086,14 @@
 DEFUN (columns, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {@var{nc} =} columns (@var{A})
+@deftypefnx {} {@var{nc} =} width (@var{A})
 Return the number of columns of @var{A}.
 
 This is equivalent to @code{size (@var{A}, 2)}.
+
+Programming Note: @code{width} is an alias for @code{columns} and can be
+used interchangeably.
+
 @seealso{rows, size, length, numel, isscalar, isvector, ismatrix}
 @end deftypefn */)
 {
@@ -3064,6 +3106,8 @@
   return ovl ((octave_value (args(0)).size ())(1));
 }
 
+DEFALIAS (width, columns);
+
 DEFUN (sum, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{y} =} sum (@var{x})
@@ -5670,9 +5714,9 @@
   octave_value arg_1 = args(0);
   octave_value arg_2 = args(1);
 
-  dim_vector sz1 = arg_1.dims ();
+  const dim_vector& sz1 = arg_1.dims ();
   bool isvector1 = sz1.ndims () == 2 && (sz1(0) == 1 || sz1(1) == 1);
-  dim_vector sz2 = arg_2.dims ();
+  const dim_vector& sz2 = arg_2.dims ();
   bool isvector2 = sz2.ndims () == 2 && (sz2(0) == 1 || sz2(1) == 1);
 
   if (! isvector1 || ! isvector2)
@@ -7075,13 +7119,19 @@
             error (R"(sort: MODE must be either "ascend" or "descend")");
         }
       else
-        dim = args(1).nint_value () - 1;
+        {
+          if (! args(1).is_scalar_type ())
+            error ("sort: DIM must be a positive scalar integer");
+          dim = args(1).nint_value () - 1;
+          if (dim < 0)
+            error ("sort: DIM must be a positive scalar integer");
+        }
     }
 
   if (nargin > 2)
     {
       if (have_sortmode)
-        error ("sort: DIM must be a valid dimension");
+        error ("sort: DIM argument must precede MODE argument");
 
       std::string mode = args(2).xstring_value ("sort: MODE must be a string");
 
@@ -7098,11 +7148,6 @@
     {
       dim = dv.first_non_singleton ();
     }
-  else
-    {
-      if (dim < 0)
-        error ("sort: DIM must be a valid dimension");
-    }
 
   octave_value_list retval (return_idx ? 2 : 1);
 
@@ -7340,8 +7385,15 @@
 %! [v, i] = sort (a);
 %! assert (i, [1, 4, 2, 5, 3]);
 
-%!error sort ()
-%!error sort (1, 2, 3, 4)
+%!error <Invalid call> sort ()
+%!error <Invalid call> sort (1, 2, 3, 4)
+%!error <MODE must be either "ascend" or "descend"> sort (1, "foobar")
+%!error <DIM must be a positive scalar integer> sort (1, [1 2 3])
+%!error <DIM argument must precede MODE argument> sort (1, "ascend", 1)
+%!error <MODE must be a string> sort (1, 1, 1)
+%!error <MODE must be either "ascend" or "descend"> sort (1, 1, "foobar")
+%!error <DIM must be a positive scalar integer> sort (1, 0)
+
 */
 
 // Sort the rows of the matrix @var{a} according to the order
@@ -7874,7 +7926,7 @@
   else if (idx.extent (n) > n)
     error ("accumdim: index out of range");
 
-  dim_vector vals_dim = vals.dims ();
+  const dim_vector& vals_dim = vals.dims ();
   dim_vector rdv = vals_dim;
 
   if (dim < 0)
@@ -7958,7 +8010,7 @@
           const NDT& tval, const NDT& fval)
 {
   typedef typename NDT::element_type T;
-  dim_vector dv = mask.dims ();
+  const dim_vector& dv = mask.dims ();
   NDT retval (dv);
 
   bool tscl = tval.numel () == 1;
@@ -7967,7 +8019,7 @@
   if ((! tscl && tval.dims () != dv) || (! fscl && fval.dims () != dv))
     error ("merge: MASK, TVAL, and FVAL dimensions must match");
 
-  T *rv = retval.fortran_vec ();
+  T *rv = retval.rwdata ();
   octave_idx_type n = retval.numel ();
 
   const T *tv = tval.data ();
@@ -8140,7 +8192,7 @@
           idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
           retval = SparseT (retval.index (col1, sl1))
                    - SparseT (retval.index (col2, sl2));
-          error_unless (retval.columns () == k-1);
+          panic_unless (retval.columns () == k-1);
           order--;
           k--;
         }
@@ -8153,7 +8205,7 @@
           idx_vector col1 (':'), col2 (':'), sl1 (1, k), sl2 (0, k-1);
           retval = SparseT (retval.index (sl1, col1))
                    - SparseT (retval.index (sl2, col2));
-          error_unless (retval.rows () == k-1);
+          panic_unless (retval.rows () == k-1);
           order--;
           k--;
         }
@@ -8348,7 +8400,7 @@
     }
 
   retval.clear (1, l);
-  T *dest = retval.fortran_vec ();
+  T *dest = retval.rwdata ();
   l = 0;
   for (octave_idx_type i = 0; i < n; i++)
     {
--- a/libinterp/corefcn/debug.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/debug.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -592,35 +592,67 @@
   return ovl ();
 }
 
-static void
-do_dbtype (std::ostream& os, const std::string& name, int start, int end)
+static bool
+parse_start_end (const std::string& arg, int& start, int& end, const char *who)
 {
-  std::string ff = octave::fcn_file_in_path (name);
+  start = 0;
+  end = 0;
+
+  std::size_t ind = arg.find (':');
 
-  if (ff.empty ())
-    os << "dbtype: unknown function " << name << "\n";
-  else
+  if (ind != std::string::npos)  // (start:end)
     {
-      std::ifstream fs = octave::sys::ifstream (ff.c_str (), std::ios::in);
+      std::string start_str = arg.substr (0, ind);
+      std::string end_str = arg.substr (ind+1);
+
+      try
+        {
+          start = std::stoi (start_str);
 
-      if (! fs)
-        os << "dbtype: unable to open '" << ff << "' for reading!\n";
-      else
+          if (end_str == "end")
+            end = std::numeric_limits<int>::max ();
+          else
+            end = std::stoi (end_str);
+        }
+      catch (const std::invalid_argument&)
         {
-          int line = 1;
-          std::string text;
+          error ("%s: invalid integer conversion while parsing range '%s'", who, arg.c_str ());
+        }
+      catch (const std::out_of_range&)
+        {
+          error ("%s: integer value out of bounds while parsing range '%s'", who, arg.c_str ());
+        }
+
+      if (std::min (start, end) <= 0)
+        error ("%s: start and end lines must be >= 1\n", who);
 
-          while (std::getline (fs, text) && line <= end)
-            {
-              if (line >= start)
-                os << line << "\t" << text << "\n";
+      if (start > end)
+        error ("%s: start line must be less than end line\n", who);
+    }
+  else  // (dbtype lineno)
+    {
+      try
+        {
+          int line = std::stoi (arg);
+
+          if (line <= 0)
+            error ("%s: start and end lines must be >= 1\n", who);
 
-              line++;
-            }
+          start = line;
+          end = line;
+        }
+      catch (const std::invalid_argument&)
+        {
+          // May be a name instead of a number.
+          return false;
+        }
+      catch (const std::out_of_range&)
+        {
+          error ("%s: integer value out of bounds while parsing '%s'", who, arg.c_str ());
         }
     }
 
-  os.flush ();
+  return true;
 }
 
 DEFMETHOD (dbtype, interp, args, ,
@@ -647,121 +679,34 @@
 @seealso{dblist, dbwhere, dbstatus, dbstop}
 @end deftypefn */)
 {
-  octave_user_code *dbg_fcn;
-
   string_vector argv = args.make_argv ("dbtype");
 
-  octave::tree_evaluator& tw = interp.get_evaluator ();
+  // Empty means current function on call stack.
+  std::string fcn_name;
+
+  int start = 0;
+  int end = std::numeric_limits<int>::max ();
 
   switch (args.length ())
     {
     case 0:  // dbtype
-      dbg_fcn = tw.get_user_code ();
-
-      if (! dbg_fcn)
-        error ("dbtype: must be inside a user function to give no arguments to dbtype\n");
-
-      do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
-                 0, std::numeric_limits<int>::max ());
-
       break;
 
     case 1:  // (dbtype start:end) || (dbtype fcn) || (dbtype lineno)
       {
         std::string arg = argv[1];
 
-        std::size_t ind = arg.find (':');
-
-        if (ind != std::string::npos)  // (dbtype start:end)
-          {
-            dbg_fcn = tw.get_user_code ();
-
-            if (dbg_fcn)
-              {
-                std::string start_str = arg.substr (0, ind);
-                std::string end_str = arg.substr (ind + 1);
-
-                int start, end;
-                start = atoi (start_str.c_str ());
-                if (end_str == "end")
-                  end = std::numeric_limits<int>::max ();
-                else
-                  end = atoi (end_str.c_str ());
-
-                if (std::min (start, end) <= 0)
-                  error ("dbtype: start and end lines must be >= 1\n");
-
-                if (start > end)
-                  error ("dbtype: start line must be less than end line\n");
-
-                do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
-                           start, end);
-              }
-          }
-        else  // (dbtype fcn) || (dbtype lineno)
-          {
-            int line = atoi (arg.c_str ());
-
-            if (line == 0)  // (dbtype fcn)
-              {
-                dbg_fcn = tw.get_user_code (arg);
-
-                if (! dbg_fcn)
-                  error ("dbtype: function <%s> not found\n", arg.c_str ());
-
-                do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
-                           0, std::numeric_limits<int>::max ());
-              }
-            else  // (dbtype lineno)
-              {
-                if (line <= 0)
-                  error ("dbtype: start and end lines must be >= 1\n");
-
-                dbg_fcn = tw.get_user_code ();
-
-                if (dbg_fcn)
-                  do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (),
-                             line, line);
-              }
-          }
+        if (! parse_start_end (arg, start, end, "dbtype"))
+          fcn_name = arg;
       }
       break;
 
     case 2:  // (dbtype fcn start:end) || (dbtype fcn start)
       {
-        dbg_fcn = tw.get_user_code (argv[1]);
-
-        if (! dbg_fcn)
-          error ("dbtype: function <%s> not found\n", argv[1].c_str ());
-
-        std::string arg = argv[2];
-        int start, end;
-        std::size_t ind = arg.find (':');
-
-        if (ind != std::string::npos)
-          {
-            std::string start_str = arg.substr (0, ind);
-            std::string end_str = arg.substr (ind + 1);
+        fcn_name = argv[1];
 
-            start = atoi (start_str.c_str ());
-            if (end_str == "end")
-              end = std::numeric_limits<int>::max ();
-            else
-              end = atoi (end_str.c_str ());
-          }
-        else
-          {
-            start = atoi (arg.c_str ());
-            end = start;
-          }
-
-        if (std::min (start, end) <= 0)
-          error ("dbtype: start and end lines must be >= 1\n");
-
-        if (start > end)
-          error ("dbtype: start line must be less than end line\n");
-
-        do_dbtype (octave_stdout, dbg_fcn->fcn_file_name (), start, end);
+        if (! parse_start_end (argv[2], start, end, "dbtype"))
+          error ("dbtype: expecting start:end or location argument, found '%s'", argv[2].c_str ());
       }
       break;
 
@@ -769,9 +714,46 @@
       error ("dbtype: expecting zero, one, or two arguments\n");
     }
 
+  if (fcn_name.empty ())
+    {
+      octave::tree_evaluator& tw = interp.get_evaluator ();
+
+      tw.debug_type (octave_stdout, start, end);
+    }
+  else
+    {
+      std::string file_name = octave::fcn_file_in_path (fcn_name);
+
+      if (file_name.empty ())
+        error ("dbtype: unknown function '%s'", fcn_name.c_str ());
+
+      octave::display_file_lines (octave_stdout, file_name, start, end, -1, "", "dbtype");
+    }
+
   return ovl ();
 }
 
+static int
+parse_integer_argument (const std::string& arg, const char *who)
+{
+  int n = 0;
+
+  try
+    {
+      n = std::stoi (arg);
+    }
+  catch (const std::invalid_argument&)
+    {
+      error ("%s: invalid value of N, found '%s'", arg.c_str (), who);
+    }
+  catch (const std::out_of_range&)
+    {
+      error ("%s: value of N ('%s') is out of range", arg.c_str (), who);
+    }
+
+  return n;
+}
+
 DEFMETHOD (dblist, interp, args, ,
            doc: /* -*- texinfo -*-
 @deftypefn  {} {} dblist
@@ -785,16 +767,17 @@
 {
   int n = 10;
 
-  if (args.length () == 1)
+  int numel = args.length ();
+
+  if (numel > 1)
+    print_usage ();
+
+  if (numel == 1)
     {
       octave_value arg = args(0);
 
       if (arg.is_string ())
-        {
-          std::string s_arg = arg.string_value ();
-
-          n = atoi (s_arg.c_str ());
-        }
+        n = parse_integer_argument (arg.string_value (), "dblist");
       else
         n = args(0).int_value ();
 
@@ -804,44 +787,7 @@
 
   octave::tree_evaluator& tw = interp.get_evaluator ();
 
-  octave_user_code *dbg_fcn = tw.get_user_code ();
-
-  if (! dbg_fcn)
-    error ("dblist: must be inside a user function to use dblist\n");
-
-  bool have_file = true;
-
-  std::string name = dbg_fcn->fcn_file_name ();
-
-  if (name.empty ())
-    {
-      have_file = false;
-      name = dbg_fcn->name ();
-    }
-
-  int l = tw.debug_user_code_line ();
-
-  if (l > 0)
-    {
-      if (have_file)
-        {
-          int l_min = std::max (l - n/2, 0);
-          int l_max = l + n/2;
-          do_dbtype (octave_stdout, name, l_min, l-1);
-
-          std::string line = dbg_fcn->get_code_line (l);
-
-          if (! line.empty ())
-            octave_stdout << l << "-->\t" << line << std::endl;
-
-          do_dbtype (octave_stdout, name, l+1, l_max);
-        }
-    }
-  else
-    {
-      octave_stdout << "dblist: unable to determine source code line"
-                    << std::endl;
-    }
+  tw.debug_list (octave_stdout, n);
 
   return ovl ();
 }
@@ -877,7 +823,7 @@
               if (s_arg == "-completenames")
                 continue;
 
-              n = atoi (s_arg.c_str ());
+              n = parse_integer_argument (s_arg, "dbstack");
             }
           else
             n = arg.int_value ();
@@ -1023,11 +969,7 @@
       octave_value arg = args(0);
 
       if (arg.is_string ())
-        {
-          std::string s_arg = arg.string_value ();
-
-          n = atoi (s_arg.c_str ());
-        }
+        n = parse_integer_argument (arg.string_value (), who.c_str ());
       else
         n = args(0).int_value ();
     }
@@ -1117,10 +1059,10 @@
         n = -2;
       else
         {
-          n = atoi (arg.c_str ());
+          n = parse_integer_argument (arg, "dbstep");
 
           if (n < 1)
-            error ("dbstep: invalid argument");
+            error ("dbstep: N must be greater than zero");
         }
     }
   else
--- a/libinterp/corefcn/defun-int.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/defun-int.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 
 class interpreter;
 
-extern OCTINTERP_API void print_usage (void);
+extern OCTINTERP_API void print_usage ();
 
 extern OCTINTERP_API void print_usage (const std::string&);
 
@@ -62,14 +62,14 @@
                       const dynamic_library& shl, bool relative = false);
 
 // Gets the shlib of the currently executing DLD function, if any.
-extern OCTINTERP_API dynamic_library get_current_shlib (void);
+extern OCTINTERP_API dynamic_library get_current_shlib ();
 
 OCTAVE_END_NAMESPACE(octave)
 
 // Some of these functions are widely used, so maybe we should avoid
 // deprecating them for now?
 
-inline void print_usage (void)
+inline void print_usage ()
 {
   octave::print_usage ();
 }
@@ -110,7 +110,7 @@
 }
 
 // Gets the shlib of the currently executing DLD function, if any.
-inline octave::dynamic_library get_current_shlib (void)
+inline octave::dynamic_library get_current_shlib ()
 {
   return octave::get_current_shlib ();
 }
--- a/libinterp/corefcn/dlmread.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/dlmread.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -47,10 +47,10 @@
 #include "ovl.h"
 #include "utils.h"
 
-static const octave_idx_type idx_max
+static constexpr octave_idx_type idx_max
   = std::numeric_limits<octave_idx_type>::max () - 1;
 
-static const double idx_max_dbl = double (idx_max);
+static constexpr double idx_max_dbl = double (idx_max);
 
 static bool
 read_cell_spec (std::istream& is, octave_idx_type& row, octave_idx_type& col)
--- a/libinterp/corefcn/dot.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/dot.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -144,7 +144,7 @@
 
           F77_XFCN (cdotc3, CDOTC3, (m, n, k,
                                      F77_CONST_CMPLX_ARG (x.data ()), F77_CONST_CMPLX_ARG (y.data ()),
-                                     F77_CMPLX_ARG (z.fortran_vec ())));
+                                     F77_CMPLX_ARG (z.rwdata ())));
           retval = z;
         }
       else
@@ -156,7 +156,7 @@
 
           F77_XFCN (zdotc3, ZDOTC3, (m, n, k,
                                      F77_CONST_DBLE_CMPLX_ARG (x.data ()), F77_CONST_DBLE_CMPLX_ARG (y.data ()),
-                                     F77_DBLE_CMPLX_ARG (z.fortran_vec ())));
+                                     F77_DBLE_CMPLX_ARG (z.rwdata ())));
           retval = z;
         }
     }
@@ -170,7 +170,7 @@
           FloatNDArray z (dimz);
 
           F77_XFCN (sdot3, SDOT3, (m, n, k, x.data (), y.data (),
-                                   z.fortran_vec ()));
+                                   z.rwdata ()));
           retval = z;
         }
       else
@@ -181,7 +181,7 @@
           NDArray z (dimz);
 
           F77_XFCN (ddot3, DDOT3, (m, n, k, x.data (), y.data (),
-                                   z.fortran_vec ()));
+                                   z.rwdata ()));
           retval = z;
         }
     }
@@ -263,7 +263,7 @@
   F77_XFCN (cmatm3, CMATM3, (m, n, k, np,
                              F77_CONST_CMPLX_ARG (x.data ()),
                              F77_CONST_CMPLX_ARG (y.data ()),
-                             F77_CMPLX_ARG (z.fortran_vec ())));
+                             F77_CMPLX_ARG (z.rwdata ())));
 }
 
 template <>
@@ -275,7 +275,7 @@
   F77_XFCN (zmatm3, ZMATM3, (m, n, k, np,
                              F77_CONST_DBLE_CMPLX_ARG (x.data ()),
                              F77_CONST_DBLE_CMPLX_ARG (y.data ()),
-                             F77_DBLE_CMPLX_ARG (z.fortran_vec ())));
+                             F77_DBLE_CMPLX_ARG (z.rwdata ())));
 }
 
 template <>
@@ -285,7 +285,7 @@
 {
   F77_XFCN (smatm3, SMATM3, (m, n, k, np,
                              x.data (), y.data (),
-                             z.fortran_vec ()));
+                             z.rwdata ()));
 }
 
 template <>
@@ -295,7 +295,7 @@
 {
   F77_XFCN (dmatm3, DMATM3, (m, n, k, np,
                              x.data (), y.data (),
-                             z.fortran_vec ()));
+                             z.rwdata ()));
 }
 
 static void
--- a/libinterp/corefcn/dynamic-ld.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/dynamic-ld.h	Fri Apr 12 15:10:26 2024 +0200
@@ -39,13 +39,11 @@
 
 class interpreter;
 
-class
-dynamic_loader
+class dynamic_loader
 {
 private:
 
-  class
-  shlibs_list
+  class shlibs_list
   {
   public:
 
--- a/libinterp/corefcn/ellipj.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ellipj.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -117,16 +117,16 @@
           // u is matrix, m is scalar
           ComplexNDArray u = u_arg.xcomplex_array_value ("ellipj: U must be a scalar or matrix");
 
-          dim_vector sz_u = u.dims ();
+          const dim_vector& sz_u = u.dims ();
 
           ComplexNDArray sn (sz_u), cn (sz_u), dn (sz_u);
           NDArray err (sz_u);
 
           const Complex *pu = u.data ();
-          Complex *psn = sn.fortran_vec ();
-          Complex *pcn = cn.fortran_vec ();
-          Complex *pdn = dn.fortran_vec ();
-          double *perr = err.fortran_vec ();
+          Complex *psn = sn.rwdata ();
+          Complex *pcn = cn.rwdata ();
+          Complex *pdn = dn.rwdata ();
+          double *perr = err.rwdata ();
           octave_idx_type nel = u.numel ();
 
           for (octave_idx_type i = 0; i < nel; i++)
@@ -139,7 +139,7 @@
     {
       NDArray m = args(1).xarray_value ("ellipj: M must be a scalar or matrix");
 
-      dim_vector sz_m = m.dims ();
+      const dim_vector& sz_m = m.dims ();
 
       if (u_arg.is_scalar_type ())
         {
@@ -153,10 +153,10 @@
               NDArray err (sz_m);
 
               const double *pm = m.data ();
-              double *psn = sn.fortran_vec ();
-              double *pcn = cn.fortran_vec ();
-              double *pdn = dn.fortran_vec ();
-              double *perr = err.fortran_vec ();
+              double *psn = sn.rwdata ();
+              double *pcn = cn.rwdata ();
+              double *pdn = dn.rwdata ();
+              double *perr = err.rwdata ();
               octave_idx_type nel = m.numel ();
 
               for (octave_idx_type i = 0; i < nel; i++)
@@ -173,10 +173,10 @@
               NDArray err (sz_m);
 
               const double *pm = m.data ();
-              Complex *psn = sn.fortran_vec ();
-              Complex *pcn = cn.fortran_vec ();
-              Complex *pdn = dn.fortran_vec ();
-              double *perr = err.fortran_vec ();
+              Complex *psn = sn.rwdata ();
+              Complex *pcn = cn.rwdata ();
+              Complex *pdn = dn.rwdata ();
+              double *perr = err.rwdata ();
               octave_idx_type nel = m.numel ();
 
               for (octave_idx_type i = 0; i < nel; i++)
@@ -193,7 +193,7 @@
               // u is real array, m is array
               NDArray u = u_arg.xarray_value ("ellipj: U must be a scalar or matrix");
 
-              dim_vector sz_u = u.dims ();
+              const dim_vector& sz_u = u.dims ();
 
               if (sz_u.ndims () == 2 && sz_m.ndims () == 2
                   && sz_u(1) == 1 && sz_m(0) == 1)
@@ -222,10 +222,10 @@
 
                   const double *pu = u.data ();
                   const double *pm = m.data ();
-                  double *psn = sn.fortran_vec ();
-                  double *pcn = cn.fortran_vec ();
-                  double *pdn = dn.fortran_vec ();
-                  double *perr = err.fortran_vec ();
+                  double *psn = sn.rwdata ();
+                  double *pcn = cn.rwdata ();
+                  double *pdn = dn.rwdata ();
+                  double *perr = err.rwdata ();
                   octave_idx_type nel = m.numel ();
 
                   for (octave_idx_type i = 0; i < nel; i++)
@@ -241,7 +241,7 @@
               // u is complex array, m is array
               ComplexNDArray u = u_arg.xcomplex_array_value ("ellipj: U must be a scalar or matrix");
 
-              dim_vector sz_u = u.dims ();
+              const dim_vector& sz_u = u.dims ();
 
               if (sz_u.ndims () == 2 && sz_m.ndims () == 2
                   && sz_u(1) == 1 && sz_m(0) == 1)
@@ -270,10 +270,10 @@
 
                   const Complex *pu = u.data ();
                   const double  *pm = m.data ();
-                  Complex *psn = sn.fortran_vec ();
-                  Complex *pcn = cn.fortran_vec ();
-                  Complex *pdn = dn.fortran_vec ();
-                  double *perr = err.fortran_vec ();
+                  Complex *psn = sn.rwdata ();
+                  Complex *pcn = cn.rwdata ();
+                  Complex *pdn = dn.rwdata ();
+                  double *perr = err.rwdata ();
                   octave_idx_type nel = m.numel ();
 
                   for (octave_idx_type i = 0; i < nel; i++)
--- a/libinterp/corefcn/error.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/error.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -633,12 +633,15 @@
 void
 error_system::vpanic (const char *fmt, va_list args)
 {
-  // Is there any point in trying to write the panic message to the
-  // diary?
+  // Earlier versions of Octave printed a message directly to std::cerr
+  // and called abort.  That might be acceptable behavior for some
+  // programs but for an interactive application like Octave, aborting
+  // the entire program when an internal programming error has been
+  // detected seems unnecessary and certainly provides a much worse user
+  // experience than simply generating an ordinary error message and
+  // attempting to return to the command prompt.
 
-  std::cerr << "panic: " << format_message (fmt, args) << std::endl;
-
-  abort ();
+  ::verror (fmt, args);
 }
 
 void
@@ -1113,25 +1116,6 @@
   va_end (args);
 }
 
-OCTAVE_NORETURN
-void
-vpanic (const char *fmt, va_list args)
-{
-  octave::error_system& es = octave::__get_error_system__ ();
-
-  es.vpanic (fmt, args);
-}
-
-OCTAVE_NORETURN
-void
-panic (const char *fmt, ...)
-{
-  va_list args;
-  va_start (args, fmt);
-  vpanic (fmt, args);
-  va_end (args);
-}
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 void
--- a/libinterp/corefcn/error.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/error.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,6 +35,10 @@
 #include "unwind-prot.h"
 
 #include "oct-map.h"
+// Include panic.h here for backward compatibility with previous
+// versions of Octave that declared the global panic functions and
+// macros here.
+#include "panic.h"
 
 class octave_value_list;
 
@@ -489,46 +493,23 @@
 extern OCTINTERP_API void
 parse_error_with_id (const char *id, const char *fmt, ...);
 
-OCTAVE_NORETURN
-extern OCTINTERP_API void vpanic (const char *fmt, va_list args);
-
-OCTAVE_FORMAT_PRINTF (1, 2)
-OCTAVE_NORETURN
-extern OCTINTERP_API void panic (const char *fmt, ...);
-
-// To allow the __FILE__ and __LINE__ macros to work as expected, the
-// panic_impossible, panic_if, panic_unless, error_impossible, error_if,
-// and error_unless symbols must be defined as macros.
-
-#define panic_impossible()                                              \
-  ::panic ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
-
-#if defined (NDEBUG)
-#  define panic_if(cond)
-#else
-#  define panic_if(cond) do { if (cond) panic_impossible (); } while (0)
-#endif
-
-#if defined (NDEBUG)
-#  define panic_unless(cond)
-#else
-#  define panic_unless(cond) panic_if (! (cond))
-#endif
+// Use of the following macros (error_impossible, error_if, and
+// error_unless) is discouraged.  All of these will only display a
+// generic error of the form
+//
+//   impossible state reached in file 'FILE' at line 'N'
+//
+// If the state really is "impossible" to reach, then it is better to
+// use one of the corresponding panic* functions instead (see panic.h).
+//
+// See also the discussion here: https://octave.discourse.group/t/assert-panic-error-and-ndebug/5409
 
 #define error_impossible()                                              \
   ::error ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
 
-#if defined (NDEBUG)
-#  define error_if(cond)
-#else
-#  define error_if(cond) do { if (cond) error_impossible (); } while (0)
-#endif
+#define error_if(cond) do { if (cond) error_impossible (); } while (0)
 
-#if defined (NDEBUG)
-#  define error_unless(cond)
-#else
-#  define error_unless(cond) error_if (! (cond))
-#endif
+#define error_unless(cond) error_if (! (cond))
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
--- a/libinterp/corefcn/event-manager.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/event-manager.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -362,7 +362,19 @@
               if (idx != 2)
                 retval(idx++) = str;
               else
-                retval(idx++) = atoi (str.c_str ());
+                {
+                  // FIXME: Should we warn or error on invalid or out of
+                  // range values in STR?  When atoi was used for
+                  // conversion instead of std::stoi we did not.  Was
+                  // that intentional?
+
+                  try
+                    {
+                      retval(idx++) = std::stoi (str);
+                    }
+                  catch (const std::invalid_argument&) { }
+                  catch (const std::out_of_range&) { }
+                }
             }
         }
     }
@@ -377,7 +389,22 @@
       for (int idx = 0; idx < nel; idx++, it++)
         items.xelem (idx) = *it;
 
-      retval = ovl (items, *it++, atoi (it->c_str ()));
+      auto fpath = *it++;
+
+      int idx = 0;
+
+      // FIXME: Should we warn or error on invalid or out of range
+      // values in *IT?  When atoi was used for conversion instead of
+      // std::stoi we did not.  Was that intentional?
+
+      try
+        {
+          idx = std::stoi (*it);
+        }
+      catch (const std::invalid_argument&) { }
+      catch (const std::out_of_range&) { }
+
+      retval = ovl (items, fpath, idx);
     }
 
   return retval;
--- a/libinterp/corefcn/event-manager.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/event-manager.h	Fri Apr 12 15:10:26 2024 +0200
@@ -288,9 +288,7 @@
 //! This class provides thread-safe communication between the
 //! interpreter and a GUI.
 
-class
-OCTINTERP_API
-event_manager
+class OCTINTERP_API event_manager
 {
 public:
 
--- a/libinterp/corefcn/event-queue.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/event-queue.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-event_queue : public action_container
+class event_queue : public action_container
 {
 public:
 
@@ -88,8 +87,7 @@
 // possibility of seeing an exception (or interrupt) in the cleanup actions.
 // Not that we can do much about it, but at least we won't crash.
 
-class
-event_queue_safe : public event_queue
+class event_queue_safe : public event_queue
 {
 public:
 
--- a/libinterp/corefcn/fft2.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/fft2.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -56,11 +56,11 @@
     {
       double dval = args(1).double_value ();
       if (math::isnan (dval))
-        error ("%s: number of rows (N) cannot be NaN", fcn);
+        error ("%s: number of rows (M) cannot be NaN", fcn);
 
       n_rows = math::nint_big (dval);
       if (n_rows < 0)
-        error ("%s: number of rows (N) must be greater than zero", fcn);
+        error ("%s: number of rows (M) must be greater than zero", fcn);
     }
 
   octave_idx_type n_cols = -1;
@@ -68,11 +68,11 @@
     {
       double dval = args(2).double_value ();
       if (math::isnan (dval))
-        error ("%s: number of columns (M) cannot be NaN", fcn);
+        error ("%s: number of columns (N) cannot be NaN", fcn);
 
       n_cols = math::nint_big (dval);
       if (n_cols < 0)
-        error ("%s: number of columns (M) must be greater than zero", fcn);
+        error ("%s: number of columns (N) must be greater than zero", fcn);
     }
 
   for (int i = 0; i < dims.ndims (); i++)
@@ -89,12 +89,12 @@
   else
     dims(1) = n_cols;
 
-  if (dims.all_zero () || n_rows == 0 || n_cols == 0)
+  if (dims.any_zero ())
     {
       if (arg.is_single_type ())
-        return octave_value (FloatMatrix ());
+        return octave_value (FloatNDArray (dims));
       else
-        return octave_value (Matrix ());
+        return octave_value (NDArray (dims));
     }
 
   if (arg.is_single_type ())
@@ -156,6 +156,20 @@
   return do_fft2 (args, "fft2", 0);
 }
 
+/*
+%!testif HAVE_FFTW <*65414>
+%! sz = size (fft2 (ones (2, 0, 3)));
+%! assert (sz, [2, 0, 3]);
+
+%!testif HAVE_FFTW <*65414>
+%! sz = size (fft2 (ones (5, 4, 3), 2, 0));
+%! assert (sz, [2, 0, 3]);
+
+%!error <number of rows \(M\) cannot be NaN> fft2 (ones (5,4,3), NaN, 2)
+%!error <number of rows \(M\) .* greater than zero> fft2 (ones (5,4,3), -1, 2)
+%!error <number of columns \(N\) cannot be NaN> fft2 (ones (5,4,3), 2, NaN)
+%!error <number of columns \(N\) .* greater than zero> fft2 (ones (5,4,3), 2, -1)
+*/
 
 DEFUN (ifft2, args, ,
        doc: /* -*- texinfo -*-
@@ -177,6 +191,14 @@
 }
 
 /*
+%!testif HAVE_FFTW <*65414>
+%! sz = size (ifft2 (ones (2, 0, 3)));
+%! assert (sz, [2, 0, 3]);
+
+%!testif HAVE_FFTW <*65414>
+%! sz = size (ifft2 (ones (5, 4, 3), 2, 0));
+%! assert (sz, [2, 0, 3]);
+
 ## Author: David Billinghurst (David.Billinghurst@riotinto.com.au)
 ##         Comalco Research and Technology
 ##         02 May 2000
@@ -258,6 +280,11 @@
 %! s = ifft2 (S);
 %!
 %! assert (s, answer, 30* eps ("single"));
+
+%!error <number of rows \(M\) cannot be NaN> ifft2 (ones (5,4,3), NaN, 2)
+%!error <number of rows \(M\) .* greater than zero> ifft2 (ones (5,4,3), -1, 2)
+%!error <number of columns \(N\) cannot be NaN> ifft2 (ones (5,4,3), 2, NaN)
+%!error <number of columns \(N\) .* greater than zero> ifft2 (ones (5,4,3), 2, -1)
 */
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/fftn.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/fftn.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -76,12 +76,12 @@
         }
     }
 
-  if (dims.all_zero ())
+  if (dims.any_zero ())
     {
       if (arg.is_single_type ())
-        return octave_value (FloatMatrix ());
+        return octave_value (FloatNDArray (dims));
       else
-        return octave_value (Matrix ());
+        return octave_value (NDArray (dims));
     }
 
   if (arg.is_single_type ())
@@ -143,6 +143,16 @@
   return do_fftn (args, "fftn", 0);
 }
 
+/*
+%!testif HAVE_FFTW <*65414>
+%! sz = size (fftn (ones (2, 0, 3)));
+%! assert (sz, [2, 0, 3]);
+
+%!testif HAVE_FFTW <*65414>
+%! sz = size (fftn (ones (5, 4, 3), [2, 0, 3]));
+%! assert (sz, [2, 0, 3]);
+*/
+
 DEFUN (ifftn, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {@var{A} =} ifftn (@var{B})
@@ -162,4 +172,14 @@
   return do_fftn (args, "ifftn", 1);
 }
 
+/*
+%!testif HAVE_FFTW <*65414>
+%! sz = size (ifftn (ones (2, 0, 3)));
+%! assert (sz, [2, 0, 3]);
+
+%!testif HAVE_FFTW <*65414>
+%! sz = size (ifftn (ones (5, 4, 3), [2, 0, 3]));
+%! assert (sz, [2, 0, 3]);
+*/
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/corefcn/file-io.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/file-io.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -3223,7 +3223,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int mask = args(0).xint_value ("umask: MASK must be an integer");
+  int mask = args(0).yint_value ("umask: MASK must be an integer");
 
   if (mask < 0)
     error ("umask: MASK must be a positive integer value");
--- a/libinterp/corefcn/filter.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/filter.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -68,13 +68,13 @@
   if (norm == static_cast<T> (0.0))
     error ("filter: the first element of A must be nonzero");
 
-  dim_vector x_dims = x.dims ();
+  const dim_vector& x_dims = x.dims ();
   if (dim < 0 || dim > x_dims.ndims ())
     error ("filter: DIM must be a valid dimension");
 
   octave_idx_type x_len = x_dims(dim);
 
-  dim_vector si_dims = si.dims ();
+  const dim_vector& si_dims = si.dims ();
   octave_idx_type si_len = si_dims(0);
 
   if (si_len != ab_len - 1)
@@ -164,8 +164,8 @@
       // is common to both branches can be pulled out here without affecting
       // correctness or speed.
 
-      T *py = y.fortran_vec ();
-      T *psi = si.fortran_vec ();
+      T *py = y.rwdata ();
+      T *psi = si.rwdata ();
       const T *pb = b.data ();
       const T *px = x.data ();
       psi += si_offset;
@@ -239,7 +239,7 @@
 MArray<T>
 filter (MArray<T>& b, MArray<T>& a, MArray<T>& x, int dim = -1)
 {
-  dim_vector x_dims = x.dims ();
+  const dim_vector& x_dims = x.dims ();
 
   if (dim < 0)
     dim = x_dims.first_non_singleton ();
@@ -369,7 +369,7 @@
     print_usage ();
 
   int dim;
-  dim_vector x_dims = args(2).dims ();
+  const dim_vector& x_dims = args(2).dims ();
 
   if (nargin == 5)
     {
--- a/libinterp/corefcn/find.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/find.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -451,7 +451,7 @@
 
           octave_value result = arg.index_vector ().unmask ();
 
-          dim_vector dv = result.dims ();
+          const dim_vector& dv = result.dims ();
 
           retval(0) = (dv.all_zero () || dv.isvector ()
                        ? result : result.reshape (dv.as_column ()));
--- a/libinterp/corefcn/ft-text-renderer.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ft-text-renderer.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -97,8 +97,7 @@
 // Forward declaration
 static void ft_face_destroyed (void *object);
 
-class
-ft_manager
+class ft_manager
 {
 private:
 
@@ -457,9 +456,7 @@
   ft_manager::font_destroyed (reinterpret_cast<FT_Face> (object));
 }
 
-class
-OCTINTERP_API
-ft_text_renderer : public base_text_renderer
+class OCTINTERP_API ft_text_renderer : public base_text_renderer
 {
 public:
 
--- a/libinterp/corefcn/gcd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/gcd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -351,9 +351,9 @@
       bool inca = aa.numel () != 1;
       bool incb = bb.numel () != 1;
 
-      T *gptr = gg.fortran_vec ();
-      T *xptr = xx.fortran_vec ();
-      T *yptr = yy.fortran_vec ();
+      T *gptr = gg.rwdata ();
+      T *xptr = xx.rwdata ();
+      T *yptr = yy.rwdata ();
 
       octave_idx_type n = gg.numel ();
       for (octave_idx_type i = 0; i < n; i++)
--- a/libinterp/corefcn/gl-render.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/gl-render.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -180,7 +180,7 @@
 {
   opengl_texture retval (glfcns);
 
-  dim_vector dv (data.dims ());
+  const dim_vector& dv = data.dims ();
 
   // Expect RGB data
   if (dv.ndims () == 3 && (dv(2) == 3 || dv(2) == 4))
@@ -339,8 +339,7 @@
   return retval;
 }
 
-class
-opengl_tessellator
+class opengl_tessellator
 {
 public:
 #if defined (HAVE_FRAMEWORK_OPENGL) && defined (HAVE_GLUTESSCALLBACK_THREEDOTS)
@@ -508,8 +507,7 @@
   std::shared_ptr<vertex_data_rep> m_rep;
 };
 
-class
-opengl_renderer::patch_tessellator : public opengl_tessellator
+class opengl_renderer::patch_tessellator : public opengl_tessellator
 {
 public:
 
@@ -675,12 +673,17 @@
 
 #else
 
-class
-opengl_renderer::patch_tessellator
+class opengl_renderer::patch_tessellator
 {
   // Dummy class.
 };
 
+OCTAVE_NORETURN static void
+error_unexpected (const char *name)
+{
+  error ("unexpected call to %s when HAVE_OPENGL is not defined - please report this bug", name);
+}
+
 #endif
 
 opengl_renderer::opengl_renderer (opengl_functions& glfcns)
@@ -898,7 +901,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::init_gl_context");
 
 #endif
 }
@@ -974,7 +977,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::render_grid");
 
 #endif
 }
@@ -985,7 +988,7 @@
                                    double p1, double p1N,
                                    double p2, double p2N,
                                    double dx, double dy, double dz,
-                                   int xyz, bool mirror)
+                                   int xyz, bool mirror, bool tickdir_both)
 {
 #if defined (HAVE_OPENGL)
 
@@ -999,31 +1002,37 @@
         {
           if (xyz == X_AXIS)
             {
-              m_glfcns.glVertex3d (val, p1, p2);
+              m_glfcns.glVertex3d (val, p1 + (tickdir_both ? -dy : 0),
+                                   p2 + (tickdir_both ? -dz : 0));
               m_glfcns.glVertex3d (val, p1+dy, p2+dz);
               if (mirror)
                 {
-                  m_glfcns.glVertex3d (val, p1N, p2N);
+                  m_glfcns.glVertex3d (val, p1N + (tickdir_both ? dy : 0),
+                                       p2N + (tickdir_both ? dz : 0));
                   m_glfcns.glVertex3d (val, p1N-dy, p2N-dz);
                 }
             }
           else if (xyz == Y_AXIS)
             {
-              m_glfcns.glVertex3d (p1, val, p2);
+              m_glfcns.glVertex3d (p1 + (tickdir_both ? -dx : 0), val,
+                                   p2 + (tickdir_both ? -dz : 0));
               m_glfcns.glVertex3d (p1+dx, val, p2+dz);
               if (mirror)
                 {
-                  m_glfcns.glVertex3d (p1N, val, p2N);
+                  m_glfcns.glVertex3d (p1N + (tickdir_both ? dx : 0), val,
+                                       p2N + (tickdir_both ? dz : 0));
                   m_glfcns.glVertex3d (p1N-dx, val, p2N-dz);
                 }
             }
           else if (xyz == Z_AXIS)
             {
-              m_glfcns.glVertex3d (p1, p2, val);
+              m_glfcns.glVertex3d (p1 + (tickdir_both ? -dx : 0),
+                                   p2 + (tickdir_both ? -dy : 0), val);
               m_glfcns.glVertex3d (p1+dx, p2+dy, val);
               if (mirror)
                 {
-                  m_glfcns.glVertex3d (p1N, p2N, val);
+                  m_glfcns.glVertex3d (p1N + (tickdir_both ? dx : 0),
+                                       p2N + (tickdir_both ? dy : 0), val);
                   m_glfcns.glVertex3d (p1N-dx, p2N-dy, val);
                 }
             }
@@ -1050,7 +1059,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::render_tickmarks");
 
 #endif
 }
@@ -1120,7 +1129,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::render_ticktexts");
 
 #endif
 }
@@ -1146,7 +1155,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_zoom_rect");
 
 #endif
 }
@@ -1211,7 +1220,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_zoom_box");
 
 #endif
 }
@@ -1225,7 +1234,7 @@
   uint8NDArray pix(dim_vector (3, width, height), 0);
 
   m_glfcns.glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
-                        pix.fortran_vec ());
+                        pix.rwdata ());
 
   // Permute and flip data
   Array<octave_idx_type> perm (dim_vector (3, 1));
@@ -1248,7 +1257,7 @@
   octave_unused_parameter (width);
   octave_unused_parameter (height);
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::get_pixels");
 
 #endif
 }
@@ -1265,7 +1274,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::finish");
 
 #endif
 }
@@ -1323,7 +1332,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::setup_opengl_transformation");
 
 #endif
 }
@@ -1383,7 +1392,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_planes");
 
 #endif
 }
@@ -1543,7 +1552,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_boxes");
 
 #endif
 }
@@ -1607,6 +1616,7 @@
                        && ! props.yscale_is ("log");
       bool is_origin_low = is_origin && (y_min + y_max) < 0;
       bool mirror = props.is_box () && xstate != AXE_ANY_DIR;
+      bool is_tickdir_both = props.tickdir_is ("both");
 
       // X grid
 
@@ -1674,17 +1684,17 @@
           if (tick_along_z)
             render_tickmarks (xmticks, x_min, x_max,
                               is_origin ? y_axis_pos : ypTick, ypTick,
-                              zpTick, zpTickN, 0., 0.,
-                              (is_origin_low ? -1. : 1.) *
+                              zpTick, zpTickN,
+                              0., 0., (is_origin_low ? -1. : 1.) *
                               math::signum (zpTick-zpTickN)*fz*xticklen/2,
-                              0, ! is_origin && mirror);
+                              0, ! is_origin && mirror, is_tickdir_both);
           else
             render_tickmarks (xmticks, 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/2,
-                              0., 0, ! is_origin && mirror);
+                              zpTick, zpTick,
+                              0., (is_origin_low ? -1. : 1.) *
+                              math::signum (ypTick-ypTickN)*fy*xticklen/2, 0.,
+                              0, ! is_origin && mirror, is_tickdir_both);
         }
 
       // tick marks
@@ -1693,17 +1703,17 @@
           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.) *
+                              zpTick, zpTickN,
+                              0., 0., (is_origin_low ? -1. : 1.) *
                               math::signum (zpTick-zpTickN)*fz*xticklen,
-                              0, ! is_origin && mirror);
+                              0, ! is_origin && mirror, is_tickdir_both);
           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);
+                              zpTick, zpTick,
+                              0., (is_origin_low ? -1. : 1.) *
+                              math::signum (ypTick-ypTickN)*fy*xticklen, 0.,
+                              0, ! is_origin && mirror, is_tickdir_both);
         }
 
       // tick texts
@@ -1743,7 +1753,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_x_grid");
 
 #endif
 }
@@ -1808,6 +1818,7 @@
       bool is_origin_low = is_origin && (x_min + x_max) < 0;
       bool mirror = props.is_box () && ystate != AXE_ANY_DIR
                     && (! props.has_property ("__plotyy_axes__"));
+      bool is_tickdir_both = props.tickdir_is ("both");
 
       // Y grid
 
@@ -1875,17 +1886,17 @@
           if (tick_along_z)
             render_tickmarks (ymticks, y_min, y_max,
                               is_origin ? x_axis_pos : xpTick, xpTick,
-                              zpTick, zpTickN, 0., 0.,
-                              (is_origin_low ? -1. : 1.) *
+                              zpTick, zpTickN,
+                              0., 0., (is_origin_low ? -1. : 1.) *
                               math::signum (zpTick-zpTickN)*fz*yticklen/2,
-                              1, ! is_origin && mirror);
+                              1, ! is_origin && mirror, is_tickdir_both);
           else
             render_tickmarks (ymticks, y_min, y_max,
                               is_origin ? x_axis_pos : xpTick, xpTickN,
                               zpTick, zpTick,
                               (is_origin_low ? -1. : 1.) *
-                              math::signum (xpTick-xpTickN)*fx*yticklen/2,
-                              0., 0., 1, ! is_origin && mirror);
+                              math::signum (xpTick-xpTickN)*fx*yticklen/2, 0., 0.,
+                              1, ! is_origin && mirror, is_tickdir_both);
         }
 
       // tick marks
@@ -1894,17 +1905,17 @@
           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.) *
+                              zpTick, zpTickN,
+                              0., 0., (is_origin_low ? -1. : 1.) *
                               math::signum (zpTick-zpTickN)*fz*yticklen,
-                              1, ! is_origin && mirror);
+                              1, ! is_origin && mirror, is_tickdir_both);
           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);
+                              math::signum (xPlaneN-xPlane)*fx*yticklen, 0., 0.,
+                              1, ! is_origin && mirror, is_tickdir_both);
         }
 
       // tick texts
@@ -1944,7 +1955,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_y_grid");
 
 #endif
 }
@@ -1993,6 +2004,7 @@
                             && (minorgridstyle != "none")
                             && ! zticks.isempty ());
       bool mirror = props.is_box () && zstate != AXE_ANY_DIR;
+      bool is_tickdir_both = props.tickdir_is ("both");
 
       // Z grid
 
@@ -2048,26 +2060,26 @@
               if (math::isinf (fy))
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlane,
                                   yPlane, yPlane,
-                                  math::signum (xPlaneN-xPlane)*fx*zticklen/2,
-                                  0., 0., 2, mirror);
+                                  math::signum (xPlaneN-xPlane)*fx*zticklen/2, 0., 0.,
+                                  2, mirror, is_tickdir_both);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlaneN, xPlaneN,
-                                  yPlane, yPlane, 0.,
-                                  math::signum (yPlane-yPlaneN)*fy*zticklen/2,
-                                  0., 2, false);
+                                  yPlane, yPlane,
+                                  0., math::signum (yPlane-yPlaneN)*fy*zticklen/2, 0.,
+                                  2, false, is_tickdir_both);
             }
           else
             {
               if (math::isinf (fx))
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
-                                  yPlaneN, yPlane, 0.,
-                                  math::signum (yPlaneN-yPlane)*fy*zticklen/2,
-                                  0., 2, mirror);
+                                  yPlaneN, yPlane,
+                                  0., math::signum (yPlaneN-yPlane)*fy*zticklen/2, 0.,
+                                  2, mirror, is_tickdir_both);
               else
                 render_tickmarks (zmticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlaneN,
-                                  math::signum (xPlane-xPlaneN)*fx*zticklen/2,
-                                  0., 0., 2, false);
+                                  math::signum (xPlane-xPlaneN)*fx*zticklen/2, 0., 0.,
+                                  2, false, is_tickdir_both);
             }
         }
 
@@ -2079,26 +2091,26 @@
               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);
+                                  math::signum (xPlaneN-xPlane)*fx*zticklen, 0., 0.,
+                                  2, mirror, is_tickdir_both);
               else
                 render_tickmarks (zticks, z_min, z_max, xPlaneN, xPlaneN,
-                                  yPlane, yPlane, 0.,
-                                  math::signum (yPlane-yPlaneN)*fy*zticklen,
-                                  0., 2, false);
+                                  yPlane, yPlane,
+                                  0., math::signum (yPlane-yPlaneN)*fy*zticklen, 0.,
+                                  2, false, is_tickdir_both);
             }
           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);
+                                  yPlaneN, yPlane,
+                                  0., math::signum (yPlaneN-yPlane)*fy*zticklen, 0.,
+                                  2, mirror, is_tickdir_both);
               else
                 render_tickmarks (zticks, z_min, z_max, xPlane, xPlane,
                                   yPlaneN, yPlane,
-                                  math::signum (xPlane-xPlaneN)*fx*zticklen,
-                                  0., 0., 2, false);
+                                  math::signum (xPlane-xPlaneN)*fx*zticklen, 0., 0.,
+                                  2, false, is_tickdir_both);
             }
         }
 
@@ -2168,7 +2180,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_grids");
 
 #endif
 }
@@ -2215,7 +2227,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_all_lights");
 
 #endif
 }
@@ -2304,7 +2316,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes_children");
 
 #endif
 }
@@ -2376,7 +2388,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_axes");
 
 #endif
 }
@@ -2522,7 +2534,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_line");
 
 #endif
 }
@@ -2543,11 +2555,11 @@
 
   NDArray c;
   const NDArray vn = props.get_vertexnormals ().array_value ();
-  dim_vector vn_dims = vn.dims ();
+  const dim_vector& vn_dims = vn.dims ();
   bool has_vertex_normals = (vn_dims(0) == zr && vn_dims(1) == zc
                              && vn_dims(2) == 3);
   const NDArray fn = props.get_facenormals ().array_value ();
-  dim_vector fn_dims = fn.dims ();
+  const dim_vector& fn_dims = fn.dims ();
   bool has_face_normals = (fn_dims(0) == zr - 1 && fn_dims(1) == zc - 1
                            && fn_dims(2) == 3);
 
@@ -3187,7 +3199,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_surface");
 
 #endif
 }
@@ -3464,7 +3476,7 @@
                       vertex_data::vertex_data_rep *vv
                         = vdata[i+j*fr].get_rep ();
 
-                      tess.add_vertex (vv->m_coords.fortran_vec (), vv);
+                      tess.add_vertex (vv->m_coords.rwdata (), vv);
                     }
 
                   if (count_f(i) > 0)
@@ -3504,7 +3516,7 @@
                             }
                         }
 
-                      tess.add_vertex (vv->m_coords.fortran_vec (), vv);
+                      tess.add_vertex (vv->m_coords.rwdata (), vv);
                     }
 
                   tess.end_contour ();
@@ -3634,7 +3646,7 @@
                     {
                       vertex_data::vertex_data_rep *vv
                         = vdata[i+j*fr].get_rep ();
-                      tess.add_vertex (vv->m_coords.fortran_vec (), vv);
+                      tess.add_vertex (vv->m_coords.rwdata (), vv);
                     }
 
                   tess.end_contour ();
@@ -3734,7 +3746,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_patch");
 
 #endif
 }
@@ -3843,7 +3855,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_scatter");
 
 #endif
 }
@@ -3880,7 +3892,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_light");
 
 #endif
 }
@@ -3911,7 +3923,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_ortho_coordinates");
 
 #endif
 }
@@ -3932,7 +3944,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::restore_previous_coordinates");
 
 #endif
 }
@@ -3970,7 +3982,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_text");
 
 #endif
 }
@@ -4056,7 +4068,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_text_background");
 
 #endif
 }
@@ -4079,7 +4091,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_image");
 
 #endif
 }
@@ -4090,7 +4102,7 @@
 {
 #if defined (HAVE_OPENGL)
 
-  dim_vector dv (cdata.dims ());
+  const dim_vector& dv = cdata.dims ();
   int h = dv(0);
   int w = dv(1);
   double x0, x1, y0, y1;
@@ -4162,7 +4174,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_texture_image");
 
 #endif
 }
@@ -4198,7 +4210,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_viewport");
 
 #endif
 }
@@ -4225,7 +4237,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::get_viewport_scaled");
 
 #endif
 
@@ -4249,7 +4261,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_color");
 
 #endif
 }
@@ -4291,7 +4303,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_polygon_offset");
 
 #endif
 }
@@ -4310,7 +4322,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_linewidth");
 
 #endif
 }
@@ -4371,7 +4383,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_linestyle");
 
 #endif
 }
@@ -4421,7 +4433,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_clipbox");
 
 #endif
 }
@@ -4450,7 +4462,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_clipping");
 
 #endif
 }
@@ -4483,7 +4495,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::init_marker");
 
 #endif
 }
@@ -4504,7 +4516,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::change_marker");
 
 #endif
 }
@@ -4528,7 +4540,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::end_marker");
 
 #endif
 }
@@ -4580,7 +4592,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::draw_marker");
 
 #endif
 }
@@ -4603,7 +4615,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::init_maxlights");
 
 #endif
 }
@@ -4630,7 +4642,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::get_string");
   return std::string ();
 
 #endif
@@ -4665,7 +4677,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::set_normal");
 
 #endif
 }
@@ -4879,7 +4891,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::make_marker_list");
 
 #endif
 }
@@ -4939,7 +4951,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::render_text");
 
 #endif
 }
@@ -4995,7 +5007,7 @@
   // This shouldn't happen because construction of opengl_renderer
   // objects is supposed to be impossible if OpenGL is not available.
 
-  panic_impossible ();
+  error_unexpected ("opengl_renderer::render_text");
 
 #endif
 }
--- a/libinterp/corefcn/gl-render.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/gl-render.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 class opengl_functions;
 
-class
-OCTINTERP_API
-opengl_renderer
+class OCTINTERP_API opengl_renderer
 {
 public:
 
@@ -146,7 +144,7 @@
                                  double lim1, double lim2,
                                  double p1, double p1N, double p2, double p2N,
                                  double dx, double dy, double dz,
-                                 int xyz, bool doubleside);
+                                 int xyz, bool doubleside, bool tickdir_both);
 
   virtual void render_ticktexts (const Matrix& ticks,
                                  const string_vector& ticklabels,
--- a/libinterp/corefcn/gl2ps-print.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/gl2ps-print.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,9 +57,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-gl2ps_renderer : public opengl_renderer
+class OCTINTERP_API gl2ps_renderer : public opengl_renderer
 {
 public:
 
@@ -406,7 +404,7 @@
       if (! tmpf)
         error ("gl2ps_renderer::draw: couldn't open temporary file for printing");
 
-      frame.add ([=] () { std::fclose (tmpf); });
+      frame.add ([tmpf] () { std::fclose (tmpf); });
 
       // Reset buffsize, unless this is 2nd pass of a texstandalone print.
       if (m_term.find ("tex") == std::string::npos)
@@ -1236,7 +1234,7 @@
 gl2ps_renderer::draw_image (const image::properties& props)
 {
   octave_value cdata = props.get_color_data ();
-  dim_vector dv (cdata.dims ());
+  const dim_vector& dv = cdata.dims ();
   int h = dv(0);
   int w = dv(1);
 
@@ -1522,10 +1520,10 @@
 
   OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);
 
-  static const float maxval = std::numeric_limits<uint8_t>::max ();
+  static constexpr float MAXVAL = std::numeric_limits<uint8_t>::max ();
 
   for (int i = 0; i < 3*w*h; i++)
-    tmp_data[i] = data[i] / maxval;
+    tmp_data[i] = data[i] / MAXVAL;
 
   draw_pixels (w, h, tmp_data);
 }
@@ -1537,10 +1535,10 @@
 
   OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);
 
-  static const float maxval = std::numeric_limits<uint16_t>::max ();
+  static constexpr float MAXVAL = std::numeric_limits<uint16_t>::max ();
 
   for (int i = 0; i < 3*w*h; i++)
-    tmp_data[i] = data[i] / maxval;
+    tmp_data[i] = data[i] / MAXVAL;
 
   draw_pixels (w, h, tmp_data);
 }
@@ -1623,7 +1621,7 @@
         error (R"(print: failed to open pipe "%s")", stream.c_str ());
 
       // Need octave:: qualifier here to avoid ambiguity.
-      frame.add ([=] () { octave::pclose (m_fp); });
+      frame.add ([m_fp] () { octave::pclose (m_fp); });
     }
   else
     {
@@ -1634,7 +1632,7 @@
       if (! m_fp)
         error (R"(gl2ps_print: failed to create file "%s")", stream.c_str ());
 
-      frame.add ([=] () { std::fclose (m_fp); });
+      frame.add ([m_fp] () { std::fclose (m_fp); });
     }
 
   gl2ps_renderer rend (glfcns, m_fp, term);
--- a/libinterp/corefcn/graphics.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/graphics.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -139,87 +139,291 @@
 static Matrix
 viridis_colormap ()
 {
-  // The values below have been produced by viridis (64)(:)
-  // It would be nice to be able to feval the
-  // viridis function but since there is a static property object that includes
-  // a colormap_property object, we need to initialize this before main is
-  // even called, so calling an interpreted function is not possible.
+  // The values below have been produced by "viridis ()(:)".
+  // It would be nice to be able to feval the  viridis function but since there
+  // is a static property object that includes a colormap_property object, we
+  // need to initialize this before main() is even called, so calling an
+  // interpreted function is not possible.
 
   const double cmapv[] =
   {
-    2.67004010000000e-01, 2.72651720952381e-01, 2.77106307619048e-01,
-    2.80356151428571e-01, 2.82390045238095e-01, 2.83204606666667e-01,
-    2.82809341428571e-01, 2.81230763333333e-01, 2.78516153333333e-01,
-    2.74735528571429e-01, 2.69981791904762e-01, 2.64368580952381e-01,
-    2.58026184285714e-01, 2.51098684761905e-01, 2.43732853333333e-01,
-    2.36073294285714e-01, 2.28263191428571e-01, 2.20424955714286e-01,
-    2.12666598571429e-01, 2.05079113809524e-01, 1.97721880952381e-01,
-    1.90631350000000e-01, 1.83819438571429e-01, 1.77272360952381e-01,
-    1.70957518571429e-01, 1.64832915714286e-01, 1.58845368095238e-01,
-    1.52951235714286e-01, 1.47131626666667e-01, 1.41402210952381e-01,
-    1.35832975714286e-01, 1.30582113809524e-01, 1.25898377619048e-01,
-    1.22163105714286e-01, 1.19872409523810e-01, 1.19626570000000e-01,
-    1.22045948571429e-01, 1.27667691904762e-01, 1.36834947142857e-01,
-    1.49643331428571e-01, 1.65967274285714e-01, 1.85538397142857e-01,
-    2.08030450000000e-01, 2.33127309523809e-01, 2.60531475238095e-01,
-    2.90000730000000e-01, 3.21329971428571e-01, 3.54355250000000e-01,
-    3.88930322857143e-01, 4.24933143333333e-01, 4.62246770476190e-01,
-    5.00753620000000e-01, 5.40336957142857e-01, 5.80861172380952e-01,
-    6.22170772857143e-01, 6.64087320476191e-01, 7.06403823333333e-01,
-    7.48885251428571e-01, 7.91273132857143e-01, 8.33302102380952e-01,
-    8.74717527142857e-01, 9.15296319047619e-01, 9.54839555238095e-01,
-    9.93247890000000e-01, 4.87433000000000e-03, 2.58456800000000e-02,
-    5.09139004761905e-02, 7.42014957142857e-02, 9.59536042857143e-02,
-    1.16893314761905e-01, 1.37350195714286e-01, 1.57479940000000e-01,
-    1.77347967619048e-01, 1.96969168571429e-01, 2.16330337619048e-01,
-    2.35404660952381e-01, 2.54161735714286e-01, 2.72573219047619e-01,
-    2.90619516666667e-01, 3.08291041428571e-01, 3.25586450952381e-01,
-    3.42517215238095e-01, 3.59102207142857e-01, 3.75366067142857e-01,
-    3.91340913333333e-01, 4.07061480000000e-01, 4.22563764285714e-01,
-    4.37885543809524e-01, 4.53062984285714e-01, 4.68129543809524e-01,
-    4.83117059523810e-01, 4.98052961428571e-01, 5.12959473333333e-01,
-    5.27854311428571e-01, 5.42750087142857e-01, 5.57652481904762e-01,
-    5.72563073333333e-01, 5.87476284285714e-01, 6.02382410952381e-01,
-    6.17265840000000e-01, 6.32106955714286e-01, 6.46881817142857e-01,
-    6.61562926190476e-01, 6.76119717142857e-01, 6.90518987142857e-01,
-    7.04725181904762e-01, 7.18700950000000e-01, 7.32406441904762e-01,
-    7.45802021904762e-01, 7.58846480000000e-01, 7.71497934761905e-01,
-    7.83714033809524e-01, 7.95453081428571e-01, 8.06673890000000e-01,
-    8.17337565714286e-01, 8.27409135714286e-01, 8.36858167619048e-01,
-    8.45663399523809e-01, 8.53815582857143e-01, 8.61321019047619e-01,
-    8.68206316666667e-01, 8.74522215714286e-01, 8.80346158571429e-01,
-    8.85780083333333e-01, 8.90945338571429e-01, 8.95973498571429e-01,
-    9.01005800000000e-01, 9.06156570000000e-01, 3.29415190000000e-01,
-    3.53367293333333e-01, 3.76236064761905e-01, 3.97901482857143e-01,
-    4.18250757142857e-01, 4.37178920000000e-01, 4.54595888571429e-01,
-    4.70433883333333e-01, 4.84653865714286e-01, 4.97250492857143e-01,
-    5.08254501428571e-01, 5.17731949047619e-01, 5.25780221428571e-01,
-    5.32522206190476e-01, 5.38097133333333e-01, 5.42651800000000e-01,
-    5.46335411904762e-01, 5.49287148571429e-01, 5.51635008571429e-01,
-    5.53493173333333e-01, 5.54953478571429e-01, 5.56089070000000e-01,
-    5.56952166666667e-01, 5.57576145714286e-01, 5.57974025714286e-01,
-    5.58142745238095e-01, 5.58058673809524e-01, 5.57684744285714e-01,
-    5.56973310000000e-01, 5.55864478571429e-01, 5.54288677142857e-01,
-    5.52175699047619e-01, 5.49445382857143e-01, 5.46023368571429e-01,
-    5.41830633809524e-01, 5.36795616666667e-01, 5.30847985714286e-01,
-    5.23924198571429e-01, 5.15966779523810e-01, 5.06924262857143e-01,
-    4.96751861428571e-01, 4.85412122857143e-01, 4.72873300000000e-01,
-    4.59105875238095e-01, 4.44095883333333e-01, 4.27825852857143e-01,
-    4.10292713809524e-01, 3.91487632857143e-01, 3.71420688571429e-01,
-    3.50098750000000e-01, 3.27544678571429e-01, 3.03798967142857e-01,
-    2.78916748571429e-01, 2.53000856190476e-01, 2.26223670000000e-01,
-    1.98879439523810e-01, 1.71494930000000e-01, 1.45037631428572e-01,
-    1.21291048571429e-01, 1.03326155238095e-01, 9.53507900000000e-02,
-    1.00469958095238e-01, 1.17876387142857e-01, 1.43936200000000e-01
+    0.26700401, 0.26851048, 0.26994384,
+    0.27130489, 0.27259384, 0.27380934,
+    0.27495242, 0.27602238, 0.27701840,
+    0.27794143, 0.27879067, 0.27956550,
+    0.28026658, 0.28089358, 0.28144581,
+    0.28192358, 0.28232739, 0.28265633,
+    0.28291049, 0.28309095, 0.28319704,
+    0.28322882, 0.28318684, 0.28307200,
+    0.28288389, 0.28262297, 0.28229037,
+    0.28188676, 0.28141228, 0.28086773,
+    0.28025468, 0.27957399, 0.27882618,
+    0.27801236, 0.27713437, 0.27619376,
+    0.27519116, 0.27412802, 0.27300596,
+    0.27182812, 0.27059473, 0.26930756,
+    0.26796846, 0.26657984, 0.26514450,
+    0.26366320, 0.26213801, 0.26057103,
+    0.25896451, 0.25732244, 0.25564519,
+    0.25393498, 0.25219404, 0.25042462,
+    0.24862899, 0.24681140, 0.24497208,
+    0.24311324, 0.24123708, 0.23934575,
+    0.23744138, 0.23552606, 0.23360277,
+    0.23167350, 0.22973926, 0.22780192,
+    0.22586330, 0.22392515, 0.22198915,
+    0.22005691, 0.21812995, 0.21620971,
+    0.21429757, 0.21239477, 0.21050310,
+    0.20862342, 0.20675628, 0.20490257,
+    0.20306309, 0.20123854, 0.19942950,
+    0.19763650, 0.19585993, 0.19410009,
+    0.19235719, 0.19063135, 0.18892259,
+    0.18723083, 0.18555593, 0.18389763,
+    0.18225561, 0.18062949, 0.17901879,
+    0.17742298, 0.17584148, 0.17427363,
+    0.17271876, 0.17117615, 0.16964573,
+    0.16812641, 0.16661710, 0.16511703,
+    0.16362543, 0.16214155, 0.16066467,
+    0.15919413, 0.15772933, 0.15626973,
+    0.15481488, 0.15336445, 0.15191820,
+    0.15047605, 0.14903918, 0.14760731,
+    0.14618026, 0.14475863, 0.14334327,
+    0.14193527, 0.14053599, 0.13914708,
+    0.13777048, 0.13640850, 0.13506561,
+    0.13374299, 0.13244401, 0.13117249,
+    0.12993270, 0.12872938, 0.12756771,
+    0.12645338, 0.12539383, 0.12439474,
+    0.12346281, 0.12260562, 0.12183122,
+    0.12114807, 0.12056501, 0.12009154,
+    0.11973756, 0.11951163, 0.11942341,
+    0.11948255, 0.11969858, 0.12008079,
+    0.12063824, 0.12137972, 0.12231244,
+    0.12344358, 0.12477953, 0.12632581,
+    0.12808703, 0.13006688, 0.13226797,
+    0.13469183, 0.13733921, 0.14020991,
+    0.14330291, 0.14661640, 0.15014782,
+    0.15389405, 0.15785146, 0.16201598,
+    0.16638320, 0.17094840, 0.17570671,
+    0.18065314, 0.18578266, 0.19109018,
+    0.19657063, 0.20221902, 0.20803045,
+    0.21400015, 0.22012381, 0.22639690,
+    0.23281498, 0.23937390, 0.24606968,
+    0.25289851, 0.25985676, 0.26694127,
+    0.27414922, 0.28147681, 0.28892102,
+    0.29647899, 0.30414796, 0.31192534,
+    0.31980860, 0.32779580, 0.33588539,
+    0.34407411, 0.35235985, 0.36074053,
+    0.36921420, 0.37777892, 0.38643282,
+    0.39517408, 0.40400101, 0.41291350,
+    0.42190813, 0.43098317, 0.44013691,
+    0.44936763, 0.45867362, 0.46805314,
+    0.47750446, 0.48702580, 0.49661536,
+    0.50627130, 0.51599182, 0.52577622,
+    0.53562110, 0.54552440, 0.55548397,
+    0.56549760, 0.57556297, 0.58567772,
+    0.59583934, 0.60604528, 0.61629283,
+    0.62657923, 0.63690157, 0.64725685,
+    0.65764197, 0.66805369, 0.67848868,
+    0.68894351, 0.69941463, 0.70989842,
+    0.72039115, 0.73088902, 0.74138803,
+    0.75188414, 0.76237342, 0.77285183,
+    0.78331535, 0.79375994, 0.80418159,
+    0.81457634, 0.82494028, 0.83526959,
+    0.84556056, 0.85580960, 0.86601325,
+    0.87616824, 0.88627146, 0.89632002,
+    0.90631121, 0.91624212, 0.92610579,
+    0.93590444, 0.94563626, 0.95529972,
+    0.96489353, 0.97441665, 0.98386829,
+    0.99324789, 0.00487433, 0.00960483,
+    0.01462494, 0.01994186, 0.02556309,
+    0.03149748, 0.03775181, 0.04416723,
+    0.05034437, 0.05632444, 0.06214536,
+    0.06783587, 0.07341724, 0.07890703,
+    0.08431970, 0.08966622, 0.09495545,
+    0.10019576, 0.10539345, 0.11055307,
+    0.11567966, 0.12077701, 0.12584799,
+    0.13089477, 0.13592005, 0.14092556,
+    0.14591233, 0.15088147, 0.15583425,
+    0.16077132, 0.16569272, 0.17059884,
+    0.17549020, 0.18036684, 0.18522836,
+    0.19007447, 0.19490540, 0.19972086,
+    0.20452049, 0.20930306, 0.21406899,
+    0.21881782, 0.22354911, 0.22826210,
+    0.23295593, 0.23763078, 0.24228619,
+    0.24692170, 0.25153685, 0.25613040,
+    0.26070284, 0.26525384, 0.26978306,
+    0.27429024, 0.27877509, 0.28323662,
+    0.28767547, 0.29209154, 0.29648471,
+    0.30085494, 0.30520222, 0.30952657,
+    0.31382773, 0.31810580, 0.32236127,
+    0.32659432, 0.33080515, 0.33499400,
+    0.33916114, 0.34330688, 0.34743154,
+    0.35153548, 0.35561907, 0.35968273,
+    0.36372671, 0.36775151, 0.37175775,
+    0.37574589, 0.37971644, 0.38366989,
+    0.38760678, 0.39152762, 0.39543297,
+    0.39932336, 0.40319934, 0.40706148,
+    0.41091033, 0.41474645, 0.41857040,
+    0.42238275, 0.42618405, 0.42997486,
+    0.43375572, 0.43752720, 0.44128981,
+    0.44504410, 0.44879060, 0.45252980,
+    0.45626209, 0.45998802, 0.46370813,
+    0.46742290, 0.47113278, 0.47483821,
+    0.47853961, 0.48223740, 0.48593197,
+    0.48962370, 0.49331293, 0.49700003,
+    0.50068529, 0.50436904, 0.50805136,
+    0.51173263, 0.51541316, 0.51909319,
+    0.52277292, 0.52645254, 0.53013219,
+    0.53381201, 0.53749213, 0.54117264,
+    0.54485335, 0.54853458, 0.55221637,
+    0.55589872, 0.55958162, 0.56326503,
+    0.56694891, 0.57063316, 0.57431754,
+    0.57800205, 0.58168661, 0.58537105,
+    0.58905521, 0.59273889, 0.59642187,
+    0.60010387, 0.60378459, 0.60746388,
+    0.61114146, 0.61481702, 0.61849025,
+    0.62216081, 0.62582833, 0.62949242,
+    0.63315277, 0.63680899, 0.64046069,
+    0.64410744, 0.64774881, 0.65138436,
+    0.65501363, 0.65863619, 0.66225157,
+    0.66585927, 0.66945881, 0.67304968,
+    0.67663139, 0.68020343, 0.68376525,
+    0.68731632, 0.69085611, 0.69438405,
+    0.69789960, 0.70140222, 0.70489133,
+    0.70836635, 0.71182668, 0.71527175,
+    0.71870095, 0.72211371, 0.72550945,
+    0.72888753, 0.73224735, 0.73558828,
+    0.73890972, 0.74221104, 0.74549162,
+    0.74875084, 0.75198807, 0.75520266,
+    0.75839399, 0.76156142, 0.76470433,
+    0.76782207, 0.77091403, 0.77397953,
+    0.77701790, 0.78002855, 0.78301086,
+    0.78596419, 0.78888793, 0.79178146,
+    0.79464415, 0.79747541, 0.80027461,
+    0.80304099, 0.80577412, 0.80847343,
+    0.81113836, 0.81376835, 0.81636288,
+    0.81892143, 0.82144351, 0.82392862,
+    0.82637633, 0.82878621, 0.83115784,
+    0.83349064, 0.83578452, 0.83803918,
+    0.84025437, 0.84242990, 0.84456561,
+    0.84666139, 0.84871722, 0.85073310,
+    0.85270912, 0.85464543, 0.85654226,
+    0.85839991, 0.86021878, 0.86199932,
+    0.86374211, 0.86544779, 0.86711711,
+    0.86875092, 0.87035015, 0.87191584,
+    0.87344918, 0.87495143, 0.87642392,
+    0.87786808, 0.87928545, 0.88067763,
+    0.88204632, 0.88339329, 0.88472036,
+    0.88602943, 0.88732243, 0.88860134,
+    0.88986815, 0.89112487, 0.89237353,
+    0.89361614, 0.89485467, 0.89609127,
+    0.89732977, 0.89857040, 0.89981500,
+    0.90106534, 0.90232311, 0.90358991,
+    0.90486726, 0.90615657, 0.32941519,
+    0.33542652, 0.34137895, 0.34726862,
+    0.35309303, 0.35885256, 0.36454323,
+    0.37016418, 0.37571452, 0.38119074,
+    0.38659204, 0.39191723, 0.39716349,
+    0.40232944, 0.40741404, 0.41241521,
+    0.41733086, 0.42216032, 0.42690202,
+    0.43155375, 0.43611482, 0.44058404,
+    0.44496000, 0.44924127, 0.45342734,
+    0.45751726, 0.46150995, 0.46540474,
+    0.46920128, 0.47289909, 0.47649762,
+    0.47999675, 0.48339654, 0.48669702,
+    0.48989831, 0.49300074, 0.49600488,
+    0.49891131, 0.50172076, 0.50443413,
+    0.50705243, 0.50957678, 0.51200840,
+    0.51434870, 0.51659930, 0.51876163,
+    0.52083736, 0.52282822, 0.52473609,
+    0.52656332, 0.52831152, 0.52998273,
+    0.53157905, 0.53310261, 0.53455561,
+    0.53594093, 0.53726018, 0.53851561,
+    0.53970946, 0.54084398, 0.54192140,
+    0.54294396, 0.54391424, 0.54483444,
+    0.54570633, 0.54653200, 0.54731353,
+    0.54805291, 0.54875211, 0.54941304,
+    0.55003755, 0.55062743, 0.55118440,
+    0.55171011, 0.55220646, 0.55267486,
+    0.55311653, 0.55353282, 0.55392505,
+    0.55429441, 0.55464205, 0.55496905,
+    0.55527637, 0.55556494, 0.55583559,
+    0.55608907, 0.55632606, 0.55654717,
+    0.55675292, 0.55694377, 0.55712010,
+    0.55728221, 0.55743035, 0.55756466,
+    0.55768526, 0.55779216, 0.55788532,
+    0.55796464, 0.55803034, 0.55808199,
+    0.55811913, 0.55814141, 0.55814842,
+    0.55813967, 0.55811466, 0.55807280,
+    0.55801347, 0.55793600, 0.55783967,
+    0.55772371, 0.55758733, 0.55742968,
+    0.55725050, 0.55704861, 0.55682271,
+    0.55657181, 0.55629491, 0.55599097,
+    0.55565893, 0.55529773, 0.55490625,
+    0.55448339, 0.55402906, 0.55354108,
+    0.55301828, 0.55245948, 0.55186354,
+    0.55122927, 0.55055551, 0.54984110,
+    0.54908564, 0.54828740, 0.54744498,
+    0.54655722, 0.54562298, 0.54464114,
+    0.54361058, 0.54253043, 0.54139999,
+    0.54021751, 0.53898192, 0.53769219,
+    0.53634733, 0.53494633, 0.53348834,
+    0.53197275, 0.53039808, 0.52876343,
+    0.52706792, 0.52531069, 0.52349092,
+    0.52160791, 0.51966086, 0.51764880,
+    0.51557101, 0.51342680, 0.51121549,
+    0.50893644, 0.50658890, 0.50417217,
+    0.50168574, 0.49912906, 0.49650163,
+    0.49380294, 0.49103252, 0.48818938,
+    0.48527326, 0.48228395, 0.47922108,
+    0.47608431, 0.47287330, 0.46958774,
+    0.46622638, 0.46278934, 0.45927675,
+    0.45568838, 0.45202405, 0.44828355,
+    0.44446673, 0.44057284, 0.43660090,
+    0.43255207, 0.42842626, 0.42422341,
+    0.41994346, 0.41558638, 0.41115215,
+    0.40664011, 0.40204917, 0.39738103,
+    0.39263579, 0.38781353, 0.38291438,
+    0.37793850, 0.37288606, 0.36775726,
+    0.36255223, 0.35726893, 0.35191009,
+    0.34647607, 0.34096730, 0.33538426,
+    0.32972749, 0.32399761, 0.31819529,
+    0.31232133, 0.30637661, 0.30036211,
+    0.29427888, 0.28812650, 0.28190832,
+    0.27562602, 0.26928147, 0.26287683,
+    0.25641457, 0.24989748, 0.24332878,
+    0.23671214, 0.23005179, 0.22335258,
+    0.21662012, 0.20986086, 0.20308229,
+    0.19629307, 0.18950326, 0.18272455,
+    0.17597055, 0.16925712, 0.16260273,
+    0.15602894, 0.14956101, 0.14322828,
+    0.13706449, 0.13110864, 0.12540538,
+    0.12000532, 0.11496505, 0.11034678,
+    0.10621724, 0.10264590, 0.09970219,
+    0.09745186, 0.09595277, 0.09525046,
+    0.09537439, 0.09633538, 0.09812496,
+    0.10071680, 0.10407067, 0.10813094,
+    0.11283773, 0.11812832, 0.12394051,
+    0.13021494, 0.13689671, 0.14393620,
   };
 
   // It would be nice if Matrix had a ctor allowing to do the
   // following without a copy
-  Matrix cmap (64, 3, 0.0);
-  std::copy (cmapv, cmapv + (64*3), cmap.fortran_vec ());
+  Matrix cmap (256, 3, 0.0);
+  std::copy (cmapv, cmapv + (256*3), cmap.rwdata ());
   return cmap;
 }
 
+/*
+## Test default colormap returns a 256-color viridis map
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = axes ("parent", hf);
+%!   assert (get (hax, "colormap"), viridis (256));
+%! unwind_protect_cleanup
+%!   delete (hf);
+%! end_unwind_protect
+*/
+
 static double
 default_screendepth ()
 {
@@ -1030,7 +1234,7 @@
   octave_idx_type lda = a.numel () / static_cast<octave_idx_type> (3);
   octave_idx_type nc = cmap.rows ();
 
-  double *av = a.fortran_vec ();
+  double *av = a.rwdata ();
   const double *cmapv = cmap.data ();
 
   double clim_0 = clim(0);
@@ -1588,7 +1792,7 @@
 
   if (xok && m_size_constraints.size () > 0)
     {
-      dim_vector vdims = v.dims ();
+      const dim_vector& vdims = v.dims ();
       int vlen = vdims.ndims ();
 
       xok = false;
@@ -1986,7 +2190,7 @@
   // their handlevisibility property set to "callback" to be visible.
 
   octave::unwind_action executing_callbacks_cleanup
-  ([=] () { executing_callbacks.erase (this); });
+  ([this] () { executing_callbacks.erase (this); });
 
   if (! executing_callbacks.contains (this))
     {
@@ -5127,10 +5331,14 @@
   // Including ones we do don't implement?
 
   // FIXME: This function is probably never called without mode == "reset".
-  //        Verify this is the case with error_unless() (1/6/2017).
-  //        If there are reports of problems then figure out what code is
-  //        calling it with the mode set to something else.
-  error_unless (mode == "reset");
+  //        Error if this is not true.  If there are reports of problems
+  //        then figure out what code is calling it with the mode set to
+  //        something else.  It's apparently been this way since
+  //        1/6/2017 without any reports.  Maybe we should eliminate the
+  //        mode argument?
+
+  if (mode != "reset")
+    error (R"(axes::properties::set_defaults: expected mode = "reset", found "%s")", mode.c_str ());
 
   Matrix tlim (1, 2, 0.0);
   tlim(1) = 1;
@@ -5598,7 +5806,7 @@
   };
   Matrix m (4, 8);
 
-  memcpy (m.fortran_vec (), data, sizeof (double)*32);
+  memcpy (m.rwdata (), data, sizeof (double)*32);
 
   return m;
 }
@@ -5608,7 +5816,7 @@
 {
   ColumnVector retval (4, 1.0);
 
-  memcpy (retval.fortran_vec (), m.data (), sizeof (double)*3);
+  memcpy (retval.rwdata (), m.data (), sizeof (double)*3);
 
   return retval;
 }
@@ -6015,7 +6223,7 @@
   else if (tickdir == "out")
     ticksign = 1;
   else if (tickdir == "both")
-    ticksign = 2;
+    ticksign = 1;
   else  // tickdir == "none"
     ticksign = 0;
 
@@ -7394,20 +7602,20 @@
 
   magform ((hi - lo) / ticint, a, b);
 
-  static const double sqrt_2 = sqrt (2.0);
-  static const double sqrt_10 = sqrt (10.0);
-  static const double sqrt_50 = sqrt (50.0);
-
-  if (a < sqrt_2)
+  static const double SQRT_2 = sqrt (2.0);
+  static const double SQRT_10 = sqrt (10.0);
+  static const double SQRT_50 = sqrt (50.0);
+
+  if (a < SQRT_2)
     x = 1;
-  else if (a < sqrt_10)
+  else if (a < SQRT_10)
     x = 2;
-  else if (a < sqrt_50)
+  else if (a < SQRT_50)
     x = 5;
   else
     x = 10;
 
-  return x * std::pow (10., b);
+  return x * std::pow (10.0, b);
 }
 
 // Attempt to make "nice" limits from the actual max and min of the data.
@@ -9481,6 +9689,14 @@
       return;
     }
 
+  bool pervertex = false;
+  if (ncv == nv)
+    pervertex = true;
+
+  bool isRGB = false;
+  if (cd.ndims () == 3)
+    isRGB = true;
+
   // Faces and Vertices
   dim_vector dv;
   bool is3D = false;
@@ -9505,6 +9721,20 @@
   Matrix vert (dv);
   Matrix idx (nf, nv);
 
+  Matrix fvc;
+  if (pervertex)
+    {
+      // "facevertexcdata" holds color data per vertex
+      fvc.resize (nv * nf, (isRGB ? 3 : 1));
+    }
+  else if (! cd.isempty ())
+    {
+      // "facevertexcdata" holds color data per face
+      dv(0) = ncf;
+      dv(1) = (isRGB ? 3 : 1);
+      fvc = cd.reshape (dv);
+    }
+
   // create list of vertices from x/y/zdata
   // FIXME: It might be possible to share vertices between adjacent faces.
   octave_idx_type kk = 0;
@@ -9517,23 +9747,22 @@
           if (is3D)
             vert(kk, 2) = zd(ii, jj);
 
+          if (pervertex)
+            {
+              fvc(kk, 0) = cd(ii, jj, 0);
+              if (isRGB)
+                {
+                  fvc(kk, 1) = cd(ii, jj, 1);
+                  fvc(kk, 2) = cd(ii, jj, 2);
+                }
+            }
+
           idx(jj, ii) = static_cast<double> (kk+1);
 
           kk++;
         }
     }
 
-  // facevertexcdata
-  Matrix fvc;
-  if (cd.ndims () == 3)
-    {
-      dv(0) = cd.rows () * cd.columns ();
-      dv(1) = cd.dims ()(2);
-      fvc = cd.reshape (dv);
-    }
-  else
-    fvc = cd.as_column ();
-
   // FIXME: shouldn't we update facevertexalphadata here ?
 
   octave::unwind_protect_var<bool> restore_var (updating_patch_data, true);
@@ -11640,8 +11869,7 @@
   return parent_go.get_factory_default (type () + name);
 }
 
-class
-callback_event : public base_graphics_event
+class callback_event : public base_graphics_event
 {
 public:
   callback_event (const graphics_handle& h, const std::string& name,
@@ -11677,8 +11905,7 @@
   octave_value m_callback_data;
 };
 
-class
-mcode_event : public base_graphics_event
+class mcode_event : public base_graphics_event
 {
 public:
   mcode_event (const graphics_handle& h, const std::string& cmd,
@@ -11711,8 +11938,7 @@
   std::string m_mcode;
 };
 
-class
-function_event : public base_graphics_event
+class function_event : public base_graphics_event
 {
 public:
 
@@ -11736,8 +11962,7 @@
   void *m_function_data;
 };
 
-class
-set_event : public base_graphics_event
+class set_event : public base_graphics_event
 {
 public:
   set_event (const graphics_handle& h, const std::string& name,
--- a/libinterp/corefcn/graphics.in.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/graphics.in.h	Fri Apr 12 15:10:26 2024 +0200
@@ -127,7 +127,7 @@
   {
     Matrix retval (m.rows (), m.cols ());
 
-    do_scale (m.data (), retval.fortran_vec (), m.numel ());
+    do_scale (m.data (), retval.rwdata (), m.numel ());
 
     return retval;
   }
@@ -136,7 +136,7 @@
   {
     NDArray retval (m.dims ());
 
-    do_scale (m.data (), retval.fortran_vec (), m.numel ());
+    do_scale (m.data (), retval.rwdata (), m.numel ());
 
     return retval;
   }
@@ -168,7 +168,7 @@
   {
     Matrix retval (m.rows (), m.cols ());
 
-    do_scale (m.data (), retval.fortran_vec (), m.numel ());
+    do_scale (m.data (), retval.rwdata (), m.numel ());
 
     return retval;
   }
@@ -177,7 +177,7 @@
   {
     NDArray retval (m.dims ());
 
-    do_scale (m.data (), retval.fortran_vec (), m.numel ());
+    do_scale (m.data (), retval.rwdata (), m.numel ());
 
     return retval;
   }
@@ -4770,7 +4770,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
@@ -4891,7 +4893,7 @@
 
     Matrix get_auto_xdata ()
     {
-      dim_vector dv = get_cdata ().dims ();
+      const dim_vector& dv = get_cdata ().dims ();
       Matrix data;
       if (dv(1) > 0.)
         {
@@ -4903,7 +4905,7 @@
 
     Matrix get_auto_ydata ()
     {
-      dim_vector dv = get_cdata ().dims ();
+      const dim_vector& dv = get_cdata ().dims ();
       Matrix data;
       if (dv(0) > 0.)
         {
@@ -5055,7 +5057,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
@@ -5558,7 +5562,9 @@
     { return m_aliminclude.current_value (); }
 
     bool is_climinclude () const
-    { return (m_climinclude.is_on () && m_cdatamapping.is ("scaled")); }
+    { return (m_climinclude.is_on ()
+              && ! (m_cdatamapping.is ("direct")
+                    || m_cdata.get ().ndims () == 3)); }
     std::string get_climinclude () const
     { return m_climinclude.current_value (); }
 
@@ -6673,9 +6679,7 @@
 
 class graphics_event;
 
-class
-OCTINTERP_API
-base_graphics_event
+class OCTINTERP_API base_graphics_event
 {
 public:
   enum priority { INTERRUPT, QUEUE, CANCEL };
@@ -6702,9 +6706,7 @@
   int m_busyaction;
 };
 
-class
-OCTINTERP_API
-graphics_event
+class OCTINTERP_API graphics_event
 {
 public:
 
--- a/libinterp/corefcn/gsvd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/gsvd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
--- a/libinterp/corefcn/help.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/help.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -675,6 +675,20 @@
       help = fcn->doc_string (fcn_nm);
       what = fcn->fcn_file_name ();
 
+      if (help.empty () && ov_fcn.is_user_function ())
+        {
+          octave_user_function *ufcn = ov_fcn.user_function_value ();
+
+          if (ufcn->is_classdef_constructor ())
+            help = "undocumented constructor: ";
+          else if (ufcn->is_classdef_method ())
+            help = "undocumented method: ";
+          else
+            help = "undocumented function: ";
+
+          help += ufcn->signature ();
+        }
+
       if (what.empty ())
         what = fcn->is_user_function () ? "command-line function" : "built-in function";
 
@@ -719,10 +733,23 @@
             }
         }
 
-      // We found a class, but no docstring for it or its constructor.
-      // Create a generic doc string.
-      help = name + " is an undocumented class";
-      what = "class";
+      // No dot in name and class is undocumented.  Look for documented
+      // constructor.
+
+      octave_value ov_meth = cls.get_method (name);
+
+      if (get_help_from_fcn (name, ov_meth, help, what, symbol_found))
+        {
+          what = "constructor";
+          symbol_found = true;
+          return true;
+        }
+
+      // We found a class, but no docstring for it and there is no
+      // constructor explicitly defined.
+
+      help = "default constructor: obj = " + name + " ()";
+      what = "constructor";
       symbol_found = true;
       return true;
     }
@@ -813,7 +840,21 @@
       octave_value ov_meth = cls.get_method (nm);
 
       if (get_help_from_fcn (nm, ov_meth, help, what, symbol_found))
-        return true;
+        {
+          what = "class method";
+          return true;
+        }
+
+      // Found class but no method.  If the NM is the same as the name
+      // of the class, then we have a default constructor.
+
+      if (cls.get_name () == nm)
+        {
+          help = "default constructor: obj = " + nm + " ()";
+          what = "constructor";
+          symbol_found = true;
+          return true;
+        }
 
       // FIXME: Should we only find public properties here?
 
--- a/libinterp/corefcn/input.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/input.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,6 @@
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
-#include <cassert>
 
 #include <algorithm>
 #include <iostream>
@@ -261,13 +260,13 @@
 is_completing_dirfns ()
 {
   static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"};
-  static const std::size_t dirfns_commands_length = 4;
+  static const std::size_t DIRFNS_COMMANDS_LENGTH = 4;
 
   bool retval = false;
 
   std::string line = command_editor::get_line_buffer ();
 
-  for (std::size_t i = 0; i < dirfns_commands_length; i++)
+  for (std::size_t i = 0; i < DIRFNS_COMMANDS_LENGTH; i++)
     {
       int index = line.find (dirfns_commands[i] + ' ');
 
@@ -889,8 +888,7 @@
   return retval;
 }
 
-class
-terminal_reader : public base_reader
+class terminal_reader : public base_reader
 {
 public:
 
@@ -912,8 +910,7 @@
   static const std::string s_in_src;
 };
 
-class
-file_reader : public base_reader
+class file_reader : public base_reader
 {
 public:
 
@@ -942,8 +939,7 @@
   static const std::string s_in_src;
 };
 
-class
-eval_string_reader : public base_reader
+class eval_string_reader : public base_reader
 {
 public:
 
@@ -1110,7 +1106,7 @@
                "converting from codepage '%s' to UTF-8: %s",
                encoding.c_str (), std::strerror (errno));
 
-      unwind_action free_utf8_str ([=] () { ::free (utf8_str); });
+      unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });
 
       src_str = std::string (reinterpret_cast<char *> (utf8_str), length);
     }
--- a/libinterp/corefcn/input.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/input.h	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 #include "pager.h"
 
 // TRUE after a call to completion_matches.
-extern bool octave_completion_matches_called;
+extern OCTINTERP_API bool octave_completion_matches_called;
 
 // TRUE if the plotting system has requested a call to drawnow at
 // the next user prompt.
--- a/libinterp/corefcn/interpreter.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/interpreter.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -290,7 +290,7 @@
   std::string arg = args(0).xstring_value ("atexit: FCN argument must be a string");
 
   bool add_mode = (nargin == 2)
-                  ? args(1).xbool_value ("atexit: FLAG argument must be a logical value")
+                  ? args(1).ybool_value ("atexit: FLAG argument must be a logical value")
                   : true;
 
   octave_value_list retval;
@@ -455,8 +455,8 @@
     m_gh_manager (nullptr),
     m_interactive (false),
     m_read_site_files (true),
-    m_read_init_files (m_app_context != nullptr),
-    m_verbose (false),
+    m_read_user_files (m_app_context != nullptr),
+    m_init_trace (false),
     m_traditional (false),
     m_inhibit_startup_message (false),
     m_load_path_initialized (false),
@@ -705,8 +705,7 @@
       unwind_action restore_add_hook (&load_path::set_add_hook, &m_load_path,
                                       m_load_path.get_add_hook ());
 
-      m_load_path.set_add_hook ([=] (const std::string& dir)
-      { this->execute_pkg_add (dir); });
+      m_load_path.set_add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); });
 
       m_load_path.initialize (set_initial_path);
 
@@ -1100,8 +1099,8 @@
 interpreter::execute_startup_files ()
 {
   bool read_site_files = m_read_site_files;
-  bool read_init_files = m_read_init_files;
-  bool verbose = m_verbose;
+  bool read_user_files = m_read_user_files;
+  bool trace = m_init_trace;
   bool inhibit_startup_message = m_inhibit_startup_message;
 
   if (m_app_context)
@@ -1109,12 +1108,12 @@
       const cmdline_options& options = m_app_context->options ();
 
       read_site_files = options.read_site_files ();
-      read_init_files = options.read_init_files ();
-      verbose = options.verbose_flag ();
+      read_user_files = options.read_user_files ();
+      trace = options.init_trace ();
       inhibit_startup_message = options.inhibit_startup_message ();
     }
 
-  verbose = (verbose && ! inhibit_startup_message);
+  trace = (trace && ! inhibit_startup_message);
 
   bool require_file = false;
 
@@ -1130,19 +1129,19 @@
       // $(prefix)/share/octave/$(version)/m/octaverc (if it exists).
 
       int status = safe_source_file (config::local_site_defaults_file (),
-                                     context, verbose, require_file);
+                                     context, trace, require_file);
 
       if (status)
         exit_status = status;
 
       status = safe_source_file (config::site_defaults_file (),
-                                 context, verbose, require_file);
+                                 context, trace, require_file);
 
       if (status)
         exit_status = status;
     }
 
-  if (read_init_files)
+  if (read_user_files)
     {
       // Try to execute commands from the Matlab compatible startup.m file
       // if it exists anywhere in the load path when starting Octave.
@@ -1179,7 +1178,7 @@
 
       if (! cfg_rc.empty ())
         {
-          int status = safe_source_file (cfg_rc, context, verbose,
+          int status = safe_source_file (cfg_rc, context, trace,
                                          require_file);
 
           if (status)
@@ -1205,7 +1204,7 @@
 
       if (! home_rc.empty ())
         {
-          int status = safe_source_file (home_rc, context, verbose,
+          int status = safe_source_file (home_rc, context, trace,
                                          require_file);
 
           if (status)
@@ -1229,7 +1228,7 @@
           if (local_rc.empty ())
             local_rc = sys::env::make_absolute (initfile);
 
-          int status = safe_source_file (local_rc, context, verbose,
+          int status = safe_source_file (local_rc, context, trace,
                                          require_file);
 
           if (status)
@@ -1237,8 +1236,8 @@
         }
     }
 
-  if (m_interactive && verbose)
-    std::cout << std::endl;
+  if (m_interactive && trace)
+    octave_stdout << std::endl;
 
   return exit_status;
 }
@@ -1659,6 +1658,12 @@
   return feval (f_arg, tmp_args, nargout);
 }
 
+std::string
+interpreter::inputname (int n, bool ids_only) const
+{
+  return m_evaluator.inputname (n, ids_only);
+}
+
 octave_value
 interpreter::make_function_handle (const std::string& name)
 {
--- a/libinterp/corefcn/interpreter.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/interpreter.h	Fri Apr 12 15:10:26 2024 +0200
@@ -177,14 +177,26 @@
     m_read_site_files = flag;
   }
 
+  void read_user_files (bool flag)
+  {
+    m_read_user_files = flag;
+  }
+
+  OCTAVE_DEPRECATED (10, "interpreter::read_init_files is deprecated, use read_user_files")
   void read_init_files (bool flag)
   {
-    m_read_init_files = flag;
+    read_user_files (flag);
   }
 
+  void init_trace (bool flag)
+  {
+    m_init_trace = flag;
+  }
+
+  OCTAVE_DEPRECATED (10, "interpreter::verbose is deprecated, use init_trace")
   void verbose (bool flag)
   {
-    m_verbose = flag;
+    init_trace (flag);
   }
 
   void traditional (bool flag)
@@ -399,6 +411,8 @@
 
   octave_value_list feval (const octave_value_list& args, int nargout = 0);
 
+  std::string inputname (int n, bool ids_only = true) const;
+
   octave_value make_function_handle (const std::string& name);
 
   void install_variable (const std::string& name, const octave_value& value,
@@ -644,9 +658,9 @@
 
   bool m_read_site_files;
 
-  bool m_read_init_files;
+  bool m_read_user_files;
 
-  bool m_verbose;
+  bool m_init_trace;
 
   bool m_traditional;
 
--- a/libinterp/corefcn/jsondecode.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/jsondecode.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -241,7 +241,7 @@
   if (same_field_names)
     {
       octave_map struct_array;
-      dim_vector struct_array_dims = dim_vector (struct_cell.numel (), 1);
+      const dim_vector& struct_array_dims = dim_vector (struct_cell.numel (), 1);
 
       if (field_names.numel ())
         {
@@ -300,7 +300,7 @@
   bool is_struct = cell(0).isstruct ();
   string_vector field_names = is_struct ? cell(0).map_value ().fieldnames ()
                               : string_vector ();
-  dim_vector sub_array_dims = cell(0).dims ();
+  const dim_vector& sub_array_dims = cell(0).dims ();
   octave_idx_type sub_array_ndims = cell(0).ndims ();
   octave_idx_type cell_numel = cell.numel ();
   for (octave_idx_type i = 0; i < cell_numel; ++i)
@@ -601,7 +601,7 @@
                               "option argument must be a string");
       if (string::strcmpi (parameter, "makeValidName"))
         {
-          use_makeValidName = args(i + 1).xbool_value ("jsondecode: "
+          use_makeValidName = args(i + 1).ybool_value ("jsondecode: "
                               "'makeValidName' value must be a bool");
         }
       else
--- a/libinterp/corefcn/jsonencode.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/jsonencode.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -61,22 +61,41 @@
 encode_numeric (T& writer, const octave_value& obj,
                 const bool& ConvertInfAndNaN)
 {
-  double value = obj.scalar_value ();
+  if (obj.isfloat ())
+    {
+      double value = obj.scalar_value ();
+
+      // Detect floating point numbers which are actually integers by checking
+      // whether the number and the integer portion of the number are the same
+      // to within eps.
+      // FIXME: If value > 999999, MATLAB will encode it in scientific
+      // notation, but rapidJSON will output all digits.
+      if (fabs (trunc (value) - value) < std::numeric_limits<double>::epsilon ())
 
-  if (obj.is_bool_scalar ())
+        writer.Int64 (value);
+      // Possibly write NULL for non-finite values (-Inf, Inf, NaN, NA)
+      else if (ConvertInfAndNaN && ! octave::math::isfinite (value))
+        writer.Null ();
+      else
+        writer.Double (value);
+    }
+  else if (obj.isinteger ())
+    {
+       if (obj.is_uint64_type ())
+         {
+            uint64_t value = obj.uint64_value ();
+            writer.Uint64 (value);
+         }
+       else
+         {
+            // Write all other integers as 64-bit values and let RapidJSON
+            // determine number of digits to keep.
+            int64_t value = obj.int64_value ();
+            writer.Int64 (value);
+         }
+    }
+  else if (obj.is_bool_scalar ())
     writer.Bool (obj.bool_value ());
-  // Any numeric input from the interpreter will be in double type so in order
-  // to detect ints, we will check if the floor of the input and the input are
-  // equal using fabs (A - B) < epsilon method as it is more accurate.
-  // If value > 999999, MATLAB will encode it in scientific notation (double)
-  else if (fabs (floor (value) - value) < std::numeric_limits<double>::epsilon ()
-           && value <= 999999 && value >= -999999)
-    writer.Int64 (value);
-  // Possibly write NULL for non-finite values (-Inf, Inf, NaN, NA)
-  else if (ConvertInfAndNaN && ! octave::math::isfinite (value))
-    writer.Null ();
-  else if (obj.is_double_type ())
-    writer.Double (value);
   else
     error ("jsonencode: unsupported type");
 }
@@ -313,7 +332,7 @@
     {
       octave_idx_type idx;
       octave_idx_type ndims = array.ndims ();
-      dim_vector dims = array.dims ();
+      const dim_vector& dims = array.dims ();
 
       // In this case, we already have a vector. So,  we transform it to 2-D
       // vector in order to be detected by "isvector" in the recursive call
@@ -400,9 +419,10 @@
 encode (T& writer, const octave_value& obj, const bool& ConvertInfAndNaN)
 {
   if (obj.is_real_scalar ())
+    // Numeric scalars.
     encode_numeric (writer, obj, ConvertInfAndNaN);
-  // As I checked for scalars, this will detect numeric & logical arrays
   else if (obj.isnumeric () || obj.islogical ())
+    // Numeric and logical arrays.
     encode_array (writer, obj, ConvertInfAndNaN, obj.dims ());
   else if (obj.is_string ())
     encode_string (writer, obj, obj.dims ());
--- a/libinterp/corefcn/kron.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/kron.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -55,8 +55,8 @@
 static MArray<T>
 kron (const MArray<R>& a, const MArray<T>& b)
 {
-  error_unless (a.ndims () == 2);
-  error_unless (b.ndims () == 2);
+  panic_unless (a.ndims () == 2);
+  panic_unless (b.ndims () == 2);
 
   octave_idx_type nra = a.rows ();
   octave_idx_type nrb = b.rows ();
@@ -64,7 +64,7 @@
   octave_idx_type ncb = b.cols ();
 
   MArray<T> c (dim_vector (nra*nrb, nca*ncb));
-  T *cv = c.fortran_vec ();
+  T *cv = c.rwdata ();
 
   for (octave_idx_type ja = 0; ja < nca; ja++)
     {
@@ -86,7 +86,7 @@
 static MArray<T>
 kron (const MDiagArray2<R>& a, const MArray<T>& b)
 {
-  error_unless (b.ndims () == 2);
+  panic_unless (b.ndims () == 2);
 
   octave_idx_type nra = a.rows ();
   octave_idx_type nrb = b.rows ();
--- a/libinterp/corefcn/latex-text-renderer.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/latex-text-renderer.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
@@ -49,9 +49,7 @@
   return ('"' + str + '"');
 }
 
-class
-OCTINTERP_API
-latex_renderer : public base_text_renderer
+class OCTINTERP_API latex_renderer : public base_text_renderer
 {
 public:
 
--- a/libinterp/corefcn/load-path.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/load-path.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -250,8 +250,8 @@
 load_path::abs_dir_cache_type load_path::s_abs_dir_cache;
 
 load_path::load_path (interpreter& interp)
-  : 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_add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); }),
+m_remove_hook ([this] (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 ()
 { }
@@ -2701,7 +2701,7 @@
     }
   else if (option_arg.isnumeric ())
     {
-      int val = option_arg.xint_value ("addpath: OPTION must be '-begin'/0 or '-end'/1");
+      int val = option_arg.yint_value ("addpath: OPTION must be '-begin'/0 or '-end'/1");
 
       if (val == 0)
         nargin--;
--- a/libinterp/corefcn/load-path.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/load-path.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-load_path
+class OCTINTERP_API load_path
 {
 public:
 
--- a/libinterp/corefcn/ls-mat4.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ls-mat4.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -340,7 +340,7 @@
             for (octave_idx_type i = 0; i < nr - 1; i++)
               c.xelem (i) = dtmp[i] - 1;
             nc_new = dtmp[nr - 1];
-            read_mat_binary_data (is, data.fortran_vec (), prec, nr - 1,
+            read_mat_binary_data (is, data.rwdata (), prec, nr - 1,
                                   swap, flt_fmt);
             read_mat_binary_data (is, dtmp, prec, 1, swap, flt_fmt);
 
@@ -353,7 +353,7 @@
       {
         Matrix re (nr, nc);
 
-        read_mat_binary_data (is, re.fortran_vec (), prec, dlen, swap, flt_fmt);
+        read_mat_binary_data (is, re.rwdata (), prec, dlen, swap, flt_fmt);
 
         if (! is)
           error ("load: reading matrix data for '%s'", name);
@@ -362,7 +362,7 @@
           {
             Matrix im (nr, nc);
 
-            read_mat_binary_data (is, im.fortran_vec (), prec, dlen, swap,
+            read_mat_binary_data (is, im.rwdata (), prec, dlen, swap,
                                   flt_fmt);
 
             if (! is)
--- a/libinterp/corefcn/ls-mat5.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ls-mat5.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -382,7 +382,7 @@
                                                                         \
     octave_idx_type n = re.numel ();                                    \
     tmp_pos = is.tellg ();                                              \
-    read_mat5_integer_data (is, re.fortran_vec (), n, swap,             \
+    read_mat5_integer_data (is, re.rwdata (), n, swap,             \
                             static_cast<enum mat5_data_type> (type));   \
                                                                         \
     if (! is)                                                           \
@@ -401,7 +401,7 @@
                  retval.c_str ());                                      \
                                                                         \
         n = im.numel ();                                                \
-        read_mat5_binary_data (is, im.fortran_vec (), n, swap,          \
+        read_mat5_binary_data (is, im.rwdata (), n, swap,          \
                                static_cast<enum mat5_data_type> (type), flt_fmt); \
                                                                         \
         if (! is)                                                       \
@@ -808,7 +808,7 @@
         if (imag)
           {
             re = NDArray (dim_vector (nnz, 1));
-            data = re.fortran_vec ();
+            data = re.rwdata ();
           }
 
         tmp_pos = is.tellg ();
@@ -832,7 +832,7 @@
               error ("load: reading sparse matrix data for '%s'",
                      retval.c_str ());
 
-            read_mat5_binary_data (is, im.fortran_vec (), nnz, swap,
+            read_mat5_binary_data (is, im.rwdata (), nnz, swap,
                                    static_cast<enum mat5_data_type> (type),
                                    flt_fmt);
 
@@ -1325,7 +1325,7 @@
 
         octave_idx_type n = re.numel ();
         tmp_pos = is.tellg ();
-        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
+        read_mat5_binary_data (is, re.rwdata (), n, swap,
                                static_cast<enum mat5_data_type> (type),
                                flt_fmt);
 
@@ -1345,7 +1345,7 @@
               error ("load: reading matrix data for '%s'", retval.c_str ());
 
             n = im.numel ();
-            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
+            read_mat5_binary_data (is, im.rwdata (), n, swap,
                                    static_cast<enum mat5_data_type> (type),
                                    flt_fmt);
 
@@ -1382,7 +1382,7 @@
 
         octave_idx_type n = re.numel ();
         tmp_pos = is.tellg ();
-        read_mat5_binary_data (is, re.fortran_vec (), n, swap,
+        read_mat5_binary_data (is, re.rwdata (), n, swap,
                                static_cast<enum mat5_data_type> (type),
                                flt_fmt);
 
@@ -1415,7 +1415,7 @@
               error ("load: reading matrix data for '%s'", retval.c_str ());
 
             n = im.numel ();
-            read_mat5_binary_data (is, im.fortran_vec (), n, swap,
+            read_mat5_binary_data (is, im.rwdata (), n, swap,
                                    static_cast<enum mat5_data_type> (type),
                                    flt_fmt);
 
@@ -2114,7 +2114,7 @@
 maybe_convert_to_u16 (const charNDArray& chm, std::size_t& n16_str)
 {
   uint16_t *u16_str;
-  dim_vector dv = chm.dims ();
+  const dim_vector& dv = chm.dims ();
 
   if (chm.ndims () == 2 && dv(0) == 1)
     {
@@ -2328,7 +2328,7 @@
   std::string cname = tc.class_name ();
   std::size_t max_namelen = 63;
 
-  dim_vector dv = tc.dims ();
+  const dim_vector& dv = tc.dims ();
   int nd = tc.ndims ();
   int dim_len = 4*nd;
 
--- a/libinterp/corefcn/matrix_type.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/matrix_type.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -274,7 +274,7 @@
               const ColumnVector perm = args(2).xvector_value ("matrix_type: Invalid permutation vector PERM");
 
               octave_idx_type len = perm.numel ();
-              dim_vector dv = args(0).dims ();
+              const dim_vector& dv = args(0).dims ();
 
               if (len != dv(0))
                 error ("matrix_type: Invalid permutation vector PERM");
@@ -411,7 +411,7 @@
               const ColumnVector perm = args(2).xvector_value ("matrix_type: Invalid permutation vector PERM");
 
               octave_idx_type len = perm.numel ();
-              dim_vector dv = args(0).dims ();
+              const dim_vector& dv = args(0).dims ();
 
               if (len != dv(0))
                 error ("matrix_type: Invalid permutation vector PERM");
--- a/libinterp/corefcn/mex.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/mex.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -47,7 +47,6 @@
 #include <string>
 
 #include "f77-fcn.h"
-#include "lo-ieee.h"
 #include "oct-locbuf.h"
 #include "quit.h"
 
@@ -239,6 +238,12 @@
   extern OCTINTERP_API void mxSetImagData (mxArray *ptr, void *pi);
 }
 
+OCTAVE_NORETURN static void
+error_impossible_call (const char *fcn_name)
+{
+  error ("unexpected call to %s - please report this bug", fcn_name);
+}
+
 static void *
 xmalloc (size_t n)
 {
@@ -442,7 +447,7 @@
   RET_TYPE FCN_NAME ARG_LIST const { request_mutation (); return RET_VAL; }
 
 #define GET_DATA_METHOD(RT, FCN_NAME, ID, COMPLEXITY)                   \
-  RT * FCN_NAME (void) const { return get_data<RT> (ID, COMPLEXITY); }
+  RT * FCN_NAME () const { return get_data<RT> (ID, COMPLEXITY); }
 
 class mxArray_octave_value : public mxArray_base
 {
@@ -461,14 +466,15 @@
 
   mxArray_octave_value& operator = (const mxArray_octave_value&) = delete;
 
-  mxArray_base * dup (void) const { return new mxArray_octave_value (*this); }
-
-  mxArray * as_mxArray (void) const
+  mxArray_base * dup () const { return new mxArray_octave_value (*this); }
+
+  mxArray * as_mxArray () const
   {
     mxArray *retval = m_val.as_mxArray (m_interleaved);
 
     // RETVAL is assumed to be an mxArray_matlab object.  Should we
-    // error_unless that condition here?
+    // panic_unless that condition here or just check and throw an
+    // error?
 
     if (retval)
       {
@@ -500,62 +506,62 @@
     return retval;
   }
 
-  ~mxArray_octave_value (void)
+  ~mxArray_octave_value ()
   {
     mxFree (m_class_name);
     mxFree (m_dims);
   }
 
-  bool is_octave_value (void) const { return true; }
-
-  int iscell (void) const { return m_val.iscell (); }
-
-  int is_char (void) const { return m_val.is_string (); }
-
-  int is_complex (void) const { return m_val.iscomplex (); }
-
-  int is_double (void) const { return m_val.is_double_type (); }
-
-  int is_function_handle (void) const { return m_val.is_function_handle (); }
-
-  int is_int16 (void) const { return m_val.is_int16_type (); }
-
-  int is_int32 (void) const { return m_val.is_int32_type (); }
-
-  int is_int64 (void) const { return m_val.is_int64_type (); }
-
-  int is_int8 (void) const { return m_val.is_int8_type (); }
-
-  int is_logical (void) const { return m_val.islogical (); }
-
-  int is_numeric (void) const { return m_val.isnumeric (); }
-
-  int is_single (void) const { return m_val.is_single_type (); }
-
-  int is_sparse (void) const { return m_val.issparse (); }
-
-  int is_struct (void) const { return m_val.isstruct (); }
-
-  int is_uint16 (void) const { return m_val.is_uint16_type (); }
-
-  int is_uint32 (void) const { return m_val.is_uint32_type (); }
-
-  int is_uint64 (void) const { return m_val.is_uint64_type (); }
-
-  int is_uint8 (void) const { return m_val.is_uint8_type (); }
-
-  int is_range (void) const { return m_val.is_range (); }
-
-  int isreal (void) const { return m_val.isreal (); }
-
-  int is_logical_scalar_true (void) const
+  bool is_octave_value () const { return true; }
+
+  int iscell () const { return m_val.iscell (); }
+
+  int is_char () const { return m_val.is_string (); }
+
+  int is_complex () const { return m_val.iscomplex (); }
+
+  int is_double () const { return m_val.is_double_type (); }
+
+  int is_function_handle () const { return m_val.is_function_handle (); }
+
+  int is_int16 () const { return m_val.is_int16_type (); }
+
+  int is_int32 () const { return m_val.is_int32_type (); }
+
+  int is_int64 () const { return m_val.is_int64_type (); }
+
+  int is_int8 () const { return m_val.is_int8_type (); }
+
+  int is_logical () const { return m_val.islogical (); }
+
+  int is_numeric () const { return m_val.isnumeric (); }
+
+  int is_single () const { return m_val.is_single_type (); }
+
+  int is_sparse () const { return m_val.issparse (); }
+
+  int is_struct () const { return m_val.isstruct (); }
+
+  int is_uint16 () const { return m_val.is_uint16_type (); }
+
+  int is_uint32 () const { return m_val.is_uint32_type (); }
+
+  int is_uint64 () const { return m_val.is_uint64_type (); }
+
+  int is_uint8 () const { return m_val.is_uint8_type (); }
+
+  int is_range () const { return m_val.is_range (); }
+
+  int isreal () const { return m_val.isreal (); }
+
+  int is_logical_scalar_true () const
   {
     return (is_logical_scalar () && m_val.is_true ());
   }
 
-  mwSize get_m (void) const { return m_val.rows (); }
-
-  mwSize get_n (void) const
+  mwSize get_m () const { return m_val.rows (); }
+
+  mwSize get_n () const
   {
     mwSize n = 1;
 
@@ -568,7 +574,7 @@
     return n;
   }
 
-  mwSize * get_dimensions (void) const
+  mwSize * get_dimensions () const
   {
     if (! m_dims)
       {
@@ -577,7 +583,7 @@
         m_dims = static_cast<mwSize *> (mxArray::malloc (m_ndims
                                         * sizeof (mwSize)));
 
-        dim_vector dv = m_val.dims ();
+        const dim_vector& dv = m_val.dims ();
 
         for (mwIndex i = 0; i < m_ndims; i++)
           m_dims[i] = dv(i);
@@ -586,7 +592,7 @@
     return m_dims;
   }
 
-  mwSize get_number_of_dimensions (void) const
+  mwSize get_number_of_dimensions () const
   {
     // Force m_dims and m_ndims to be cached.
     get_dimensions ();
@@ -599,11 +605,11 @@
 
   MUTATION_METHOD (int, set_dimensions, (mwSize *, mwSize), 0)
 
-  mwSize get_number_of_elements (void) const { return m_val.numel (); }
-
-  int isempty (void) const { return m_val.isempty (); }
-
-  bool is_scalar (void) const
+  mwSize get_number_of_elements () const { return m_val.numel (); }
+
+  int isempty () const { return m_val.isempty (); }
+
+  bool is_scalar () const
   {
     // Force m_dims and m_ndims to be cached.
     get_dimensions ();
@@ -611,7 +617,7 @@
     return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;
   }
 
-  mxClassID get_class_id (void) const
+  mxClassID get_class_id () const
   {
     m_id = mxUNKNOWN_CLASS;
 
@@ -651,7 +657,7 @@
     return m_id;
   }
 
-  const char * get_class_name (void) const
+  const char * get_class_name () const
   {
     if (! m_class_name)
       {
@@ -703,7 +709,7 @@
   // Not allowed.
   VOID_MUTATION_METHOD (set_cell, (mwIndex, mxArray *))
 
-  double get_scalar (void) const
+  double get_scalar () const
   {
     if (m_val.issparse ())
       {
@@ -723,7 +729,7 @@
       return m_val.scalar_value (true);
   }
 
-  void * get_data (void) const
+  void * get_data () const
   {
     // Casting away const required for MEX interface.
 
@@ -784,7 +790,7 @@
   GET_DATA_METHOD (mxComplexSingle, get_complex_singles,
                    mxDOUBLE_CLASS, mxCOMPLEX);
 
-  void * get_imag_data (void) const
+  void * get_imag_data () const
   {
     void *retval = nullptr;
 
@@ -816,7 +822,7 @@
   // Not allowed.
   VOID_MUTATION_METHOD (set_imag_data, (void *))
 
-  mwIndex * get_ir (void) const
+  mwIndex * get_ir () const
   {
     // Casting away const required for MEX interface.
 
@@ -824,7 +830,7 @@
     return static_cast<mwIndex *> (maybe_mark_foreign (ptr));
   }
 
-  mwIndex * get_jc (void) const
+  mwIndex * get_jc () const
   {
     // Casting away const required for MEX interface.
 
@@ -832,7 +838,7 @@
     return static_cast<mwIndex *> (maybe_mark_foreign (ptr));
   }
 
-  mwSize get_nzmax (void) const { return m_val.nzmax (); }
+  mwSize get_nzmax () const { return m_val.nzmax (); }
 
   // Not allowed.
   VOID_MUTATION_METHOD (set_ir, (mwIndex *))
@@ -854,7 +860,7 @@
   // Not allowed.
   VOID_MUTATION_METHOD (set_field_by_number, (mwIndex, int, mxArray *))
 
-  int get_number_of_fields (void) const { return m_val.nfields (); }
+  int get_number_of_fields () const { return m_val.nfields (); }
 
   CONST_MUTATION_METHOD (const char *, get_field_name_by_number, (int), nullptr)
 
@@ -883,7 +889,7 @@
     return retval;
   }
 
-  char * array_to_string (void) const
+  char * array_to_string () const
   {
     // FIXME: this is supposed to handle multi-byte character strings.
 
@@ -919,7 +925,7 @@
     return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);
   }
 
-  std::size_t get_element_size (void) const
+  std::size_t get_element_size () const
   {
     // Force m_id to be cached.
     get_class_id ();
@@ -947,19 +953,19 @@
       }
   }
 
-  bool mutation_needed (void) const { return m_mutate_flag; }
-
-  void request_mutation (void) const
+  bool mutation_needed () const { return m_mutate_flag; }
+
+  void request_mutation () const
   {
     if (m_mutate_flag)
-      panic_impossible ();
+      error ("unexpected: m_mutate_flag is true in mxArray_octave_value::request_mutation - please report this bug");
 
     m_mutate_flag = true;
   }
 
-  mxArray * mutate (void) const { return as_mxArray (); }
-
-  octave_value as_octave_value (void) const { return m_val; }
+  mxArray * mutate () const { return as_mxArray (); }
+
+  octave_value as_octave_value () const { return m_val; }
 
 protected:
 
@@ -1009,33 +1015,33 @@
 
   mxArray_matlab& operator = (const mxArray_matlab&) = delete;
 
-  ~mxArray_matlab (void)
+  ~mxArray_matlab ()
   {
     mxFree (m_class_name);
     mxFree (m_dims);
   }
 
-  int iscell (void) const { return m_id == mxCELL_CLASS; }
-
-  int is_char (void) const { return m_id == mxCHAR_CLASS; }
-
-  int is_complex (void) const { return m_is_complex; }
-
-  int is_double (void) const { return m_id == mxDOUBLE_CLASS; }
-
-  int is_function_handle (void) const { return m_id == mxFUNCTION_CLASS; }
-
-  int is_int16 (void) const { return m_id == mxINT16_CLASS; }
-
-  int is_int32 (void) const { return m_id == mxINT32_CLASS; }
-
-  int is_int64 (void) const { return m_id == mxINT64_CLASS; }
-
-  int is_int8 (void) const { return m_id == mxINT8_CLASS; }
-
-  int is_logical (void) const { return m_id == mxLOGICAL_CLASS; }
-
-  int is_numeric (void) const
+  int iscell () const { return m_id == mxCELL_CLASS; }
+
+  int is_char () const { return m_id == mxCHAR_CLASS; }
+
+  int is_complex () const { return m_is_complex; }
+
+  int is_double () const { return m_id == mxDOUBLE_CLASS; }
+
+  int is_function_handle () const { return m_id == mxFUNCTION_CLASS; }
+
+  int is_int16 () const { return m_id == mxINT16_CLASS; }
+
+  int is_int32 () const { return m_id == mxINT32_CLASS; }
+
+  int is_int64 () const { return m_id == mxINT64_CLASS; }
+
+  int is_int8 () const { return m_id == mxINT8_CLASS; }
+
+  int is_logical () const { return m_id == mxLOGICAL_CLASS; }
+
+  int is_numeric () const
   {
     return (m_id == mxDOUBLE_CLASS || m_id == mxSINGLE_CLASS
             || m_id == mxINT8_CLASS || m_id == mxUINT8_CLASS
@@ -1044,29 +1050,29 @@
             || m_id == mxINT64_CLASS || m_id == mxUINT64_CLASS);
   }
 
-  int is_single (void) const { return m_id == mxSINGLE_CLASS; }
-
-  int is_sparse (void) const { return 0; }
-
-  int is_struct (void) const { return m_id == mxSTRUCT_CLASS; }
-
-  int is_uint16 (void) const { return m_id == mxUINT16_CLASS; }
-
-  int is_uint32 (void) const { return m_id == mxUINT32_CLASS; }
-
-  int is_uint64 (void) const { return m_id == mxUINT64_CLASS; }
-
-  int is_uint8 (void) const { return m_id == mxUINT8_CLASS; }
-
-  int is_logical_scalar_true (void) const
+  int is_single () const { return m_id == mxSINGLE_CLASS; }
+
+  int is_sparse () const { return 0; }
+
+  int is_struct () const { return m_id == mxSTRUCT_CLASS; }
+
+  int is_uint16 () const { return m_id == mxUINT16_CLASS; }
+
+  int is_uint32 () const { return m_id == mxUINT32_CLASS; }
+
+  int is_uint64 () const { return m_id == mxUINT64_CLASS; }
+
+  int is_uint8 () const { return m_id == mxUINT8_CLASS; }
+
+  int is_logical_scalar_true () const
   {
     return (is_logical_scalar ()
             && static_cast<mxLogical *> (get_data ())[0] != 0);
   }
 
-  mwSize get_m (void) const { return m_dims[0]; }
-
-  mwSize get_n (void) const
+  mwSize get_m () const { return m_dims[0]; }
+
+  mwSize get_n () const
   {
     mwSize n = 1;
 
@@ -1076,9 +1082,9 @@
     return n;
   }
 
-  mwSize * get_dimensions (void) const { return m_dims; }
-
-  mwSize get_number_of_dimensions (void) const { return m_ndims; }
+  mwSize * get_dimensions () const { return m_dims; }
+
+  mwSize get_number_of_dimensions () const { return m_ndims; }
 
   void set_m (mwSize m) { m_dims[0] = m; }
 
@@ -1110,7 +1116,7 @@
       }
   }
 
-  mwSize get_number_of_elements (void) const
+  mwSize get_number_of_elements () const
   {
     mwSize retval = m_dims[0];
 
@@ -1120,18 +1126,18 @@
     return retval;
   }
 
-  int isempty (void) const { return get_number_of_elements () == 0; }
-
-  bool is_scalar (void) const
+  int isempty () const { return get_number_of_elements () == 0; }
+
+  bool is_scalar () const
   {
     return m_ndims == 2 && m_dims[0] == 1 && m_dims[1] == 1;
   }
 
-  mxClassID get_class_id (void) const { return m_id; }
-
-  const char * get_class_name (void) const
+  mxClassID get_class_id () const { return m_id; }
+
+  static std::string get_class_name (mxClassID id)
   {
-    switch (m_id)
+    switch (id)
       {
       case mxDOUBLE_CLASS: return "double";
       case mxSINGLE_CLASS: return "single";
@@ -1154,6 +1160,11 @@
       }
   }
 
+  const char * get_class_name () const
+  {
+    return m_class_name;
+  }
+
   void set_class_name (const char *name)
   {
     mxFree (m_class_name);
@@ -1171,77 +1182,77 @@
     err_invalid_type ("set_cell");
   }
 
-  double get_scalar (void) const
+  double get_scalar () const
   {
     err_invalid_type ("get_scalar");
   }
 
-  void * get_data (void) const
+  void * get_data () const
   {
     err_invalid_type ("get_data");
   }
 
-  mxDouble * get_doubles (void) const
+  mxDouble * get_doubles () const
   {
     err_invalid_type ("get_doubles");
   }
 
-  mxSingle * get_singles (void) const
+  mxSingle * get_singles () const
   {
     err_invalid_type ("get_singles");
   }
 
-  mxInt8 * get_int8s (void) const
+  mxInt8 * get_int8s () const
   {
     err_invalid_type ("get_int8s");
   }
 
-  mxInt16 * get_int16s (void) const
+  mxInt16 * get_int16s () const
   {
     err_invalid_type ("get_int16s");
   }
 
-  mxInt32 * get_int32s (void) const
+  mxInt32 * get_int32s () const
   {
     err_invalid_type ("get_int32s");
   }
 
-  mxInt64 * get_int64s (void) const
+  mxInt64 * get_int64s () const
   {
     err_invalid_type ("get_int64s");
   }
 
-  mxUint8 * get_uint8s (void) const
+  mxUint8 * get_uint8s () const
   {
     err_invalid_type ("get_uint8s");
   }
 
-  mxUint16 * get_uint16s (void) const
+  mxUint16 * get_uint16s () const
   {
     err_invalid_type ("get_uint16s");
   }
 
-  mxUint32 * get_uint32s (void) const
+  mxUint32 * get_uint32s () const
   {
     err_invalid_type ("get_uint32s");
   }
 
-  mxUint64 * get_uint64s (void) const
+  mxUint64 * get_uint64s () const
   {
     err_invalid_type ("get_uint64s");
   }
 
-  mxComplexDouble * get_complex_doubles (void) const
+  mxComplexDouble * get_complex_doubles () const
   {
     err_invalid_type ("get_complex_doubles");
   }
 
-  mxComplexSingle * get_complex_singles (void) const
+  mxComplexSingle * get_complex_singles () const
   {
     err_invalid_type ("get_complex_singles");
   }
 
-  void * get_imag_data (void) const
+  void * get_imag_data () const
   {
     err_invalid_type ("get_imag_data");
   }
@@ -1316,17 +1327,17 @@
     err_invalid_type ("set_imag_data");
   }
 
-  mwIndex * get_ir (void) const
+  mwIndex * get_ir () const
   {
     err_invalid_type ("get_ir");
   }
 
-  mwIndex * get_jc (void) const
+  mwIndex * get_jc () const
   {
     err_invalid_type ("get_jc");
   }
 
-  mwSize get_nzmax (void) const
+  mwSize get_nzmax () const
   {
     err_invalid_type ("get_nzmax");
   }
@@ -1367,7 +1378,7 @@
     err_invalid_type ("set_field_by_number");
   }
 
-  int get_number_of_fields (void) const
+  int get_number_of_fields () const
   {
     err_invalid_type ("get_number_of_fields");
   }
@@ -1387,7 +1398,7 @@
     err_invalid_type ("get_string");
   }
 
-  char * array_to_string (void) const
+  char * array_to_string () const
   {
     err_invalid_type ("array_to_string");
   }
@@ -1397,7 +1408,7 @@
     return calc_single_subscript_internal (m_ndims, m_dims, nsubs, subs);
   }
 
-  std::size_t get_element_size (void) const
+  std::size_t get_element_size () const
   {
     switch (m_id)
       {
@@ -1493,7 +1504,7 @@
   void set_complexity (bool is_complex) { m_is_complex = is_complex; }
 
   dim_vector
-  dims_to_dim_vector (void) const
+  dims_to_dim_vector () const
   {
     mwSize nd = get_number_of_dimensions ();
 
@@ -1605,23 +1616,25 @@
 
   mxArray_base_full& operator = (const mxArray_base_full&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_base_full (*this);
   }
 
-  ~mxArray_base_full (void)
+  ~mxArray_base_full ()
   {
     mxFree (m_pr);
   }
 
-  double get_scalar (void) const
+  double get_scalar () const
   {
     // FIXME: how does this work for interleaved complex arrays?
 
     double retval = 0;
 
-    switch (get_class_id ())
+    mxClassID id = get_class_id ();
+
+    switch (id)
       {
       case mxDOUBLE_CLASS:
         retval = *(static_cast<double *> (m_pr));
@@ -1671,14 +1684,27 @@
         retval = *(static_cast<uint64_t *> (m_pr));
         break;
 
-      default:
-        panic_impossible ();
+      case mxCELL_CLASS:
+      case mxFUNCTION_CLASS:
+      case mxSTRUCT_CLASS:
+      case mxUNKNOWN_CLASS:
+      case mxVOID_CLASS:
+        {
+          std::string dest_cname = get_class_name (id);
+          error ("invalid conversion from %s mxArray to %s scalar value", get_class_name (), dest_cname.c_str ());
+        }
+        break;
+
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
     return retval;
   }
 
-  void * get_data (void) const { return m_pr; }
+  void * get_data () const { return m_pr; }
 
   void set_data (void *pr) { m_pr = pr; }
 
@@ -1687,62 +1713,62 @@
   // definitions in the mxArray_separate_full class that override these
   // functions.
 
-  mxDouble * get_doubles (void) const
+  mxDouble * get_doubles () const
   {
     return static_cast<mxDouble *> (m_pr);
   }
 
-  mxSingle * get_singles (void) const
+  mxSingle * get_singles () const
   {
     return static_cast<mxSingle *> (m_pr);
   }
 
-  mxInt8 * get_int8s (void) const
+  mxInt8 * get_int8s () const
   {
     return static_cast<mxInt8 *> (m_pr);
   }
 
-  mxInt16 * get_int16s (void) const
+  mxInt16 * get_int16s () const
   {
     return static_cast<mxInt16 *> (m_pr);
   }
 
-  mxInt32 * get_int32s (void) const
+  mxInt32 * get_int32s () const
   {
     return static_cast<mxInt32 *> (m_pr);
   }
 
-  mxInt64 * get_int64s (void) const
+  mxInt64 * get_int64s () const
   {
     return static_cast<mxInt64 *> (m_pr);
   }
 
-  mxUint8 * get_uint8s (void) const
+  mxUint8 * get_uint8s () const
   {
     return static_cast<mxUint8 *> (m_pr);
   }
 
-  mxUint16 * get_uint16s (void) const
+  mxUint16 * get_uint16s () const
   {
     return static_cast<mxUint16 *> (m_pr);
   }
 
-  mxUint32 * get_uint32s (void) const
+  mxUint32 * get_uint32s () const
   {
     return static_cast<mxUint32 *> (m_pr);
   }
 
-  mxUint64 * get_uint64s (void) const
+  mxUint64 * get_uint64s () const
   {
     return static_cast<mxUint64 *> (m_pr);
   }
 
-  mxComplexDouble * get_complex_doubles (void) const
+  mxComplexDouble * get_complex_doubles () const
   {
     return static_cast<mxComplexDouble *> (m_pr);
   }
 
-  mxComplexSingle * get_complex_singles (void) const
+  mxComplexSingle * get_complex_singles () const
   {
     return static_cast<mxComplexSingle *> (m_pr);
   }
@@ -1845,7 +1871,7 @@
     return retval;
   }
 
-  char * array_to_string (void) const
+  char * array_to_string () const
   {
     // FIXME: this is supposed to handle multi-byte character strings.
 
@@ -1866,11 +1892,11 @@
     return buf;
   }
 
-  octave_value as_octave_value (void) const
+  octave_value as_octave_value () const
   {
     octave_value retval;
 
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     switch (get_class_id ())
       {
@@ -1912,8 +1938,18 @@
       case mxUINT64_CLASS:
         return int_to_ov<uint64_t, uint64NDArray, octave_uint64> (dv);
 
-      default:
-        panic_impossible ();
+      case mxCELL_CLASS:
+      case mxFUNCTION_CLASS:
+      case mxSTRUCT_CLASS:
+      case mxUNKNOWN_CLASS:
+      case mxVOID_CLASS:
+        error ("invalid conversion from %s%s mxArray to octave_value", (is_complex () ? "complex " : ""), get_class_name ());
+        break;
+
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
     return retval;
@@ -1941,7 +1977,7 @@
 
     if (current_mx_memory_resource == &the_mx_deleting_memory_resource)
       {
-        octave::unwind_action act ([=] () { maybe_disown_ptr (m_pr); });
+        octave::unwind_action act ([this] () { maybe_disown_ptr (m_pr); });
 
         return octave_value (Array<ELT_T> (ppr, dv, current_mx_memory_resource));
       }
@@ -1955,7 +1991,7 @@
 
     Array<ELT_T> val (dv);
 
-    ELT_T *ptr = val.fortran_vec ();
+    ELT_T *ptr = val.rwdata ();
 
     mwSize nel = get_number_of_elements ();
 
@@ -1981,7 +2017,7 @@
 
     ARRAY_T val (dv);
 
-    ARRAY_ELT_T *ptr = val.fortran_vec ();
+    ARRAY_ELT_T *ptr = val.rwdata ();
 
     mwSize nel = get_number_of_elements ();
 
@@ -2043,16 +2079,16 @@
 
   mxArray_interleaved_full& operator = (const mxArray_interleaved_full&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_interleaved_full (*this);
   }
 
-  ~mxArray_interleaved_full (void) = default;
-
-  void * get_imag_data (void) const { panic_impossible (); }
-
-  void set_imag_data (void */*pi*/) { panic_impossible (); }
+  ~mxArray_interleaved_full () = default;
+
+  void * get_imag_data () const { error_impossible_call ("mxArray_interleaved_full::get_imag_data"); }
+
+  void set_imag_data (void */*pi*/) { error_impossible_call ("mxArray_interleaved_full::set_imag_data"); }
 
 protected:
 
@@ -2113,17 +2149,17 @@
 
   mxArray_separate_full& operator = (const mxArray_separate_full&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_separate_full (*this);
   }
 
-  ~mxArray_separate_full (void)
+  ~mxArray_separate_full ()
   {
     mxFree (m_pi);
   }
 
-  void * get_imag_data (void) const { return m_pi; }
+  void * get_imag_data () const { return m_pi; }
 
   void set_imag_data (void *pi)
   {
@@ -2132,64 +2168,64 @@
     set_complexity (m_pi != nullptr);
   }
 
-  mxDouble * get_doubles (void) const { panic_impossible (); }
-  mxSingle * get_singles (void) const { panic_impossible (); }
-  mxInt8 * get_int8s (void) const { panic_impossible (); }
-  mxInt16 * get_int16s (void) const { panic_impossible (); }
-  mxInt32 * get_int32s (void) const { panic_impossible (); }
-  mxInt64 * get_int64s (void) const { panic_impossible (); }
-  mxUint8 * get_uint8s (void) const { panic_impossible (); }
-  mxUint16 * get_uint16s (void) const { panic_impossible (); }
-  mxUint32 * get_uint32s (void) const { panic_impossible (); }
-  mxUint64 * get_uint64s (void) const { panic_impossible (); }
-
-  mxComplexDouble * get_complex_doubles (void) const { panic_impossible (); }
-  mxComplexSingle * get_complex_singles (void) const { panic_impossible (); }
+  mxDouble * get_doubles () const { error_impossible_call ("mxArray_separate_full::get_doubles"); }
+  mxSingle * get_singles () const { error_impossible_call ("mxArray_separate_full::get_singles"); }
+  mxInt8 * get_int8s () const { error_impossible_call ("mxArray_separate_full::get_int8s"); }
+  mxInt16 * get_int16s () const { error_impossible_call ("mxArray_separate_full::get_int16s"); }
+  mxInt32 * get_int32s () const { error_impossible_call ("mxArray_separate_full::get_int32s"); }
+  mxInt64 * get_int64s () const { error_impossible_call ("mxArray_separate_full::get_int64s"); }
+  mxUint8 * get_uint8s () const { error_impossible_call ("mxArray_separate_full::get_uint8s"); }
+  mxUint16 * get_uint16s () const { error_impossible_call ("mxArray_separate_full::get_uint16s"); }
+  mxUint32 * get_uint32s () const { error_impossible_call ("mxArray_separate_full::get_uint32s"); }
+  mxUint64 * get_uint64s () const { error_impossible_call ("mxArray_separate_full::get_uint64s"); }
+
+  mxComplexDouble * get_complex_doubles () const { error_impossible_call ("mxArray_separate_full::get_complex_doubles"); }
+  mxComplexSingle * get_complex_singles () const { error_impossible_call ("mxArray_separate_full::get_complex_singles"); }
 
   // We don't have complex integer types, but for separate storage they
   // still would not work.
-  mxComplexInt8 * get_complex_int8s (void) const { panic_impossible (); }
-  mxComplexInt16 * get_complex_int16s (void) const { panic_impossible (); }
-  mxComplexInt32 * get_complex_int32s (void) const { panic_impossible (); }
-  mxComplexInt64 * get_complex_int64s (void) const { panic_impossible (); }
-  mxComplexUint8 * get_complex_uint8s (void) const { panic_impossible (); }
-  mxComplexUint16 * get_complex_uint16s (void) const { panic_impossible (); }
-  mxComplexUint32 * get_complex_uint32s (void) const { panic_impossible (); }
-  mxComplexUint64 * get_complex_uint64s (void) const { panic_impossible (); }
-
-  int set_doubles (mxDouble *) { panic_impossible (); }
-  int set_singles (mxSingle *) { panic_impossible (); }
-  int set_int8s (mxInt8 *) { panic_impossible (); }
-  int set_int16s (mxInt16 *) { panic_impossible (); }
-  int set_int32s (mxInt32 *) { panic_impossible (); }
-  int set_int64s (mxInt64 *) { panic_impossible (); }
-  int set_uint8s (mxUint8 *) { panic_impossible (); }
-  int set_uint16s (mxUint16 *) { panic_impossible (); }
-  int set_uint32s (mxUint32 *) { panic_impossible (); }
-  int set_uint64s (mxUint64 *) { panic_impossible (); }
-
-  int set_complex_doubles (mxComplexDouble *) { panic_impossible (); }
-  int set_complex_singles (mxComplexSingle *) { panic_impossible (); }
+  mxComplexInt8 * get_complex_int8s () const { error_impossible_call ("mxArray_separate_full::get_complex_int8s"); }
+  mxComplexInt16 * get_complex_int16s () const { error_impossible_call ("mxArray_separate_full::get_complex_int16s"); }
+  mxComplexInt32 * get_complex_int32s () const { error_impossible_call ("mxArray_separate_full::get_complex_int32s"); }
+  mxComplexInt64 * get_complex_int64s () const { error_impossible_call ("mxArray_separate_full::get_complex_int64s"); }
+  mxComplexUint8 * get_complex_uint8s () const { error_impossible_call ("mxArray_separate_full::get_complex_uint8s"); }
+  mxComplexUint16 * get_complex_uint16s () const { error_impossible_call ("mxArray_separate_full::get_complex_uint16s"); }
+  mxComplexUint32 * get_complex_uint32s () const { error_impossible_call ("mxArray_separate_full::get_complex_uint32s"); }
+  mxComplexUint64 * get_complex_uint64s () const { error_impossible_call ("mxArray_separate_full::get_complex_uint64s"); }
+
+  int set_doubles (mxDouble *) { error_impossible_call ("mxArray_separate_full::set_doubles"); }
+  int set_singles (mxSingle *) { error_impossible_call ("mxArray_separate_full::set_singles"); }
+  int set_int8s (mxInt8 *) { error_impossible_call ("mxArray_separate_full::set_int8s"); }
+  int set_int16s (mxInt16 *) { error_impossible_call ("mxArray_separate_full::set_int16s"); }
+  int set_int32s (mxInt32 *) { error_impossible_call ("mxArray_separate_full::set_int32s"); }
+  int set_int64s (mxInt64 *) { error_impossible_call ("mxArray_separate_full::set_int64s"); }
+  int set_uint8s (mxUint8 *) { error_impossible_call ("mxArray_separate_full::set_uint8s"); }
+  int set_uint16s (mxUint16 *) { error_impossible_call ("mxArray_separate_full::set_uint16s"); }
+  int set_uint32s (mxUint32 *) { error_impossible_call ("mxArray_separate_full::set_uint32s"); }
+  int set_uint64s (mxUint64 *) { error_impossible_call ("mxArray_separate_full::set_uint64s"); }
+
+  int set_complex_doubles (mxComplexDouble *) { error_impossible_call ("mxArray_separate_full::set_complex_doubles"); }
+  int set_complex_singles (mxComplexSingle *) { error_impossible_call ("mxArray_separate_full::set_complex_singles"); }
 
   // We don't have complex integer types, but for separate storage they
   // still would not work.
-  int set_complex_int8s (mxComplexInt8 *) { panic_impossible (); }
-  int set_complex_int16s (mxComplexInt16 *) { panic_impossible (); }
-  int set_complex_int32s (mxComplexInt32 *) { panic_impossible (); }
-  int set_complex_int64s (mxComplexInt64 *) { panic_impossible (); }
-  int set_complex_uint8s (mxComplexUint8 *) { panic_impossible (); }
-  int set_complex_uint16s (mxComplexUint16 *) { panic_impossible (); }
-  int set_complex_uint32s (mxComplexUint32 *) { panic_impossible (); }
-  int set_complex_uint64s (mxComplexUint64 *) { panic_impossible (); }
-
-  octave_value as_octave_value (void) const
+  int set_complex_int8s (mxComplexInt8 *) { error_impossible_call ("mxArray_separate_full::set_complex_int8s"); }
+  int set_complex_int16s (mxComplexInt16 *) { error_impossible_call ("mxArray_separate_full::set_complex_int16s"); }
+  int set_complex_int32s (mxComplexInt32 *) { error_impossible_call ("mxArray_separate_full::set_complex_int32s"); }
+  int set_complex_int64s (mxComplexInt64 *) { error_impossible_call ("mxArray_separate_full::set_complex_int64s"); }
+  int set_complex_uint8s (mxComplexUint8 *) { error_impossible_call ("mxArray_separate_full::set_complex_uint8s"); }
+  int set_complex_uint16s (mxComplexUint16 *) { error_impossible_call ("mxArray_separate_full::set_complex_uint16s"); }
+  int set_complex_uint32s (mxComplexUint32 *) { error_impossible_call ("mxArray_separate_full::set_complex_uint32s"); }
+  int set_complex_uint64s (mxComplexUint64 *) { error_impossible_call ("mxArray_separate_full::set_complex_uint64s"); }
+
+  octave_value as_octave_value () const
   {
     if (! is_complex ())
       return mxArray_base_full::as_octave_value ();
 
     octave_value retval;
 
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     switch (get_class_id ())
       {
@@ -2210,8 +2246,19 @@
       case mxUINT64_CLASS:
         error ("complex integer types are not supported");
 
-      default:
-        panic_impossible ();
+      case mxCELL_CLASS:
+      case mxCHAR_CLASS:
+      case mxFUNCTION_CLASS:
+      case mxSTRUCT_CLASS:
+      case mxUNKNOWN_CLASS:
+      case mxVOID_CLASS:
+        error ("invalid conversion from complex %s mxArray to octave_value", get_class_name ());
+        break;
+
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
     return retval;
@@ -2244,7 +2291,7 @@
 
     Array<std::complex<T>> val (dv);
 
-    std::complex<T> *ptr = val.fortran_vec ();
+    std::complex<T> *ptr = val.rwdata ();
 
     T *ppi = static_cast<T *> (m_pi);
 
@@ -2301,30 +2348,30 @@
 
   mxArray_base_sparse& operator = (const mxArray_base_sparse&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_base_sparse (*this);
   }
 
-  ~mxArray_base_sparse (void)
+  ~mxArray_base_sparse ()
   {
     mxFree (m_ir);
     mxFree (m_jc);
     mxFree (m_pr);
   }
 
-  int is_sparse (void) const { return 1; }
-
-  void * get_data (void) const { return m_pr; }
+  int is_sparse () const { return 1; }
+
+  void * get_data () const { return m_pr; }
 
   void set_data (void *pr) { m_pr = pr; }
 
-  mxDouble * get_doubles (void) const
+  mxDouble * get_doubles () const
   {
     return static_cast<mxDouble *> (m_pr);
   }
 
-  mxComplexDouble * get_complex_doubles (void) const
+  mxComplexDouble * get_complex_doubles () const
   {
     return static_cast<mxComplexDouble *> (m_pr);
   }
@@ -2341,11 +2388,11 @@
     return 0;
   }
 
-  mwIndex * get_ir (void) const { return m_ir; }
-
-  mwIndex * get_jc (void) const { return m_jc; }
-
-  mwSize get_nzmax (void) const { return m_nzmax; }
+  mwIndex * get_ir () const { return m_ir; }
+
+  mwIndex * get_jc () const { return m_jc; }
+
+  mwSize get_nzmax () const { return m_nzmax; }
 
   void set_ir (mwIndex *ir) { m_ir = ir; }
 
@@ -2357,11 +2404,11 @@
     m_nzmax = (nzmax > 0 ? nzmax : 1);
   }
 
-  octave_value as_octave_value (void) const
+  octave_value as_octave_value () const
   {
     octave_value retval;
 
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     switch (get_class_id ())
       {
@@ -2374,8 +2421,27 @@
       case mxLOGICAL_CLASS:
         return to_ov<bool> (dv);
 
-      default:
-        panic_impossible ();
+      case mxINT8_CLASS:
+      case mxUINT8_CLASS:
+      case mxINT16_CLASS:
+      case mxUINT16_CLASS:
+      case mxINT32_CLASS:
+      case mxUINT32_CLASS:
+      case mxINT64_CLASS:
+      case mxUINT64_CLASS:
+      case mxCELL_CLASS:
+      case mxCHAR_CLASS:
+      case mxFUNCTION_CLASS:
+      case mxSTRUCT_CLASS:
+      case mxUNKNOWN_CLASS:
+      case mxVOID_CLASS:
+        error ("invalid conversion from %s%s sparse mxArray to octave_value", (is_complex () ? "complex " : ""), get_class_name ());
+        break;
+
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
     return retval;
@@ -2393,7 +2459,7 @@
 
     if (current_mx_memory_resource == &the_mx_deleting_memory_resource)
       {
-        octave::unwind_action act ([=] ()
+        octave::unwind_action act ([this] ()
         {
           maybe_disown_ptr (m_pr);
           maybe_disown_ptr (m_ir);
@@ -2469,16 +2535,16 @@
 
   mxArray_interleaved_sparse& operator = (const mxArray_interleaved_sparse&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_interleaved_sparse (*this);
   }
 
-  ~mxArray_interleaved_sparse (void) = default;
-
-  void * get_imag_data (void) const { panic_impossible (); }
-
-  void set_imag_data (void */*pi*/) { panic_impossible (); }
+  ~mxArray_interleaved_sparse () = default;
+
+  void * get_imag_data () const { error_impossible_call ("mxArray_interleaved_sparse::get_imag_data"); }
+
+  void set_imag_data (void */*pi*/) { error_impossible_call ("mxArray_interleaved_sparse::set_imag_data"); }
 };
 
 class mxArray_separate_sparse : public mxArray_base_sparse
@@ -2514,17 +2580,17 @@
 
   mxArray_separate_sparse& operator = (const mxArray_separate_sparse&) = delete;
 
-  mxArray_base * dup (void) const
+  mxArray_base * dup () const
   {
     return new mxArray_separate_sparse (*this);
   }
 
-  ~mxArray_separate_sparse (void)
+  ~mxArray_separate_sparse ()
   {
     mxFree (m_pi);
   }
 
-  void * get_imag_data (void) const { return m_pi; }
+  void * get_imag_data () const { return m_pi; }
 
   void set_imag_data (void *pi)
   {
@@ -2532,20 +2598,20 @@
     set_complexity (m_pi != nullptr);
   }
 
-  mxDouble * get_doubles (void) const { panic_impossible (); }
-  mxComplexDouble * get_complex_doubles (void) const { panic_impossible (); }
-
-  int set_doubles (mxDouble *) { panic_impossible (); }
-  int set_complex_doubles (mxComplexDouble *) { panic_impossible (); }
-
-  octave_value as_octave_value (void) const
+  mxDouble * get_doubles () const { error_impossible_call ("mxArray_separate_sparse::get_doubles"); }
+  mxComplexDouble * get_complex_doubles () const { error_impossible_call ("mxArray_separate_sparse::get_complex_doubles"); }
+
+  int set_doubles (mxDouble *) { error_impossible_call ("mxArray_separate_sparse::set_doubles"); }
+  int set_complex_doubles (mxComplexDouble *) { error_impossible_call ("mxArray_separate_sparse::set_complex_doubles"); }
+
+  octave_value as_octave_value () const
   {
     if (! is_complex ())
       return mxArray_base_sparse::as_octave_value ();
 
     octave_value retval;
 
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     switch (get_class_id ())
       {
@@ -2573,8 +2639,28 @@
       case mxSINGLE_CLASS:
         error ("single precision sparse data type not supported");
 
-      default:
-        panic_impossible ();
+      case mxLOGICAL_CLASS:
+      case mxINT8_CLASS:
+      case mxUINT8_CLASS:
+      case mxINT16_CLASS:
+      case mxUINT16_CLASS:
+      case mxINT32_CLASS:
+      case mxUINT32_CLASS:
+      case mxINT64_CLASS:
+      case mxUINT64_CLASS:
+      case mxCELL_CLASS:
+      case mxCHAR_CLASS:
+      case mxFUNCTION_CLASS:
+      case mxSTRUCT_CLASS:
+      case mxUNKNOWN_CLASS:
+      case mxVOID_CLASS:
+        error ("invalid conversion from complex %s sparse mxArray to octave_value", get_class_name ());
+        break;
+
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
     return retval;
@@ -2668,9 +2754,9 @@
       m_fields[i] = mxArray::strsave (keys[i]);
   }
 
-  mxArray_base * dup (void) const { return new mxArray_struct (*this); }
-
-  ~mxArray_struct (void)
+  mxArray_base * dup () const { return new mxArray_struct (*this); }
+
+  ~mxArray_struct ()
   {
     for (int i = 0; i < m_nfields; i++)
       mxFree (m_fields[i]);
@@ -2793,7 +2879,7 @@
 
   void set_field_by_number (mwIndex index, int key_num, mxArray *val);
 
-  int get_number_of_fields (void) const { return m_nfields; }
+  int get_number_of_fields () const { return m_nfields; }
 
   const char * get_field_name_by_number (int key_num) const
   {
@@ -2816,13 +2902,13 @@
     return retval;
   }
 
-  void * get_data (void) const { return m_data; }
+  void * get_data () const { return m_data; }
 
   void set_data (void *data) { m_data = static_cast<mxArray **> (data); }
 
-  octave_value as_octave_value (void) const
+  octave_value as_octave_value () const
   {
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     string_vector keys (m_fields, m_nfields);
 
@@ -2834,7 +2920,7 @@
       {
         Cell c (dv);
 
-        octave_value *p = c.fortran_vec ();
+        octave_value *p = c.rwdata ();
 
         mwIndex k = 0;
         for (mwIndex j = i; j < ntot; j += m_nfields)
@@ -2900,9 +2986,9 @@
 
   mxArray_cell& operator = (const mxArray_cell&) = delete;
 
-  mxArray_base * dup (void) const { return new mxArray_cell (*this); }
-
-  ~mxArray_cell (void)
+  mxArray_base * dup () const { return new mxArray_cell (*this); }
+
+  ~mxArray_cell ()
   {
     mwSize nel = get_number_of_elements ();
 
@@ -2919,19 +3005,19 @@
 
   void set_cell (mwIndex idx, mxArray *val);
 
-  void * get_data (void) const { return m_data; }
+  void * get_data () const { return m_data; }
 
   void set_data (void *data) { m_data = static_cast<mxArray **> (data); }
 
-  octave_value as_octave_value (void) const
+  octave_value as_octave_value () const
   {
-    dim_vector dv = dims_to_dim_vector ();
+    const dim_vector& dv = dims_to_dim_vector ();
 
     Cell c (dv);
 
     mwSize nel = get_number_of_elements ();
 
-    octave_value *p = c.fortran_vec ();
+    octave_value *p = c.rwdata ();
 
     for (mwIndex i = 0; i < nel; i++)
       p[i] = mxArray::as_octave_value (m_data[i]);
@@ -3018,7 +3104,7 @@
   : m_rep (new mxArray_cell (interleaved, m, n)), m_name (nullptr)
 { }
 
-mxArray::~mxArray (void)
+mxArray::~mxArray ()
 {
   mxFree (m_name);
 
@@ -3043,7 +3129,7 @@
 }
 
 octave_value
-mxArray::as_octave_value (void) const
+mxArray::as_octave_value () const
 {
   return m_rep->as_octave_value ();
 }
@@ -3131,7 +3217,7 @@
 }
 
 void
-mxArray::maybe_mutate (void) const
+mxArray::maybe_mutate () const
 {
   if (m_rep->is_octave_value ())
     {
@@ -3165,7 +3251,7 @@
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (mex)
 
-  ~mex (void)
+  ~mex ()
   {
     // We can't use mex::free here because it modifies memlist.
     while (! m_memlist.empty ())
@@ -3189,7 +3275,7 @@
     mxFree (m_fname);
   }
 
-  const char * function_name (void) const
+  const char * function_name () const
   {
     if (! m_fname)
       {
@@ -3414,7 +3500,7 @@
     return inlist;
   }
 
-  octave_mex_function& current_mex_function (void) const
+  octave_mex_function& current_mex_function () const
   {
     return m_curr_mex_fcn;
   }
@@ -3559,35 +3645,35 @@
 bool
 mxIsFinite (const double v)
 {
-  return lo_ieee_isfinite (v) != 0;
+  return octave::math::isfinite (v) != 0;
 }
 
 bool
 mxIsInf (const double v)
 {
-  return lo_ieee_isinf (v) != 0;
+  return octave::math::isinf (v) != 0;
 }
 
 bool
 mxIsNaN (const double v)
 {
-  return lo_ieee_isnan (v) != 0;
+  return octave::math::isnan (v) != 0;
 }
 
 double
-mxGetEps (void)
+mxGetEps ()
 {
   return std::numeric_limits<double>::epsilon ();
 }
 
 double
-mxGetInf (void)
+mxGetInf ()
 {
   return lo_ieee_inf_value ();
 }
 
 double
-mxGetNaN (void)
+mxGetNaN ()
 {
   return lo_ieee_nan_value ();
 }
@@ -4474,7 +4560,7 @@
   // Use at least 1 for nargout since even for zero specified args,
   // still want to be able to return an ans.
 
-  volatile int nargout = nargout_arg;
+  int nargout = nargout_arg;
 
   int nargin = args.length ();
   OCTAVE_LOCAL_BUFFER (mxArray *, argin, nargin);
@@ -4541,7 +4627,7 @@
 // C interface to mex functions:
 
 const char *
-mexFunctionName (void)
+mexFunctionName ()
 {
   return mex_context ? mex_context->function_name () : "unknown";
 }
@@ -4985,7 +5071,7 @@
 }
 
 int
-mexAtExit (void (*f) (void))
+mexAtExit (void (*f) ())
 {
   if (mex_context)
     {
@@ -5032,7 +5118,7 @@
 }
 
 int
-mexIsLocked (void)
+mexIsLocked ()
 {
   int retval = 0;
 
@@ -5051,7 +5137,7 @@
 std::map<std::string, int> mex_lock_count;
 
 void
-mexLock (void)
+mexLock ()
 {
   if (mex_context)
     {
@@ -5090,7 +5176,7 @@
 }
 
 void
-mexUnlock (void)
+mexUnlock ()
 {
   if (mex_context)
     {
--- a/libinterp/corefcn/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -79,6 +79,7 @@
   %reldir%/oct.h \
   %reldir%/octave-default-image.h \
   %reldir%/pager.h \
+  %reldir%/panic.h \
   %reldir%/pr-flt-fmt.h \
   %reldir%/pr-output.h \
   %reldir%/procstream.h \
@@ -235,6 +236,7 @@
   %reldir%/ordqz.cc \
   %reldir%/ordschur.cc \
   %reldir%/pager.cc \
+  %reldir%/panic.cc \
   %reldir%/perms.cc \
   %reldir%/pinv.cc \
   %reldir%/pow2.cc \
--- a/libinterp/corefcn/mx-type-traits.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/mx-type-traits.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,12 +28,13 @@
 
 #include "octave-config.h"
 
+#include <string>
+
 #include "mxtypes.h"
 #include "oct-inttypes-fwd.h"
 
 template <typename T>
-class
-mx_type_traits
+class mx_type_traits
 {
 public:
   static const mxClassID mx_class;
@@ -41,8 +42,7 @@
 };
 
 template <>
-class
-mx_type_traits<bool>
+class mx_type_traits<bool>
 {
 public:
   static const mxClassID mx_class = mxLOGICAL_CLASS;
@@ -50,8 +50,7 @@
 };
 
 template <>
-class
-mx_type_traits<char>
+class mx_type_traits<char>
 {
 public:
   static const mxClassID mx_class = mxCHAR_CLASS;
@@ -59,8 +58,7 @@
 };
 
 template <>
-class
-mx_type_traits<double>
+class mx_type_traits<double>
 {
 public:
   static const mxClassID mx_class = mxDOUBLE_CLASS;
@@ -68,8 +66,7 @@
 };
 
 template <>
-class
-mx_type_traits<float>
+class mx_type_traits<float>
 {
 public:
   static const mxClassID mx_class = mxSINGLE_CLASS;
@@ -77,8 +74,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_int8>
+class mx_type_traits<octave_int8>
 {
 public:
   static const mxClassID mx_class = mxINT8_CLASS;
@@ -86,8 +82,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_uint8>
+class mx_type_traits<octave_uint8>
 {
 public:
   static const mxClassID mx_class = mxUINT8_CLASS;
@@ -95,8 +90,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_int16>
+class mx_type_traits<octave_int16>
 {
 public:
   static const mxClassID mx_class = mxINT16_CLASS;
@@ -104,8 +98,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_uint16>
+class mx_type_traits<octave_uint16>
 {
 public:
   static const mxClassID mx_class = mxUINT16_CLASS;
@@ -113,8 +106,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_int32>
+class mx_type_traits<octave_int32>
 {
 public:
   static const mxClassID mx_class = mxINT32_CLASS;
@@ -122,8 +114,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_uint32>
+class mx_type_traits<octave_uint32>
 {
 public:
   static const mxClassID mx_class = mxUINT32_CLASS;
@@ -131,8 +122,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_int64>
+class mx_type_traits<octave_int64>
 {
 public:
   static const mxClassID mx_class = mxINT64_CLASS;
@@ -140,8 +130,7 @@
 };
 
 template <>
-class
-mx_type_traits<octave_uint64>
+class mx_type_traits<octave_uint64>
 {
 public:
   static const mxClassID mx_class = mxUINT64_CLASS;
--- a/libinterp/corefcn/oct-errno.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-errno.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,8 +34,7 @@
 
 #include "oct-map.h"
 
-class
-octave_errno
+class octave_errno
 {
 protected:
 
--- a/libinterp/corefcn/oct-fstrm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-fstrm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-fstream : public base_stream
+class fstream : public base_stream
 {
 public:
 
--- a/libinterp/corefcn/oct-hist.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-hist.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -463,8 +463,7 @@
   // Ignore interrupts while we are off editing commands.  Should we
   // maybe avoid using system()?
 
-  volatile interrupt_handler old_interrupt_handler
-    = ignore_interrupts ();
+  interrupt_handler old_interrupt_handler = ignore_interrupts ();
 
   int status = sys::system (cmd);
 
--- a/libinterp/corefcn/oct-iostrm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-iostrm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,8 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-base_iostream : public base_stream
+class base_iostream : public base_stream
 {
 public:
 
@@ -79,8 +78,7 @@
   virtual const char * stream_type () const = 0;
 };
 
-class
-istream : public base_iostream
+class istream : public base_iostream
 {
 public:
 
@@ -113,8 +111,7 @@
   const char * stream_type () const { return "istream"; }
 };
 
-class
-ostream : public base_iostream
+class ostream : public base_iostream
 {
 public:
 
--- a/libinterp/corefcn/oct-map.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-map.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -151,7 +151,7 @@
   if (perm.numel () != n)
     perm.clear (1, n);
 
-  return equal_up_to_order (other, perm.fortran_vec ());
+  return equal_up_to_order (other, perm.rwdata ());
 }
 
 string_vector
@@ -612,7 +612,7 @@
   for (octave_idx_type j = 0; j < nf; j++)
     {
       retval.m_vals.push_back (Cell (rd));
-      error_unless (retval.m_vals[j].numel () == n);
+      panic_unless (retval.m_vals[j].numel () == n);
       for (octave_idx_type i = 0; i < n; i++)
         retval.m_vals[j].xelem (i) = map_list[i].m_vals[j];
     }
@@ -1033,7 +1033,7 @@
           error (ee, "incompatible fields in struct assignment");
         }
 
-      error_unless (rhs1.m_keys.is_same (m_keys));
+      panic_unless (rhs1.m_keys.is_same (m_keys));
       assign (i, rhs1);
     }
 }
@@ -1081,7 +1081,7 @@
           error (ee, "incompatible fields in struct assignment");
         }
 
-      error_unless (rhs1.m_keys.is_same (m_keys));
+      panic_unless (rhs1.m_keys.is_same (m_keys));
       assign (i, j, rhs1);
     }
 }
@@ -1129,7 +1129,7 @@
           error (ee, "incompatible fields in struct assignment");
         }
 
-      error_unless (rhs1.m_keys.is_same (m_keys));
+      panic_unless (rhs1.m_keys.is_same (m_keys));
       assign (ia, rhs1);
     }
 }
@@ -1334,7 +1334,7 @@
     }
   else
     {
-      dim_vector dv = dims ();
+      const dim_vector& dv = dims ();
 
       if (dv.all_zero ())
         *this = rb;
--- a/libinterp/corefcn/oct-prcstrm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-prcstrm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,8 +40,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-octave_iprocstream : public octave::stdiostream
+class octave_iprocstream : public octave::stdiostream
 {
 public:
 
@@ -64,8 +63,7 @@
   ~octave_iprocstream ();
 };
 
-class
-octave_oprocstream : public octave::stdiostream
+class octave_oprocstream : public octave::stdiostream
 {
 public:
 
--- a/libinterp/corefcn/oct-procbuf.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-procbuf.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -103,9 +103,9 @@
 
   int pipe_fds[2];
 
-  volatile int child_std_end = (mode & std::ios::in) ? 1 : 0;
+  int child_std_end = (mode & std::ios::in) ? 1 : 0;
 
-  volatile int parent_end, child_end;
+  int parent_end, child_end;
 
   if (is_open ())
     return nullptr;
--- a/libinterp/corefcn/oct-procbuf.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-procbuf.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,8 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-procbuf : public c_file_ptr_buf
+class procbuf : public c_file_ptr_buf
 {
 public:
 
--- a/libinterp/corefcn/oct-process.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-process.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-process_execution_result
+class process_execution_result
 {
 public:
 
--- a/libinterp/corefcn/oct-stdstrm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-stdstrm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,8 +36,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 template <typename BUF_T, typename STREAM_T, typename FILE_T>
-class
-tstdiostream : public base_stream
+class tstdiostream : public base_stream
 {
 public:
 
@@ -119,8 +118,7 @@
   int m_fnum;
 };
 
-class
-stdiostream
+class stdiostream
   : public tstdiostream<c_file_ptr_buf, io_c_file_ptr_stream, FILE *>
 {
 public:
@@ -152,8 +150,7 @@
 
 #if defined (HAVE_ZLIB)
 
-class
-zstdiostream
+class zstdiostream
   : public tstdiostream<c_zfile_ptr_buf, io_c_zfile_ptr_stream, gzFile>
 {
 public:
--- a/libinterp/corefcn/oct-stream.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-stream.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
 #include <cctype>
 #include <cstring>
 
@@ -110,7 +109,7 @@
 
   if (! conv_err)
     {
-      if (! lo_ieee_isnan (dval))
+      if (! math::isnan (dval))
         {
           int ival = math::nint (dval);
 
@@ -131,7 +130,7 @@
 {
   octave_idx_type retval = -1;
 
-  if (lo_ieee_isnan (d))
+  if (math::isnan (d))
     ::error ("%s: NaN invalid as size specification", who.c_str ());
 
   if (math::isinf (d))
@@ -142,9 +141,8 @@
         ::error ("%s: negative value invalid as size specification",
                  who.c_str ());
 
-      static const double out_of_range_top
-        = static_cast<double> (std::numeric_limits<octave_idx_type>::max ())
-          + 1.;
+      static constexpr double out_of_range_top
+        = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
       if (d >= out_of_range_top)
         ::error ("%s: dimension too large for Octave's index type",
                  who.c_str ());
@@ -240,8 +238,7 @@
   return retval;
 }
 
-class
-scanf_format_elt
+class scanf_format_elt
 {
 public:
 
@@ -285,8 +282,7 @@
   std::string char_class;
 };
 
-class
-scanf_format_list
+class scanf_format_list
 {
 public:
 
@@ -748,8 +744,7 @@
     return false;
 }
 
-class
-printf_format_elt
+class printf_format_elt
 {
 public:
 
@@ -789,8 +784,7 @@
   char modifier;
 };
 
-class
-printf_format_list
+class printf_format_list
 {
 public:
 
@@ -1214,8 +1208,7 @@
 // of the buffer and the buffer is refilled.  This also allows cheap
 // seek and tell operations within a "fast read" block.
 
-class
-delimited_stream
+class delimited_stream
 {
 public:
 
@@ -1637,8 +1630,7 @@
 
 // A single conversion specifier, such as %f or %c.
 
-class
-textscan_format_elt
+class textscan_format_elt
 {
 public:
 
@@ -1692,8 +1684,7 @@
 
 class textscan;
 
-class
-textscan_format_list
+class textscan_format_list
 {
 public:
 
@@ -1803,9 +1794,7 @@
 //   textscan scanner ();
 //   scanner.scan (...);
 
-class
-OCTINTERP_API
-textscan
+class OCTINTERP_API textscan
 {
 public:
 
@@ -3693,7 +3682,7 @@
         }
       else if (param == "collectoutput")
         {
-          m_collect_output = args(i+1).xbool_value ("%s: CollectOutput must be logical or numeric",
+          m_collect_output = args(i+1).ybool_value ("%s: CollectOutput must be logical or numeric",
                              m_who.c_str ());
         }
       else if (param == "emptyvalue")
@@ -3711,11 +3700,11 @@
       else if (param == "multipledelimsasone")
         {
           m_multiple_delims_as_one = args(i
-                                        +1).xbool_value ("%s: MultipleDelimsAsOne must be logical or numeric", m_who.c_str ());
+                                        +1).ybool_value ("%s: MultipleDelimsAsOne must be logical or numeric", m_who.c_str ());
         }
       else if (param == "returnonerror")
         {
-          m_return_on_error = args(i+1).xbool_value ("%s: ReturnOnError must be logical or numeric",
+          m_return_on_error = args(i+1).ybool_value ("%s: ReturnOnError must be logical or numeric",
                               m_who.c_str ());
         }
       else if (param == "whitespace")
@@ -4460,7 +4449,7 @@
       else
         mval.resize (max_size, 1, 0.0);
 
-      data = mval.fortran_vec ();
+      data = mval.rwdata ();
     }
 
   if (! discard)
@@ -4700,7 +4689,7 @@
                       else                                              \
                         mval.resize (max_size, 1, 0.0);                 \
                                                                         \
-                      data = mval.fortran_vec ();                       \
+                      data = mval.rwdata ();                       \
                     }                                                   \
                                                                         \
                   data[data_index++] = static_cast<unsigned char>       \
@@ -4802,7 +4791,7 @@
       max_size = 32;
     }
 
-  double *data = mval.fortran_vec ();
+  double *data = mval.rwdata ();
 
   if (isp)
     {
@@ -4864,7 +4853,7 @@
                   else
                     mval.resize (max_size, 1, 0.0);
 
-                  data = mval.fortran_vec ();
+                  data = mval.rwdata ();
                 }
 
               std::string fmt = elt->text;
@@ -5485,8 +5474,7 @@
   return retval;
 }
 
-class
-printf_value_cache
+class printf_value_cache
 {
 public:
 
@@ -5831,7 +5819,7 @@
         }
 
       const char *tval;
-      if (lo_ieee_isinf (dval))
+      if (math::isinf (dval))
         {
           if (elt->flags.find ('+') != std::string::npos)
             tval = (dval < 0 ? "-Inf" : "+Inf");
@@ -6414,7 +6402,7 @@
 
   DST_T conv (dim_vector (nr, nc));
 
-  dst_elt_type *conv_data = conv.fortran_vec ();
+  dst_elt_type *conv_data = conv.rwdata ();
 
   octave_idx_type j = 0;
 
@@ -6690,7 +6678,7 @@
   std::ptrdiff_t input_buf_size
     = static_cast<std::ptrdiff_t> (input_buf_elts) * input_elt_size;
 
-  error_if (input_buf_size < 0);
+  panic_if (input_buf_size < 0);
 
   // Must also work and return correct type object for 0 elements to read.
   std::istream *isp = input_stream ();
--- a/libinterp/corefcn/oct-stream.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-stream.h	Fri Apr 12 15:10:26 2024 +0200
@@ -63,9 +63,7 @@
 
 // Provide an interface for Octave streams.
 
-class
-OCTINTERP_API
-base_stream
+class OCTINTERP_API base_stream
 {
   friend class stream;
 
@@ -297,9 +295,7 @@
   invalid_operation (const std::string& who, const char *rw);
 };
 
-class
-OCTINTERP_API
-stream
+class OCTINTERP_API stream
 {
 public:
 
@@ -499,9 +495,7 @@
                  mach_info::float_format ffmt);
 };
 
-class
-OCTINTERP_API
-stream_list
+class OCTINTERP_API stream_list
 {
 public:
 
--- a/libinterp/corefcn/oct-strstrm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/oct-strstrm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-base_strstream : public base_stream
+class base_strstream : public base_stream
 {
 public:
 
@@ -73,8 +72,7 @@
   virtual void clear () = 0;
 };
 
-class
-istrstream : public base_strstream
+class istrstream : public base_strstream
 {
 public:
 
@@ -133,8 +131,7 @@
   std::istringstream m_istream;
 };
 
-class
-ostrstream : public base_strstream
+class ostrstream : public base_strstream
 {
 public:
 
--- a/libinterp/corefcn/ordqz.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ordqz.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -329,9 +329,14 @@
               else
                 select(k) = false;
               break;
-            default:
-              // default: case just here to suppress compiler warning.
-              panic_impossible ();
+            case NONE:
+              error ("ordqz: invalid select mode NONE");
+              break;
+
+              // We should have handled all possible enum values above.
+              // Rely on compiler diagnostics to warn if we haven't.
+              // For example, GCC's -Wswitch option, enabled by -Wall,
+              // will provide a warning.
             }
         }
 
@@ -345,18 +350,18 @@
 
       F77_XFCN (ztgsen, ZTGSEN,
                 (ijob, wantq, wantz,
-                 select.fortran_vec (), nn,
-                 F77_DBLE_CMPLX_ARG (caa.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (cbb.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (alpha.fortran_vec ()),
-                 F77_DBLE_CMPLX_ARG (beta.fortran_vec ()),
-                 F77_DBLE_CMPLX_ARG (cqq.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (czz.fortran_vec ()), nn,
+                 select.rwdata (), nn,
+                 F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (alpha.rwdata ()),
+                 F77_DBLE_CMPLX_ARG (beta.rwdata ()),
+                 F77_DBLE_CMPLX_ARG (cqq.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (czz.rwdata ()), nn,
                  mm,
                  pl, pr,
                  nullptr,
-                 F77_DBLE_CMPLX_ARG (work3.fortran_vec ()), lrwork3,
-                 iwork.fortran_vec (), liwork,
+                 F77_DBLE_CMPLX_ARG (work3.rwdata ()), lrwork3,
+                 iwork.rwdata (), liwork,
                  info));
       if (info != 0)
         error_with_id ("Octave:ordqz:ztgsen_failed",
@@ -374,7 +379,7 @@
       k = 0;
       while (k < nn)
         {
-#ifdef DEBUG
+#if defined (DEBUG)
           octave_stdout << "ordqz: k = " << k  << " nn = " << nn << " \n";
 #endif
           if ((k < nn-1 && aa(k+1, k) == 0.0) || k == nn-1)
@@ -395,8 +400,8 @@
               F77_INT ihi = 2;
               F77_INT lwork = 4;
               F77_INT info = 0;
-              double *aa_vec = aa.fortran_vec ();
-              double *bb_vec = bb.fortran_vec ();
+              double *aa_vec = aa.rwdata ();
+              double *bb_vec = bb.rwdata ();
 
               F77_XFCN (dhgeqz, DHGEQZ,
                         (F77_CONST_CHAR_ARG2 (&qz_job, 1),
@@ -450,9 +455,14 @@
               else
                 select(k) = false;
               break;
-            default:
-              // default: case just here to suppress compiler warning.
-              panic_impossible();
+            case NONE:
+              error ("ordqz: invalid select mode NONE");
+              break;
+
+              // We should have handled all possible enum values above.
+              // Rely on compiler diagnostics to warn if we haven't.
+              // For example, GCC's -Wswitch option, enabled by -Wall,
+              // will provide a warning.
             }
         }
 
@@ -466,19 +476,19 @@
 
       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 (),
-                 beta.fortran_vec (),
-                 qq.fortran_vec (), nn,
-                 zz.fortran_vec (), nn,
+                 select.rwdata (), nn,
+                 aa.rwdata (), nn,
+                 bb.rwdata (), nn,
+                 alphar.rwdata (),
+                 alphai.rwdata (),
+                 beta.rwdata (),
+                 qq.rwdata (), nn,
+                 zz.rwdata (), nn,
                  mm,
                  pl, pr,
                  nullptr,
-                 rwork3.fortran_vec (), lrwork3,
-                 iwork.fortran_vec (), liwork,
+                 rwork3.rwdata (), lrwork3,
+                 iwork.rwdata (), liwork,
                  info));
       if (info != 0)
         error("ordqz: failed to reorder eigenvalues");
--- a/libinterp/corefcn/ordschur.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/ordschur.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -130,10 +130,10 @@
 
           F77_XFCN (ztrsen, ztrsen,
                     (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
-                     sel.data (), n, F77_DBLE_CMPLX_ARG (S.fortran_vec ()), n,
-                     F77_DBLE_CMPLX_ARG (U.fortran_vec ()), n,
-                     F77_DBLE_CMPLX_ARG (w.fortran_vec ()), m, cond1, cond2,
-                     F77_DBLE_CMPLX_ARG (work.fortran_vec ()), n,
+                     sel.data (), n, F77_DBLE_CMPLX_ARG (S.rwdata ()), n,
+                     F77_DBLE_CMPLX_ARG (U.rwdata ()), n,
+                     F77_DBLE_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
+                     F77_DBLE_CMPLX_ARG (work.rwdata ()), n,
                      info));
 
           PREPARE_OUTPUT()
@@ -146,9 +146,9 @@
 
           F77_XFCN (dtrsen, dtrsen,
                     (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
-                     sel.data (), n, S.fortran_vec (), n, U.fortran_vec (), n,
-                     w.fortran_vec (), wi.fortran_vec (), m, cond1, cond2,
-                     work.fortran_vec (), n, iwork.fortran_vec (), n, info));
+                     sel.data (), n, S.rwdata (), n, U.rwdata (), n,
+                     w.rwdata (), wi.rwdata (), m, cond1, cond2,
+                     work.rwdata (), n, iwork.rwdata (), n, info));
 
           PREPARE_OUTPUT ()
         }
@@ -161,10 +161,10 @@
 
           F77_XFCN (ctrsen, ctrsen,
                     (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
-                     sel.data (), n, F77_CMPLX_ARG (S.fortran_vec ()), n,
-                     F77_CMPLX_ARG (U.fortran_vec ()), n,
-                     F77_CMPLX_ARG (w.fortran_vec ()), m, cond1, cond2,
-                     F77_CMPLX_ARG (work.fortran_vec ()), n,
+                     sel.data (), n, F77_CMPLX_ARG (S.rwdata ()), n,
+                     F77_CMPLX_ARG (U.rwdata ()), n,
+                     F77_CMPLX_ARG (w.rwdata ()), m, cond1, cond2,
+                     F77_CMPLX_ARG (work.rwdata ()), n,
                      info));
 
           PREPARE_OUTPUT ()
@@ -177,9 +177,9 @@
 
           F77_XFCN (strsen, strsen,
                     (F77_CONST_CHAR_ARG ("N"), F77_CONST_CHAR_ARG ("V"),
-                     sel.data (), n, S.fortran_vec (), n, U.fortran_vec (), n,
-                     w.fortran_vec (), wi.fortran_vec (), m, cond1, cond2,
-                     work.fortran_vec (), n, iwork.fortran_vec (), n, info));
+                     sel.data (), n, S.rwdata (), n, U.rwdata (), n,
+                     w.rwdata (), wi.rwdata (), m, cond1, cond2,
+                     work.rwdata (), n, iwork.rwdata (), n, info));
 
           PREPARE_OUTPUT ()
         }
--- a/libinterp/corefcn/pager.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/pager.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 class interpreter;
 class oprocstream;
 
-class
-OCTINTERP_API
-pager_buf : public std::stringbuf
+class OCTINTERP_API pager_buf : public std::stringbuf
 {
 public:
 
@@ -66,9 +64,7 @@
   std::size_t m_diary_skip;
 };
 
-class
-OCTINTERP_API
-pager_stream : public std::ostream
+class OCTINTERP_API pager_stream : public std::ostream
 {
 public:
 
@@ -91,9 +87,7 @@
   pager_buf *m_pb;
 };
 
-class
-OCTINTERP_API
-diary_buf : public std::stringbuf
+class OCTINTERP_API diary_buf : public std::stringbuf
 {
 public:
 
@@ -105,9 +99,7 @@
   int sync ();
 };
 
-class
-OCTINTERP_API
-diary_stream : public std::ostream
+class OCTINTERP_API diary_stream : public std::ostream
 {
 public:
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/panic.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 1993-2024 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 "error.h"
+#include "interpreter-private.h"
+#include "panic.h"
+
+OCTAVE_NORETURN
+void
+vpanic (const char *fmt, va_list args)
+{
+  octave::error_system& es = octave::__get_error_system__ ();
+
+  es.vpanic (fmt, args);
+}
+
+OCTAVE_NORETURN
+void
+panic (const char *fmt, ...)
+{
+  va_list args;
+  va_start (args, fmt);
+  vpanic (fmt, args);
+  va_end (args);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/panic.h	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,63 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2024 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_panic_h)
+#define octave_panic_h 1
+
+#include "octave-config.h"
+
+#include <cstdarg>
+
+OCTAVE_NORETURN
+extern OCTINTERP_API void vpanic (const char *fmt, va_list args);
+
+OCTAVE_FORMAT_PRINTF (1, 2)
+OCTAVE_NORETURN
+extern OCTINTERP_API void panic (const char *fmt, ...);
+
+// To allow the __FILE__ and __LINE__ macros to work as expected, the
+// panic_impossible, panic_if, and panic_unless symbols must be defined
+// as macros.
+
+#if defined (NDEBUG)
+
+#  define panic_impossible() do { } while (0)
+
+#  define panic_if(cond) do { } while (0)
+
+#  define panic_unless(cond) do { } while (0)
+
+#else
+
+#  define panic_impossible()                                                            \
+  ::panic ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
+
+#  define panic_if(cond) do { if (cond) panic_impossible (); } while (0)
+
+#  define panic_unless(cond) panic_if (! (cond))
+
+#endif
+
+#endif
--- a/libinterp/corefcn/perms.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/perms.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,11 +23,12 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#if defined(HAVE_CONFIG_H)
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
 #include <algorithm>
+#include <numeric>
 
 #include "defun.h"
 #include "error.h"
@@ -48,124 +49,88 @@
 //
 // 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
-  OCTAVE_LOCAL_BUFFER (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);
-    }
+// FIXME: To allow comparison between all supported template types, we need
+// to use either "if constexpr" (supported in C++17) or template specialisation
+// (supported in C++11).  Currently (2024), Octave stipulates the usage of
+// C++11, so the (slightly more complex) template specialization is used.
+// Once Octave moves to C++17 or beyond, the following code snippet is
+// preferrable and the comparison templates can be removed:
+// bool isequal;
+// if constexpr (std::is_same<T, octave_value>::value)
+//   isequal = Ar[i].is_equal (Ar[j]);
+// else
+//   isequal = (Ar[i] == Ar[j]);
 
-  // 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 <typename T>
+bool is_equal_T (T a, T b)
+{
+  return a == b;
 }
 
-// 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 <>
+bool is_equal_T<octave_value> (octave_value a, octave_value b)
+{
+  return a.is_equal (b);
+}
 
 template <typename T>
 static inline Array<T>
-GetPermsNoSort (const Array<T>& ar_in, bool uniq_v = false)
+GetPerms (const Array<T>& ar_in, bool uniq_v = false)
 {
   octave_idx_type m = ar_in.numel ();
-  double nr = Factorial (m);
+  double nr;  // number of rows of resulting array
 
   // Setup index vector filled from 0..m-1
-  OCTAVE_LOCAL_BUFFER (int, myvidx, m);
-  for (int i = 0; i < m; i++)
-    myvidx[i] = i;
+  OCTAVE_LOCAL_BUFFER (octave_idx_type, myvidx, m);
+  std::iota (&myvidx[0], &myvidx[m], 0);
 
   const T *Ar = ar_in.data ();
 
   if (uniq_v)
     {
-      // Mutual Comparison using is_equal to detect duplicated values
-      int N_el = 1;
+      // Mutual Comparison is used to detect duplicated values.
+      // Using sort would be possible for numerical values and be of
+      // O(n*log (n)) complexity instead of O(n*(n -1) / 2).  But sort
+      // is not supported for the octave_value container (structs/cells).
+      // Moreover, sort requires overhead for creating, filling, and sorting
+      // the intermediate array which would need to be post-processed.
+      // In practice, and because n must be very small, mutual comparison is
+      // typically faster and consumes less memory.
+
+      octave_idx_type N_el = 1;
+      double denom = 1.0;
       // 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]))
+              bool isequal = is_equal_T<T> (Ar[i], Ar[j]);
+              if (myvidx[j] > myvidx[i] && isequal)
                 {
                   myvidx[j] = myvidx[i];  // not yet processed...
                   N_el++;
                 }
               else
                 {
-                  nr /= Factorial (N_el);
+                  denom *= Factorial (N_el);
                   N_el = 1;
                 }
             }
         }
-      nr /= Factorial (N_el);
+      denom *= Factorial (N_el);
+      nr = Factorial (m) / denom;
     }
+  else
+    nr = Factorial (m);
 
   // Sort vector indices for inverse lexicographic order later.
-  std::sort (myvidx, myvidx + m, std::greater<int> ());
+  std::sort (myvidx, myvidx + m, std::greater<octave_idx_type> ());
 
   // 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 ();
+  T *Res = res.rwdata ();
 
   // Do the actual job
   octave_idx_type i = 0;
@@ -259,8 +224,8 @@
          || 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.");
+      error ("perms: V must be a matrix, range, cell array, "
+             "struct, or a scalar.");
     }
 
   std::string clname = args (0).class_name ();
@@ -291,7 +256,7 @@
   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);
+    retval = GetPerms<octave_value> (args (0).cell_value (), uniq_v);
   else if (clname == "struct")
     {
       const octave_map map_in (args (0).map_value ());
@@ -312,7 +277,7 @@
             {
               for (octave_idx_type i = 0; i < fn.numel (); i++)
                 {
-                  out.assign (fn (i), GetPermsNoSort<octave_value>
+                  out.assign (fn (i), GetPerms<octave_value>
                                       (map_in.contents (fn (i)), uniq_v));
                 }
             }
--- a/libinterp/corefcn/pr-flt-fmt.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/pr-flt-fmt.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,9 +44,7 @@
 
 extern OCTINTERP_API void set_output_prec (int prec);
 
-class
-OCTINTERP_API
-float_format
+class OCTINTERP_API float_format
 {
 public:
 
@@ -205,9 +203,7 @@
   int m_sp;
 };
 
-class
-OCTINTERP_API
-float_display_format
+class OCTINTERP_API float_display_format
 {
 public:
 
--- a/libinterp/corefcn/pr-output.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/pr-output.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -300,7 +300,7 @@
 pr_max_internal (const MArray<T>& m)
 {
   // We expect a 2-d array.
-  error_unless (m.ndims () == 2);
+  panic_unless (m.ndims () == 2);
 
   octave_idx_type nr = m.rows ();
   octave_idx_type nc = m.columns ();
@@ -680,7 +680,8 @@
 static inline float_display_format
 make_matrix_format (const MT& m)
 {
-  error_unless (m.ndims () == 2);
+  // We expect a 2-d array.
+  panic_unless (m.ndims () == 2);
 
   if (free_format)
     return float_display_format ();
@@ -1546,7 +1547,7 @@
   if (! bank_format)
     {
       T i = cval.imag ();
-      if (! (hex_format || bit_format) && lo_ieee_signbit (i))
+      if (! (hex_format || bit_format) && std::signbit (i))
         {
           os << " - ";
           i = -i;
@@ -1569,7 +1570,7 @@
 print_empty_matrix (std::ostream& os, octave_idx_type nr, octave_idx_type nc,
                     bool pr_as_read_syntax)
 {
-  error_unless (nr == 0 || nc == 0);
+  panic_unless (nr == 0 || nc == 0);
 
   if (pr_as_read_syntax)
     {
@@ -1591,7 +1592,7 @@
 print_empty_nd_array (std::ostream& os, const dim_vector& dims,
                       bool pr_as_read_syntax)
 {
-  error_unless (dims.any_zero ());
+  panic_unless (dims.any_zero ());
 
   if (pr_as_read_syntax)
     os << "zeros (" << dims.str (',') << ')';
@@ -2124,7 +2125,7 @@
 
       int ndims = nda.ndims ();
 
-      dim_vector dims = nda.dims ();
+      const dim_vector& dims = nda.dims ();
 
       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
 
@@ -2712,7 +2713,7 @@
     {
       int ndims = nda.ndims ();
 
-      dim_vector dims = nda.dims ();
+      const dim_vector& dims = nda.dims ();
 
       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
 
@@ -2784,8 +2785,7 @@
 }
 
 template <typename T>
-class
-octave_print_conv
+class octave_print_conv
 {
 public:
   typedef T print_conv_type;
@@ -2954,7 +2954,7 @@
 
       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
 
-      dim_vector dims = nda.dims ();
+      const dim_vector& dims = nda.dims ();
 
       octave_idx_type m = 1;
 
@@ -3023,7 +3023,7 @@
     {
       int ndims = nda.ndims ();
 
-      dim_vector dims = nda.dims ();
+      const dim_vector& dims = nda.dims ();
 
       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
 
@@ -3606,7 +3606,7 @@
   frame.protect_var (Vcompact_format);
   frame.protect_var (uppercase_format);
   int prec = output_precision ();
-  frame.add ([=] () { set_output_prec (prec); });
+  frame.add ([prec] () { set_output_prec (prec); });
 
   format = format_string;   // Initialize with existing value
   while (argc-- > 0)
--- a/libinterp/corefcn/pr-output.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/pr-output.h	Fri Apr 12 15:10:26 2024 +0200
@@ -508,8 +508,7 @@
                        bool pr_as_read_syntax = false);
 
 template <typename T>
-class
-pr_engineering_float
+class pr_engineering_float
 {
 public:
 
@@ -529,8 +528,7 @@
 };
 
 template <typename T>
-class
-pr_formatted_float
+class pr_formatted_float
 {
 public:
 
@@ -546,8 +544,7 @@
 };
 
 template <typename T>
-class
-pr_rational_float
+class pr_rational_float
 {
 public:
 
--- a/libinterp/corefcn/procstream.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/procstream.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-procstreambase : virtual public std::ios
+class OCTINTERP_API procstreambase : virtual public std::ios
 {
 public:
 
@@ -80,9 +78,7 @@
   }
 };
 
-class
-OCTINTERP_API
-iprocstream : public std::istream, public procstreambase
+class OCTINTERP_API iprocstream : public std::istream, public procstreambase
 {
 public:
 
@@ -111,9 +107,7 @@
   }
 };
 
-class
-OCTINTERP_API
-oprocstream : public std::ostream, public procstreambase
+class OCTINTERP_API oprocstream : public std::ostream, public procstreambase
 {
 public:
 
@@ -140,9 +134,7 @@
   }
 };
 
-class
-OCTINTERP_API
-procstream : public std::iostream, public procstreambase
+class OCTINTERP_API procstream : public std::iostream, public procstreambase
 {
 public:
 
--- a/libinterp/corefcn/psi.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/psi.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -78,7 +78,7 @@
     print_usage ();
 
   const octave_value oct_z = (nargin == 1) ? args(0) : args(1);
-  const octave_idx_type k = (nargin == 1) ? 0 : args(0).xidx_type_value ("psi: K must be an integer");
+  const octave_idx_type k = (nargin == 1) ? 0 : args(0).yidx_type_value ("psi: K must be an integer");
   if (k < 0)
     error ("psi: K must be non-negative");
 
@@ -93,7 +93,7 @@
           A ## NDArray psi_z (z.dims ());                       \
                                                                 \
           const E *zv = z.data ();                              \
-          E *psi_zv = psi_z.fortran_vec ();                     \
+          E *psi_zv = psi_z.rwdata ();                     \
           const octave_idx_type n = z.numel ();                 \
           for (octave_idx_type i = 0; i < n; i++)               \
             *psi_zv++ = math::psi (*zv++);              \
@@ -130,7 +130,7 @@
           A ## NDArray psi_z (z.dims ());                               \
                                                                         \
           const E *zv = z.data ();                                      \
-          E *psi_zv = psi_z.fortran_vec ();                             \
+          E *psi_zv = psi_z.rwdata ();                             \
           const octave_idx_type n = z.numel ();                         \
           for (octave_idx_type i = 0; i < n; i++)                       \
             {                                                           \
--- a/libinterp/corefcn/qr.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/qr.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -1925,9 +1925,9 @@
 @w{@var{A} = @var{Q}*@var{R}}, @var{Q}@tie{}unitary and
 @var{R}@tie{}upper trapezoidal, return the QR@tie{}factorization
 of @w{@var{A}(:,p)}, where @w{p} is the permutation @*
-@code{p = [1:i-1, shift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*
+@code{p = [1:i-1, circshift(i:j, 1), j+1:n]} if @w{@var{i} < @var{j}} @*
  or @*
-@code{p = [1:j-1, shift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*
+@code{p = [1:j-1, circshift(j:i,-1), i+1:n]} if @w{@var{j} < @var{i}}.  @*
 
 @seealso{qr, qrupdate, qrinsert, qrdelete}
 @end deftypefn */)
@@ -2011,7 +2011,7 @@
 /*
 %!test
 %! AA = A.';
-%! i = 2;  j = 4;  p = [1:i-1, shift(i:j,-1), j+1:5];
+%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2019,7 +2019,7 @@
 %! assert (norm (vec (triu (R) - R), Inf), 0);
 %! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);
 %!
-%! j = 2;  i = 4;  p = [1:j-1, shift(j:i,+1), i+1:5];
+%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2029,7 +2029,7 @@
 %!
 %!test
 %! AA = Ac.';
-%! i = 2;  j = 4;  p = [1:i-1, shift(i:j,-1), j+1:5];
+%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2037,7 +2037,7 @@
 %! assert (norm (vec (triu (R) - R), Inf), 0);
 %! assert (norm (vec (Q*R - AA(:,p)), Inf), 0, norm (AA)*1e1*eps);
 %!
-%! j = 2;  i = 4;  p = [1:j-1, shift(j:i,+1), i+1:5];
+%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2047,7 +2047,7 @@
 
 %!test
 %! AA = single (A).';
-%! i = 2;  j = 4;  p = [1:i-1, shift(i:j,-1), j+1:5];
+%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2057,7 +2057,7 @@
 %! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...
 %!         norm (AA)*1e1 * eps ("single"));
 %!
-%! j = 2;  i = 4;  p = [1:j-1, shift(j:i,+1), i+1:5];
+%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2069,7 +2069,7 @@
 %!
 %!test
 %! AA = single (Ac).';
-%! i = 2;  j = 4;  p = [1:i-1, shift(i:j,-1), j+1:5];
+%! i = 2;  j = 4;  p = [1:i-1, circshift(i:j,-1), j+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
@@ -2079,7 +2079,7 @@
 %! assert (norm (vec (Q*R - AA(:,p)), Inf), single (0), ...
 %!         norm (AA)*1e1 * eps ("single"));
 %!
-%! j = 2;  i = 4;  p = [1:j-1, shift(j:i,+1), i+1:5];
+%! j = 2;  i = 4;  p = [1:j-1, circshift(j:i,+1), i+1:5];
 %!
 %! [Q,R] = qr (AA);
 %! [Q,R] = qrshift (Q, R, i, j);
--- a/libinterp/corefcn/quadcc.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/quadcc.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -61,7 +61,7 @@
 };
 
 // Define relative tolerance used when deciding to drop an interval.
-static const double DROP_RELTOL = std::numeric_limits<double>::epsilon () * 10;
+static constexpr double DROP_RELTOL = std::numeric_limits<double>::epsilon () * 10;
 
 // Some constants and matrices that we'll need.
 
@@ -1672,7 +1672,7 @@
     {
       // Intervals around singularities.
       NDArray arr = args(4).array_value ();
-      sing = arr.fortran_vec ();
+      sing = arr.rwdata ();
       iivals[0] = a;
       std::copy_n (sing, nivals-1, iivals+1);
       iivals[nivals] = b;
--- a/libinterp/corefcn/qz.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/qz.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -219,8 +219,8 @@
   // Initialize Q, Z to identity matrix if either is needed
   if (comp_q == 'V' || comp_z == 'V')
     {
-      double *QQptr = QQ.fortran_vec ();
-      double *ZZptr = ZZ.fortran_vec ();
+      double *QQptr = QQ.rwdata ();
+      double *ZZptr = ZZ.rwdata ();
       std::fill_n (QQptr, QQ.numel (), 0.0);
       std::fill_n (ZZptr, ZZ.numel (), 0.0);
       for (F77_INT i = 0; i < nn; i++)
@@ -254,10 +254,10 @@
 
       F77_XFCN (zggbal, ZGGBAL,
                 (F77_CONST_CHAR_ARG2 (&bal_job, 1),
-                 nn, F77_DBLE_CMPLX_ARG (caa.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (cbb.fortran_vec ()),
-                 nn, ilo, ihi, lscale.fortran_vec (),
-                 rscale.fortran_vec (), work.fortran_vec (), info
+                 nn, F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()),
+                 nn, ilo, ihi, lscale.rwdata (),
+                 rscale.rwdata (), work.rwdata (), info
                  F77_CHAR_ARG_LEN (1)));
     }
   else
@@ -269,9 +269,9 @@
 
       F77_XFCN (dggbal, DGGBAL,
                 (F77_CONST_CHAR_ARG2 (&bal_job, 1),
-                 nn, aa.fortran_vec (), nn, bb.fortran_vec (),
-                 nn, ilo, ihi, lscale.fortran_vec (),
-                 rscale.fortran_vec (), work.fortran_vec (), info
+                 nn, aa.rwdata (), nn, bb.rwdata (),
+                 nn, ilo, ihi, lscale.rwdata (),
+                 rscale.rwdata (), work.rwdata (), info
                  F77_CHAR_ARG_LEN (1)));
     }
 
@@ -294,10 +294,10 @@
       F77_XFCN (zgghrd, ZGGHRD,
                 (F77_CONST_CHAR_ARG2 (&comp_q, 1),
                  F77_CONST_CHAR_ARG2 (&comp_z, 1),
-                 nn, ilo, ihi, F77_DBLE_CMPLX_ARG (caa.fortran_vec ()),
-                 nn, F77_DBLE_CMPLX_ARG (cbb.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (CQ.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (CZ.fortran_vec ()), nn, info
+                 nn, ilo, ihi, F77_DBLE_CMPLX_ARG (caa.rwdata ()),
+                 nn, F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn, info
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)));
 
@@ -308,14 +308,14 @@
                  F77_CONST_CHAR_ARG2 (&comp_q, 1),
                  F77_CONST_CHAR_ARG2 (&comp_z, 1),
                  nn, ilo, ihi,
-                 F77_DBLE_CMPLX_ARG (caa.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (cbb.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (xalpha.fortran_vec ()),
-                 F77_DBLE_CMPLX_ARG (xbeta.fortran_vec ()),
-                 F77_DBLE_CMPLX_ARG (CQ.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (CZ.fortran_vec ()), nn,
-                 F77_DBLE_CMPLX_ARG (cwork.fortran_vec ()), nn,
-                 rwork.fortran_vec (), info
+                 F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (cbb.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (xalpha.rwdata ()),
+                 F77_DBLE_CMPLX_ARG (xbeta.rwdata ()),
+                 F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn,
+                 F77_DBLE_CMPLX_ARG (cwork.rwdata ()), nn,
+                 rwork.rwdata (), info
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)));
@@ -327,7 +327,7 @@
                     (F77_CONST_CHAR_ARG2 (&bal_job, 1),
                      F77_CONST_CHAR_ARG2 ("L", 1),
                      nn, ilo, ihi, lscale.data (), rscale.data (),
-                     nn, F77_DBLE_CMPLX_ARG (CQ.fortran_vec ()), nn, info
+                     nn, F77_DBLE_CMPLX_ARG (CQ.rwdata ()), nn, info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
         }
@@ -339,7 +339,7 @@
                     (F77_CONST_CHAR_ARG2 (&bal_job, 1),
                      F77_CONST_CHAR_ARG2 ("R", 1),
                      nn, ilo, ihi, lscale.data (), rscale.data (),
-                     nn, F77_DBLE_CMPLX_ARG (CZ.fortran_vec ()), nn, info
+                     nn, F77_DBLE_CMPLX_ARG (CZ.rwdata ()), nn, info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
         }
@@ -391,9 +391,9 @@
       F77_XFCN (dgghrd, DGGHRD,
                 (F77_CONST_CHAR_ARG2 (&comp_q, 1),
                  F77_CONST_CHAR_ARG2 (&comp_z, 1),
-                 nn, ilo, ihi, aa.fortran_vec (),
-                 nn, bb.fortran_vec (), nn, QQ.fortran_vec (), nn,
-                 ZZ.fortran_vec (), nn, info
+                 nn, ilo, ihi, aa.rwdata (),
+                 nn, bb.rwdata (), nn, QQ.rwdata (), nn,
+                 ZZ.rwdata (), nn, info
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)));
 
@@ -405,10 +405,10 @@
                 (F77_CONST_CHAR_ARG2 (&qz_job, 1),
                  F77_CONST_CHAR_ARG2 (&comp_q, 1),
                  F77_CONST_CHAR_ARG2 (&comp_z, 1),
-                 nn, ilo, ihi, aa.fortran_vec (), nn, bb.fortran_vec (),
-                 nn, alphar.fortran_vec (), alphai.fortran_vec (),
-                 betar.fortran_vec (), QQ.fortran_vec (), nn,
-                 ZZ.fortran_vec (), nn, work.fortran_vec (), nn, info
+                 nn, ilo, ihi, aa.rwdata (), nn, bb.rwdata (),
+                 nn, alphar.rwdata (), alphai.rwdata (),
+                 betar.rwdata (), QQ.rwdata (), nn,
+                 ZZ.rwdata (), nn, work.rwdata (), nn, info
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)
                  F77_CHAR_ARG_LEN (1)));
@@ -419,7 +419,7 @@
                     (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
+                     nn, QQ.rwdata (), nn, info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
 
@@ -436,7 +436,7 @@
                     (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
+                     nn, ZZ.rwdata (), nn, info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
 
@@ -469,12 +469,12 @@
           F77_XFCN (ztgevc, ZTGEVC,
                     (F77_CONST_CHAR_ARG2 (&side, 1),
                      F77_CONST_CHAR_ARG2 (&howmany, 1),
-                     select, nn, F77_DBLE_CMPLX_ARG (caa.fortran_vec ()), nn,
-                     F77_DBLE_CMPLX_ARG (cbb.fortran_vec ()),
-                     nn, F77_DBLE_CMPLX_ARG (CVL.fortran_vec ()), nn,
-                     F77_DBLE_CMPLX_ARG (CVR.fortran_vec ()), nn, nn,
-                     m, F77_DBLE_CMPLX_ARG (cwork2.fortran_vec ()),
-                     rwork2.fortran_vec (), info
+                     select, nn, F77_DBLE_CMPLX_ARG (caa.rwdata ()), nn,
+                     F77_DBLE_CMPLX_ARG (cbb.rwdata ()),
+                     nn, F77_DBLE_CMPLX_ARG (CVL.rwdata ()), nn,
+                     F77_DBLE_CMPLX_ARG (CVR.rwdata ()), nn, nn,
+                     m, F77_DBLE_CMPLX_ARG (cwork2.rwdata ()),
+                     rwork2.rwdata (), info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
         }
@@ -491,9 +491,9 @@
           F77_XFCN (dtgevc, DTGEVC,
                     (F77_CONST_CHAR_ARG2 (&side, 1),
                      F77_CONST_CHAR_ARG2 (&howmany, 1),
-                     select, nn, aa.fortran_vec (), nn, bb.fortran_vec (),
-                     nn, VL.fortran_vec (), nn, VR.fortran_vec (), nn, nn,
-                     m, work.fortran_vec (), info
+                     select, nn, aa.rwdata (), nn, bb.rwdata (),
+                     nn, VL.rwdata (), nn, VR.rwdata (), nn, nn,
+                     m, work.rwdata (), info
                      F77_CHAR_ARG_LEN (1)
                      F77_CHAR_ARG_LEN (1)));
         }
--- a/libinterp/corefcn/rand.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/rand.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -318,7 +318,7 @@
 
               octave_idx_type len = a.numel ();
               FloatNDArray m (dims);
-              float *v = m.fortran_vec ();
+              float *v = m.rwdata ();
 
               for (octave_idx_type i = 0; i < len; i++)
                 v[i] = rand::float_scalar (a(i));
@@ -342,7 +342,7 @@
 
               octave_idx_type len = a.numel ();
               NDArray m (dims);
-              double *v = m.fortran_vec ();
+              double *v = m.rwdata ();
 
               for (octave_idx_type i = 0; i < len; i++)
                 v[i] = rand::scalar (a(i));
@@ -1144,7 +1144,7 @@
 
   // Generate random numbers.
   NDArray r = rand::nd_array (dim_vector (1, m));
-  double *rvec = r.fortran_vec ();
+  double *rvec = r.rwdata ();
 
   octave_idx_type idx_len = (short_shuffle ? m : n);
   Array<octave_idx_type> idx;
@@ -1161,7 +1161,7 @@
       idx = Array<octave_idx_type> (dim_vector (1, idx_len));
     }
 
-  octave_idx_type *ivec = idx.fortran_vec ();
+  octave_idx_type *ivec = idx.rwdata ();
 
   for (octave_idx_type i = 0; i < idx_len; i++)
     ivec[i] = i;
--- a/libinterp/corefcn/regexp.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/regexp.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -30,7 +30,6 @@
 #include <list>
 #include <sstream>
 
-#include "base-list.h"
 #include "oct-locbuf.h"
 #include "quit.h"
 #include "lo-regexp.h"
--- a/libinterp/corefcn/schur.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/schur.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,7 +46,7 @@
   octave_value retval = a;
 
   octave_idx_type n = a.rows ();
-  error_unless (a.columns () == n);
+  panic_unless (a.columns () == n);
 
   const typename Matrix::element_type zero = typename Matrix::element_type ();
 
--- a/libinterp/corefcn/sighandlers.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sighandlers.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -203,8 +203,7 @@
               || (have_sigcld && sig == sigcld))
             {
               // FIXME: should we block or ignore?
-              volatile interrupt_handler saved_interrupt_handler
-                = ignore_interrupts ();
+              interrupt_handler saved_interrupt_handler = ignore_interrupts ();
 
               void *context = octave_block_child ();
 
@@ -346,8 +345,7 @@
 }
 
 interrupt_handler
-set_interrupt_handler (const volatile interrupt_handler& h,
-                       bool restart_syscalls)
+set_interrupt_handler (const interrupt_handler& h, bool restart_syscalls)
 {
   interrupt_handler retval;
 
--- a/libinterp/corefcn/sighandlers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sighandlers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -77,7 +77,7 @@
 extern OCTINTERP_API interrupt_handler ignore_interrupts ();
 
 extern OCTINTERP_API interrupt_handler
-set_interrupt_handler (const volatile interrupt_handler& h,
+set_interrupt_handler (const interrupt_handler& h,
                        bool restart_syscalls = true);
 
 // TRUE means we should try to enter the debugger on SIGINT.
--- a/libinterp/corefcn/sparse-xdiv.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sparse-xdiv.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include "Array-util.h"
 #include "lo-array-errwarn.h"
 #include "oct-cmplx.h"
--- a/libinterp/corefcn/sparse-xpow.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sparse-xpow.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include <limits>
 
 #include "Array-util.h"
--- a/libinterp/corefcn/sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -199,8 +199,8 @@
     }
   else if (nargin == 2)
     {
-      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");
+      octave_idx_type m = args(0).yidx_type_value ("sparse: M must be a non-negative integer");
+      octave_idx_type n = args(1).yidx_type_value ("sparse: N must be a non-negative integer");
 
       if (m < 0 || n < 0)
         error ("sparse: dimensions M and N must be non-negative");
@@ -233,8 +233,8 @@
 
       if (nargin == 5)
         {
-          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");
+          m = args(3).yidx_type_value ("sparse: M must be a non-negative integer");
+          n = args(4).yidx_type_value ("sparse: N must be a non-negative integer");
 
           if (m < 0 || n < 0)
             error ("sparse: dimensions M and N must be non-negative");
--- a/libinterp/corefcn/sqrtm.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sqrtm.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -40,51 +40,94 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-template <typename Matrix>
+template <typename T>
 static void
-sqrtm_utri_inplace (Matrix& T)
+sqrtm_utri_inplace (T& m)
 {
-  typedef typename Matrix::element_type element_type;
+  typedef typename T::element_type element_type;
+  typedef typename T::real_matrix_type real_matrix_type;
+  typedef typename T::real_elt_type real_elt_type;
 
   const element_type zero = element_type ();
 
   bool singular = false;
+  bool diagonal = true;
 
-  // The following code is equivalent to this triple loop:
-  //
-  //   n = rows (T);
-  //   for j = 1:n
-  //     T(j,j) = sqrt (T(j,j));
-  //     for i = j-1:-1:1
-  //       if T(i,j) != 0
-  //         T(i,j) /= (T(i,i) + T(j,j));
-  //       endif
-  //       k = 1:i-1;
-  //       T(k,j) -= T(k,i) * T(i,j);
-  //     endfor
-  //   endfor
-  //
-  // this is an in-place, cache-aligned variant of the code
-  // given in Higham's paper.
+  // The Schur matrix of Hermitian matrices is diagonal.
+  // check for off-diagonal elements above tolerance
+  const octave_idx_type n = m.rows ();
+  real_matrix_type abs_m = m.abs ();
+
+  real_elt_type max_abs_diag = 0;
+  for (octave_idx_type i = 0; i < n; i++)
+    max_abs_diag = std::max (max_abs_diag, abs_m(i,i));
+
+  const real_elt_type tol = n * max_abs_diag
+                            * std::numeric_limits<real_elt_type>::epsilon ();
+
+   for (octave_idx_type j = 0; j < n; j++)
+     {
+       for (octave_idx_type i = j-1; i >= 0; i--)
+         {
+          if (abs_m(i,j) > tol)
+            {
+              diagonal = false;
+              break;
+            }
+        }
+      if (! diagonal)
+        break;
+    }
 
-  const octave_idx_type n = T.rows ();
-  element_type *Tp = T.fortran_vec ();
-  for (octave_idx_type j = 0; j < n; j++)
+  element_type *mp = m.rwdata ();
+  if (diagonal)
+    {
+      // shortcut for diagonal Schur matrices
+      for (octave_idx_type i = 0; i < n; i++)
+        {
+          octave_idx_type idx_diag = i*(n+1);
+          if (mp[idx_diag] != zero)
+            mp[idx_diag] = sqrt (mp[idx_diag]);
+          else
+            singular = true;
+        }
+    }
+  else
     {
-      element_type *colj = Tp + n*j;
-      if (colj[j] != zero)
-        colj[j] = sqrt (colj[j]);
-      else
-        singular = true;
+      // The following code is equivalent to this triple loop:
+      //
+      //   n = rows (m);
+      //   for j = 1:n
+      //     m(j,j) = sqrt (m(j,j));
+      //     for i = j-1:-1:1
+      //       if m(i,j) != 0
+      //         m(i,j) /= (m(i,i) + m(j,j));
+      //       endif
+      //       k = 1:i-1;
+      //       m(k,j) -= m(k,i) * m(i,j);
+      //     endfor
+      //   endfor
+      //
+      // this is an in-place, cache-aligned variant of the code
+      // given in Higham's paper.
 
-      for (octave_idx_type i = j-1; i >= 0; i--)
+      for (octave_idx_type j = 0; j < n; j++)
         {
-          const element_type *coli = Tp + n*i;
-          if (colj[i] != zero)
-            colj[i] /= (coli[i] + colj[j]);
-          const element_type colji = colj[i];
-          for (octave_idx_type k = 0; k < i; k++)
-            colj[k] -= coli[k] * colji;
+          element_type *colj = mp + n*j;
+          if (colj[j] != zero)
+            colj[j] = sqrt (colj[j]);
+          else
+            singular = true;
+
+          for (octave_idx_type i = j-1; i >= 0; i--)
+            {
+              const element_type *coli = mp + n*i;
+              if (colj[i] != zero)
+                colj[i] /= (coli[i] + colj[j]);
+              const element_type colji = colj[i];
+              for (octave_idx_type k = 0; k < i; k++)
+                colj[k] -= coli[k] * colji;
+            }
         }
     }
 
@@ -186,11 +229,11 @@
                 x = schur_fact.schur_matrix ();
                 u = schur_fact.unitary_schur_matrix ();
               }
-            while (0); // schur no longer needed.
+            while (0);  // schur_fact no longer needed.
 
             sqrtm_utri_inplace (x);
 
-            x = u * x; // original x no longer needed.
+            x = u * x;  // original x no longer needed.
             ComplexMatrix res = xgemm (x, u, blas_no_trans, blas_conj_trans);
 
             if (cutoff > 0 && xnorm (imag (res), one) <= cutoff)
--- a/libinterp/corefcn/stack-frame.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/stack-frame.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -30,6 +30,7 @@
 #include <iostream>
 
 #include "lo-regexp.h"
+#include "lo-sysdep.h"
 #include "str-vec.h"
 
 #include "defun.h"
@@ -48,6 +49,7 @@
 #include "syminfo.h"
 #include "symrec.h"
 #include "symscope.h"
+#include "utils.h"
 #include "variables.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -190,6 +192,14 @@
     return m_static_link->varref (sym);
   }
 
+  std::string inputname (int n, bool ids_only) const
+  {
+    // Look in closest stack frame that contains values (either the
+    // top scope, or a user-defined function or script).
+
+    return m_static_link->inputname (n, ids_only);
+  }
+
   void mark_scope (const symbol_record& sym, scope_flags flag)
   {
     // Look in closest stack frame that contains values (either the
@@ -315,6 +325,11 @@
 
   octave_value& varref (const symbol_record& sym);
 
+  std::string inputname (int n, bool ids_only) const
+  {
+    return m_access_link->inputname (n, ids_only);
+  }
+
   void mark_scope (const symbol_record& sym, scope_flags flag);
 
   void display (bool follow = true) const;
@@ -551,6 +566,8 @@
 
   octave_value& varref (const symbol_record& sym);
 
+  std::string inputname (int n, bool ids_only) const;
+
   void mark_scope (const symbol_record& sym, scope_flags flag);
 
   void display (bool follow = true) const;
@@ -621,6 +638,14 @@
 
   octave_value& varref (const symbol_record& sym);
 
+  std::string inputname (int, bool) const
+  {
+    if (m_index == 0)
+      error ("invalid call to inputname outside of a function");
+
+    return "";
+  }
+
   void mark_scope (const symbol_record& sym, scope_flags flag);
 
   void display (bool follow = true) const;
@@ -1132,7 +1157,7 @@
       symbol_info syminf (sym.name (), value, sym.is_formal (),
                           is_global (sym), is_persistent (sym));
 
-      symbol_stats.append (syminf);
+      symbol_stats.push_back (syminf);
     }
 
   return symbol_stats;
@@ -1277,7 +1302,7 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::size () - please report this bug");
 }
 
 void
@@ -1287,7 +1312,7 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::resize () - please report this bug");
 }
 
 stack_frame::scope_flags
@@ -1297,7 +1322,7 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::get_scope_flag (std::size_t) - please report this bug");
 }
 
 void
@@ -1307,7 +1332,7 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::get_scope_flag (std::size_t, scope_flags) - please report this bug");
 }
 
 void
@@ -1364,7 +1389,7 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::varval (std::size_t) - please report this bug");
 }
 
 octave_value&
@@ -1374,7 +1399,16 @@
   // scope_stack_frame objects.  Anything else indicates an error in
   // the implementation.
 
-  panic_impossible ();
+  error ("unexpected call to stack_frame::varref (std::size_t) - please report this bug");
+}
+
+std::string
+stack_frame::inputname (int, bool) const
+{
+  // This function should only be called for user_fcn_stack_frame.
+  // Anything else indicates an error in the implementation.
+
+  error ("unexpected call to stack_frame::inputname (int, bool) - please report this bug");
 }
 
 void
@@ -1451,6 +1485,24 @@
 }
 
 void
+stack_frame::debug_list (std::ostream& os, int num_lines) const
+{
+  std::string file_name = fcn_file_name ();
+
+  int target_line = line ();
+  int start = std::max (target_line - num_lines/2, 0);
+  int end = target_line + num_lines/2;
+
+  display_file_lines (os, fcn_file_name (), start, end, target_line, "-->", "dblist");
+}
+
+void
+stack_frame::debug_type (std::ostream& os, int start_line, int end_line) const
+{
+  display_file_lines (os, fcn_file_name (), start_line, end_line, -1, "", "dbtype");
+}
+
+void
 stack_frame::display (bool follow) const
 {
   std::ostream& os = octave_stdout;
@@ -1653,7 +1705,8 @@
   // scope.  If the symbol wasn't present before, it should be outside
   // the range so we need to resize then update offsets.
 
-  panic_unless (data_offset >= size ());
+  if (data_offset < size ())
+    error ("unexpected: data_offset < size () in script_stack_frame::resize_and_update_script_offsets - please report this bug");
 
   resize (data_offset+1);
 
@@ -1706,7 +1759,8 @@
 
   if (sym)
     {
-      panic_unless (sym.frame_offset () == 0);
+      if (sym.frame_offset () != 0)
+        error ("unexpected: sym.frame_offset () != 0 in script_stack_frame::lookup_symbol - please report this bug");
 
       return sym;
     }
@@ -1736,7 +1790,9 @@
       // All symbol records in a script scope should have zero offset,
       // which means we redirect our lookup using
       // lexical_frame_offsets and values_offets.
-      panic_unless (sym.frame_offset () == 0);
+
+      if (sym.frame_offset () != 0)
+        error ("unexpected: sym.frame_offset () != 0 in script_stack_frame::insert_symbol - please report this bug");
 
       return sym;
     }
@@ -1746,7 +1802,8 @@
 
   sym = scope.find_symbol (name);
 
-  panic_unless (sym.is_valid ());
+  if (! sym.is_valid ())
+    error ("unexpected: sym is not valid in script_stack_frame::insert_symbol - please report this bug");
 
   resize_and_update_script_offsets (sym);
 
@@ -2290,7 +2347,8 @@
 
   sym = scope.find_symbol (name);
 
-  panic_unless (sym.is_valid ());
+  if (! sym.is_valid ())
+    error ("unexpected: sym is not valid in user_fcn_stack_frame::insert_symbol - please report this bug");
 
   return sym;
 }
@@ -2402,6 +2460,25 @@
   error ("internal error: invalid switch case");
 }
 
+std::string
+user_fcn_stack_frame::inputname (int n, bool ids_only) const
+{
+  std::string name;
+
+  Array<std::string> arg_names
+    = m_auto_vars.at (stack_frame::ARG_NAMES).cellstr_value ();
+
+  if (n >= 0 && n < arg_names.numel ())
+    {
+      name = arg_names(n);
+
+      if (ids_only && ! m_static_link->is_variable (name))
+        name = "";
+    }
+
+  return name;
+}
+
 void
 user_fcn_stack_frame::mark_scope (const symbol_record& sym, scope_flags flag)
 {
@@ -2464,7 +2541,8 @@
 
   sym = m_scope.find_symbol (name);
 
-  panic_unless (sym.is_valid ());
+  if (! sym.is_valid ())
+    error ("unexpected: sym is not valid in scope_stack_frame::insert_symbol - please report this bug");
 
   return sym;
 }
--- a/libinterp/corefcn/stack-frame.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/stack-frame.h	Fri Apr 12 15:10:26 2024 +0200
@@ -455,6 +455,8 @@
 
   virtual octave_value& varref (std::size_t data_offset);
 
+  virtual std::string inputname (int n, bool ids_only) const;
+
   void assign (const symbol_record& sym, const octave_value& val)
   {
     octave_value& lhs = varref (sym);
@@ -559,6 +561,15 @@
 
   void display_stopped_in_message (std::ostream& os) const;
 
+  void debug_where (std::ostream& os) const
+  {
+    display_stopped_in_message (os);
+  }
+
+  void debug_list (std::ostream& os, int num_lines) const;
+
+  void debug_type (std::ostream& os, int start_line, int end_line) const;
+
   virtual void mark_scope (const symbol_record&, scope_flags) = 0;
 
   virtual void display (bool follow = true) const;
--- a/libinterp/corefcn/strfind.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/strfind.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -365,7 +365,7 @@
               ret.clear (dim_vector (1, retsiz));
               const char *src = str.data ();
               const char *reps = rep.data ();
-              char *dest = ret.fortran_vec ();
+              char *dest = ret.rwdata ();
 
               octave_idx_type k = 0;
               for (octave_idx_type i = 0; i < nidx; i++)
--- a/libinterp/corefcn/strfns.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/strfns.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -908,7 +908,7 @@
                codepage, std::strerror (errno));
     }
 
-  unwind_action free_utf8_str ([=] () { ::free (utf8_str); });
+  unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });
 
   octave_idx_type len = length;
 
@@ -953,7 +953,7 @@
                codepage, std::strerror (errno));
     }
 
-  unwind_action free_native_bytes ([=] () { ::free (native_bytes); });
+  unwind_action free_native_bytes ([native_bytes] () { ::free (native_bytes); });
 
   octave_idx_type len = length;
 
@@ -1221,7 +1221,7 @@
   int width = -1;
 
   if (nargin > 1 && ! args(1).isempty ())
-    width = args(1).xint_value ("list_in_columns: WIDTH must be an integer");
+    width = args(1).yint_value ("list_in_columns: WIDTH must be an integer");
 
   std::string prefix;
 
--- a/libinterp/corefcn/sub2ind.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sub2ind.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -117,7 +117,7 @@
   if (nargin < 2)
     print_usage ();
 
-  dim_vector dv = get_dim_vector (args(0), "sub2ind");
+  const dim_vector& dv = get_dim_vector (args(0), "sub2ind");
 
   Array<idx_vector> idxa (dim_vector (nargin-1, 1));
 
--- a/libinterp/corefcn/syminfo.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/syminfo.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -169,7 +169,7 @@
 octave_value
 symbol_info_list::varval (const std::string& name) const
 {
-  for (const auto& syminfo : m_lst)
+  for (const auto& syminfo : *this)
     {
       if (name == syminfo.name ())
         return syminfo.value ();
@@ -183,7 +183,7 @@
 {
   std::list<std::string> retval;
 
-  for (const auto& syminfo : m_lst)
+  for (const auto& syminfo : *this)
     retval.push_back (syminfo.name ());
 
   return retval;
@@ -193,7 +193,7 @@
 symbol_info_list::map_value (const std::string& caller_function_name,
                              int nesting_level) const
 {
-  std::size_t len = m_lst.size ();
+  std::size_t len = size ();
 
   Cell name_info (len, 1);
   Cell size_info (len, 1);
@@ -207,7 +207,7 @@
 
   std::size_t j = 0;
 
-  for (const auto& syminfo : m_lst)
+  for (const auto& syminfo : *this)
     {
       octave_scalar_map ni;
 
@@ -334,7 +334,7 @@
 symbol_info_list::display (std::ostream& os,
                            const std::string& format) const
 {
-  if (! m_lst.empty ())
+  if (! empty ())
     {
       std::size_t bytes = 0;
       std::size_t elements = 0;
@@ -345,7 +345,7 @@
 
       octave_stdout << "\n";
 
-      for (const auto& syminfo : m_lst)
+      for (const auto& syminfo : *this)
         {
           syminfo.display_line (os, params);
 
@@ -403,7 +403,7 @@
   // Calculating necessary spacing for name column,
   // bytes column, elements column and class column
 
-  for (const auto& syminfo : m_lst)
+  for (const auto& syminfo : *this)
     {
       std::stringstream ss1, ss2;
       std::string str;
@@ -511,7 +511,7 @@
               int first = param.first_parameter_length;
               int total = param.parameter_length;
 
-              for (const auto& syminfo : m_lst)
+              for (const auto& syminfo : *this)
                 {
                   octave_value val = syminfo.value ();
                   std::string dims_str = val.get_dims_str ();
--- a/libinterp/corefcn/syminfo.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/syminfo.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,10 +28,9 @@
 
 #include "octave-config.h"
 
+#include <iosfwd>
+#include <list>
 #include <string>
-#include <iosfwd>
-
-#include "base-list.h"
 
 #include "ov.h"
 
@@ -50,9 +49,7 @@
   std::string line;
 };
 
-class
-OCTINTERP_API
-symbol_info
+class OCTINTERP_API symbol_info
 {
 public:
 
@@ -90,9 +87,7 @@
   bool m_is_persistent;
 };
 
-class
-OCTINTERP_API
-symbol_info_list : public base_list<symbol_info>
+class OCTINTERP_API symbol_info_list : public std::list<symbol_info>
 {
 public:
 
--- a/libinterp/corefcn/symrcm.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/symrcm.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -206,7 +206,7 @@
 
   OCTAVE_LOCAL_BUFFER (CMK_Node, Q, N+1);
   boolNDArray btmp (dim_vector (1, N), false);
-  bool *visit = btmp.fortran_vec ();
+  bool *visit = btmp.rwdata ();
 
   octave_idx_type qh = 0;
   octave_idx_type qt = 0;
@@ -512,7 +512,7 @@
   // that have degree==0 and build a CC of the graph.
 
   boolNDArray btmp (dim_vector (1, N), false);
-  bool *visit = btmp.fortran_vec ();
+  bool *visit = btmp.rwdata ();
 
   octave_quit ();
 
--- a/libinterp/corefcn/symrec.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/symrec.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,9 +40,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class symbol_scope_rep;
-
-class symbol_record
+class OCTINTERP_API symbol_record
 {
 public:
 
@@ -125,11 +123,18 @@
                         | ADDED_STATIC);
     }
 
+    void mark_variable ()
+    {
+      m_storage_class = static_cast<symrec_t> (m_storage_class | VARIABLE);
+    }
+
+    OCTAVE_DEPRECATED (10, "symbol_record_rep::mark_as_variable is obsolete, use mark_variable")
     void mark_as_variable ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class | VARIABLE);
     }
 
+
     void unmark_local ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class & ~LOCAL);
@@ -146,6 +151,12 @@
                         & ~ADDED_STATIC);
     }
 
+    void unmark_variable ()
+    {
+      m_storage_class = static_cast<symrec_t> (m_storage_class & ~VARIABLE);
+    }
+
+    OCTAVE_DEPRECATED (10, "symbol_record_rep::unmark_as_variable is obsolete, use unmark_variable")
     void unmark_as_variable ()
     {
       m_storage_class = static_cast<symrec_t> (m_storage_class & ~VARIABLE);
@@ -216,12 +227,16 @@
   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 mark_variable () { m_rep->mark_variable (); }
+  OCTAVE_DEPRECATED (10, "symbol_record::mark_as_variable is obsolete, use mark_variable")
+  void mark_as_variable () { m_rep->mark_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 (); }
+  void unmark_variable () { m_rep->unmark_variable (); }
+  OCTAVE_DEPRECATED (10, "symbol_record::unmark_as_variable is obsolete, use unmark_variable")
+  void unmark_as_variable () { m_rep->unmark_variable (); }
 
   unsigned int storage_class () const { return m_rep->storage_class (); }
 
--- a/libinterp/corefcn/symscope.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/symscope.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-symbol_record symbol_scope_rep::insert_local (const std::string& name)
+symbol_record symbol_scope::symbol_scope_rep::insert_local (const std::string& name)
 {
   symbol_record sym (name);
 
@@ -52,7 +52,7 @@
 }
 
 void
-symbol_scope_rep::insert_symbol_record (symbol_record& sr)
+symbol_scope::symbol_scope_rep::insert_symbol_record (symbol_record& sr)
 {
   std::size_t data_offset = num_symbols ();
   std::string name = sr.name ();
@@ -63,7 +63,7 @@
 }
 
 symbol_record
-symbol_scope_rep::insert (const std::string& name)
+symbol_scope::symbol_scope_rep::insert (const std::string& name)
 {
   table_iterator p = m_symbols.find (name);
 
@@ -95,7 +95,7 @@
 }
 
 std::list<octave_value>
-symbol_scope_rep::localfunctions () const
+symbol_scope::symbol_scope_rep::localfunctions () const
 {
   std::list<octave_value> retval;
 
@@ -133,7 +133,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump () const
+symbol_scope::symbol_scope_rep::dump () const
 {
   std::map<std::string, octave_value> m
   = {{ "name", m_name },
@@ -148,7 +148,7 @@
 }
 
 octave_value
-symbol_scope_rep::dump_symbols_map () const
+symbol_scope::symbol_scope_rep::dump_symbols_map () const
 {
   std::map<std::string, octave_value> info_map;
 
@@ -163,7 +163,7 @@
 }
 
 std::list<symbol_record>
-symbol_scope_rep::symbol_list () const
+symbol_scope::symbol_scope_rep::symbol_list () const
 {
   std::list<symbol_record> retval;
 
@@ -174,7 +174,7 @@
 }
 
 octave_value
-symbol_scope_rep::find_subfunction (const std::string& name) const
+symbol_scope::symbol_scope_rep::find_subfunction (const std::string& name) const
 {
   subfunctions_const_iterator p = m_subfunctions.find (name);
 
@@ -190,7 +190,7 @@
 }
 
 void
-symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
+symbol_scope::symbol_scope_rep::mark_subfunctions_in_scope_as_private (const std::string& class_name)
 {
   for (auto& nm_sf : m_subfunctions)
     {
@@ -202,7 +202,7 @@
 }
 
 std::list<std::string>
-symbol_scope_rep::parent_fcn_names () const
+symbol_scope::symbol_scope_rep::parent_fcn_names () const
 {
   std::list<std::string> retval;
 
@@ -219,25 +219,25 @@
 }
 
 void
-symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope_rep>& parent)
+symbol_scope::symbol_scope_rep::set_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
 {
-  m_parent = std::weak_ptr<symbol_scope_rep> (parent);
+  m_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
 }
 
 void
-symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent)
+symbol_scope::symbol_scope_rep::set_primary_parent (const std::shared_ptr<symbol_scope::symbol_scope_rep>& parent)
 {
-  m_primary_parent = std::weak_ptr<symbol_scope_rep> (parent);
+  m_primary_parent = std::weak_ptr<symbol_scope::symbol_scope_rep> (parent);
 }
 
 void
-symbol_scope_rep::cache_dir_name (const std::string& name)
+symbol_scope::symbol_scope_rep::cache_dir_name (const std::string& name)
 {
   m_dir_name = sys::canonicalize_file_name (name);
 }
 
 bool
-symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const
+symbol_scope::symbol_scope_rep::is_relative (const std::shared_ptr<symbol_scope::symbol_scope_rep>& scope) const
 {
   if (is_nested ())
     {
@@ -276,23 +276,23 @@
 }
 
 void
-symbol_scope_rep::mark_as_variable (const std::string& nm)
+symbol_scope::symbol_scope_rep::mark_as_variable (const std::string& nm)
 {
   table_iterator p = m_symbols.find (nm);
 
   if (p != m_symbols.end ())
-    p->second.mark_as_variable ();
+    p->second.mark_variable ();
 }
 
 void
-symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)
+symbol_scope::symbol_scope_rep::mark_as_variables (const std::list<std::string>& lst)
 {
   for (const auto& nm : lst)
     mark_as_variable (nm);
 }
 
 bool
-symbol_scope_rep::is_variable (const std::string& nm) const
+symbol_scope::symbol_scope_rep::is_variable (const std::string& nm) const
 {
   table_const_iterator p = m_symbols.find (nm);
 
@@ -312,7 +312,7 @@
 }
 
 void
-symbol_scope_rep::update_nest ()
+symbol_scope::symbol_scope_rep::update_nest ()
 {
   auto t_parent = m_parent.lock ();
 
@@ -344,9 +344,9 @@
 }
 
 bool
-symbol_scope_rep::look_nonlocal (const std::string& name,
-                                 std::size_t offset,
-                                 symbol_record& result)
+symbol_scope::symbol_scope_rep::look_nonlocal (const std::string& name,
+                                               std::size_t offset,
+                                               symbol_record& result)
 {
   offset++;
 
@@ -388,7 +388,7 @@
   if (is_primary_fcn_scope ())
     return m_rep->localfunctions ();
 
-  std::shared_ptr<symbol_scope_rep> ppsr
+  std::shared_ptr<symbol_scope::symbol_scope_rep> ppsr
     = m_rep->primary_parent_scope_rep ();
 
   if (! ppsr)
--- a/libinterp/corefcn/symscope.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/symscope.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,327 +48,327 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class symbol_scope;
-
-class symbol_scope_rep
-  : public std::enable_shared_from_this<symbol_scope_rep>
+class OCTINTERP_API symbol_scope
 {
-public:
-
-  typedef std::map<std::string, symbol_record>::const_iterator
-    table_const_iterator;
-  typedef std::map<std::string, symbol_record>::iterator
-    table_iterator;
-
-  typedef std::map<std::string, octave_value>::const_iterator
-    subfunctions_const_iterator;
-  typedef std::map<std::string, octave_value>::iterator
-    subfunctions_iterator;
-
-  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)
-  {
-    // Most scopes have ans as the first symbol, initially undefined.
-    if (add_ans)
-      insert_local ("ans");
-  }
-
-  OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)
-
-  ~symbol_scope_rep () = default;
-
-  std::size_t num_symbols () const { return m_symbols.size (); }
-
-  // Simply inserts symbol.  No non-local searching.
-
-  symbol_record insert_local (const std::string& name);
-
-  void insert_symbol_record (symbol_record& sr);
-
-  bool is_nested () const { return m_nesting_depth > 0; }
-
-  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 () const { return ! m_children.empty (); }
-
-  bool is_static () const { return m_is_static; }
-
-  void mark_static () { m_is_static = true; }
-
-  std::shared_ptr<symbol_scope_rep> parent_scope_rep () const
-  {
-    return m_parent.lock ();
-  }
-
-  std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const
-  {
-    return m_primary_parent.lock ();
-  }
-
-  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));
-
-    for (const auto& nm_sr : m_symbols)
-      new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();
-
-    new_sid->m_subfunctions = m_subfunctions;
-    new_sid->m_persistent_values = m_persistent_values;
-    new_sid->m_subfunction_names = m_subfunction_names;
-    new_sid->m_code = m_code;
-    new_sid->m_fcn_name = m_fcn_name;
-    new_sid->m_fcn_file_name = m_fcn_file_name;
-    new_sid->m_dir_name = m_dir_name;
-    new_sid->m_parent = m_parent;
-    new_sid->m_primary_parent = m_primary_parent;
-    new_sid->m_children = m_children;
-    new_sid->m_nesting_depth = m_nesting_depth;
-    new_sid->m_is_static = m_is_static;
-    new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope;
-
-    return new_sid;
-  }
-
-  octave_value& persistent_varref (std::size_t data_offset)
-  {
-    return m_persistent_values[data_offset];
-  }
-
-  octave_value persistent_varval (std::size_t data_offset) const
-  {
-    auto p = m_persistent_values.find (data_offset);
-
-    return p == m_persistent_values.end () ? octave_value () : p->second;
-  }
-
-  symbol_record find_symbol (const std::string& name)
-  {
-    auto p = m_symbols.find (name);
-
-    if (p == m_symbols.end ())
-      return insert (name);
-    else
-      return p->second;
-  }
-
-  symbol_record lookup_symbol (const std::string& name) const
-  {
-    auto p = m_symbols.find (name);
-
-    return p == m_symbols.end () ? symbol_record () : p->second;
-  }
-
-  symbol_record insert (const std::string& name);
-
-  void rename (const std::string& old_name, const std::string& new_name)
-  {
-    auto p = m_symbols.find (old_name);
-
-    if (p != m_symbols.end ())
-      {
-        symbol_record sr = p->second;
-
-        sr.rename (new_name);
-
-        m_symbols.erase (p);
-
-        m_symbols[new_name] = sr;
-      }
-  }
-
-  void install_subfunction (const std::string& name,
-                            const octave_value& fval)
-  {
-    m_subfunctions[name] = fval;
-  }
-
-  void install_nestfunction (const std::string& name,
-                             const octave_value& fval,
-                             const symbol_scope& fcn_scope)
-  {
-    m_subfunctions[name] = fval;
-
-    m_children.push_back (fcn_scope);
-  }
-
-  octave_value find_subfunction (const std::string& name) const;
-
-  void lock_subfunctions ()
-  {
-    for (auto& nm_sf : m_subfunctions)
-      nm_sf.second.lock ();
-  }
-
-  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 () const
-  {
-    return m_subfunctions;
-  }
-
-  void erase_subfunctions ()
-  {
-    m_subfunctions.clear ();
-  }
-
-  void mark_subfunctions_in_scope_as_private (const std::string& class_name);
-
-  bool has_subfunctions () const
-  {
-    return ! m_subfunction_names.empty ();
-  }
-
-  void stash_subfunction_names (const std::list<std::string>& names)
-  {
-    m_subfunction_names = names;
-  }
-
-  std::list<std::string> subfunction_names () const
-  {
-    return m_subfunction_names;
-  }
-
-  std::list<octave_value> localfunctions () const;
-
-  octave_value dump () const;
-
-  std::string name () const { return m_name; }
-
-  void cache_name (const std::string& name) { m_name = 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 () const;
-
-  octave_user_code * user_code () const { return m_code; }
-
-  void set_user_code (octave_user_code *code) { m_code = code; }
-
-  void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);
-
-  void set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent);
-
-  void cache_fcn_file_name (const std::string& name)
-  {
-    m_fcn_file_name = name;
-  }
-
-  std::string fcn_file_name () const { return m_fcn_file_name; }
-
-  void cache_dir_name (const std::string& name);
-
-  std::string dir_name () const { return m_dir_name; }
-
-  void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }
-
-  bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }
-
-  bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;
-
-  void mark_as_variable (const std::string& nm);
-  void mark_as_variables (const std::list<std::string>& lst);
-
-  bool is_variable (const std::string& nm) const;
-
-  void update_nest ();
-
-  bool look_nonlocal (const std::string& name, std::size_t offset,
-                      symbol_record& result);
-
-  octave_value dump_symbols_map () const;
-
-  const std::map<std::string, symbol_record>& symbols () const
-  {
-    return m_symbols;
-  }
-
-  std::map<std::string, symbol_record>& symbols ()
-  {
-    return m_symbols;
-  }
-
-  std::list<symbol_record> symbol_list () const;
-
 private:
 
-  //! Name for this scope (usually the corresponding filename of the
-  //! function corresponding to the scope).
+  class symbol_scope_rep
+    : public std::enable_shared_from_this<symbol_scope_rep>
+  {
+  public:
+
+    typedef std::map<std::string, symbol_record>::const_iterator
+      table_const_iterator;
+    typedef std::map<std::string, symbol_record>::iterator
+      table_iterator;
+
+    typedef std::map<std::string, octave_value>::const_iterator
+      subfunctions_const_iterator;
+    typedef std::map<std::string, octave_value>::iterator
+      subfunctions_iterator;
 
-  std::string m_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)
+    {
+      // Most scopes have ans as the first symbol, initially undefined.
+      if (add_ans)
+        insert_local ("ans");
+    }
+
+    OCTAVE_DISABLE_COPY_MOVE (symbol_scope_rep)
+
+    ~symbol_scope_rep () = default;
+
+    std::size_t num_symbols () const { return m_symbols.size (); }
 
-  //! Map from symbol names to symbol info.
+    // Simply inserts symbol.  No non-local searching.
+
+    symbol_record insert_local (const std::string& name);
+
+    void insert_symbol_record (symbol_record& sr);
+
+    bool is_nested () const { return m_nesting_depth > 0; }
 
-  std::map<std::string, symbol_record> m_symbols;
+    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 () const { return ! m_children.empty (); }
+
+    bool is_static () const { return m_is_static; }
+
+    void mark_static () { m_is_static = true; }
 
-  //! Map from symbol names to subfunctions.
+    std::shared_ptr<symbol_scope_rep> parent_scope_rep () const
+    {
+      return m_parent.lock ();
+    }
 
-  std::map<std::string, octave_value> m_subfunctions;
+    std::shared_ptr<symbol_scope_rep> primary_parent_scope_rep () const
+    {
+      return m_primary_parent.lock ();
+    }
+
+    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));
+
+      for (const auto& nm_sr : m_symbols)
+        new_sid->m_symbols[nm_sr.first] = nm_sr.second.dup ();
 
-  //! Map from data offset to persistent values in this scope.
-  std::map<std::size_t, octave_value> m_persistent_values;
+      new_sid->m_subfunctions = m_subfunctions;
+      new_sid->m_persistent_values = m_persistent_values;
+      new_sid->m_subfunction_names = m_subfunction_names;
+      new_sid->m_code = m_code;
+      new_sid->m_fcn_name = m_fcn_name;
+      new_sid->m_fcn_file_name = m_fcn_file_name;
+      new_sid->m_dir_name = m_dir_name;
+      new_sid->m_parent = m_parent;
+      new_sid->m_primary_parent = m_primary_parent;
+      new_sid->m_children = m_children;
+      new_sid->m_nesting_depth = m_nesting_depth;
+      new_sid->m_is_static = m_is_static;
+      new_sid->m_is_primary_fcn_scope = m_is_primary_fcn_scope;
+
+      return new_sid;
+    }
 
-  //! The list of subfunctions (if any) in the order they appear in
-  //! the function file.
+    octave_value& persistent_varref (std::size_t data_offset)
+    {
+      return m_persistent_values[data_offset];
+    }
+
+    octave_value persistent_varval (std::size_t data_offset) const
+    {
+      auto p = m_persistent_values.find (data_offset);
+
+      return p == m_persistent_values.end () ? octave_value () : p->second;
+    }
 
-  std::list<std::string> m_subfunction_names;
+    symbol_record find_symbol (const std::string& name)
+    {
+      auto p = m_symbols.find (name);
+
+      if (p == m_symbols.end ())
+        return insert (name);
+      else
+        return p->second;
+    }
+
+    symbol_record lookup_symbol (const std::string& name) const
+    {
+      auto p = m_symbols.find (name);
 
-  //! The associated user code (may be null).
+      return p == m_symbols.end () ? symbol_record () : p->second;
+    }
+
+    symbol_record insert (const std::string& name);
+
+    void rename (const std::string& old_name, const std::string& new_name)
+    {
+      auto p = m_symbols.find (old_name);
 
-  octave_user_code *m_code;
+      if (p != m_symbols.end ())
+        {
+          symbol_record sr = p->second;
+
+          sr.rename (new_name);
+
+          m_symbols.erase (p);
+
+          m_symbols[new_name] = sr;
+        }
+    }
 
-  //! Simple name of the function corresponding to this scope.
+    void install_subfunction (const std::string& name,
+                              const octave_value& fval)
+    {
+      m_subfunctions[name] = fval;
+    }
 
-  std::string m_fcn_name;
+    void install_nestfunction (const std::string& name,
+                               const octave_value& fval,
+                               const symbol_scope& fcn_scope)
+    {
+      m_subfunctions[name] = fval;
 
-  //! The file name associated with m_code.
+      m_children.push_back (fcn_scope);
+    }
+
+    octave_value find_subfunction (const std::string& name) const;
+
+    void lock_subfunctions ()
+    {
+      for (auto& nm_sf : m_subfunctions)
+        nm_sf.second.lock ();
+    }
 
-  std::string m_fcn_file_name;
+    void unlock_subfunctions ()
+    {
+      for (auto& nm_sf : m_subfunctions)
+        nm_sf.second.unlock ();
+    }
 
-  //! The directory associated with m_code.
+    // Pairs of name, function objects.
+    std::map<std::string, octave_value> subfunctions () const
+    {
+      return m_subfunctions;
+    }
+
+    void erase_subfunctions ()
+    {
+      m_subfunctions.clear ();
+    }
+
+    void mark_subfunctions_in_scope_as_private (const std::string& class_name);
 
-  std::string m_dir_name;
+    bool has_subfunctions () const
+    {
+      return ! m_subfunction_names.empty ();
+    }
+
+    void stash_subfunction_names (const std::list<std::string>& names)
+    {
+      m_subfunction_names = names;
+    }
 
-  //! Parent of nested function (may be null).
+    std::list<std::string> subfunction_names () const
+    {
+      return m_subfunction_names;
+    }
+
+    std::list<octave_value> localfunctions () const;
+
+    octave_value dump () const;
+
+    std::string name () const { return m_name; }
 
-  std::weak_ptr<symbol_scope_rep> m_parent;
+    void cache_name (const std::string& name) { m_name = 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 () const;
+
+    octave_user_code * user_code () const { return m_code; }
+
+    void set_user_code (octave_user_code *code) { m_code = code; }
+
+    void set_parent (const std::shared_ptr<symbol_scope_rep>& parent);
+
+    void set_primary_parent (const std::shared_ptr<symbol_scope_rep>& parent);
 
-  //! Primary (top) parent of nested function (may be null).  Used
-  //! to determine whether two nested functions are related.
+    void cache_fcn_file_name (const std::string& name)
+    {
+      m_fcn_file_name = name;
+    }
+
+    std::string fcn_file_name () const { return m_fcn_file_name; }
+
+    void cache_dir_name (const std::string& name);
+
+    std::string dir_name () const { return m_dir_name; }
 
-  std::weak_ptr<symbol_scope_rep> m_primary_parent;
+    void mark_primary_fcn_scope () { m_is_primary_fcn_scope = true; }
+
+    bool is_primary_fcn_scope () const { return m_is_primary_fcn_scope; }
+
+    bool is_relative (const std::shared_ptr<symbol_scope_rep>& scope) const;
 
-  //! Child nested functions.
+    void mark_as_variable (const std::string& nm);
+    void mark_as_variables (const std::list<std::string>& lst);
+
+    bool is_variable (const std::string& nm) const;
+
+    void update_nest ();
 
-  std::vector<symbol_scope> m_children;
+    bool look_nonlocal (const std::string& name, std::size_t offset,
+                        symbol_record& result);
+
+    octave_value dump_symbols_map () const;
 
-  //! If true, then this scope belongs to a nested function.
+    const std::map<std::string, symbol_record>& symbols () const
+    {
+      return m_symbols;
+    }
+
+    std::map<std::string, symbol_record>& symbols ()
+    {
+      return m_symbols;
+    }
+
+    std::list<symbol_record> symbol_list () const;
+
+  private:
 
-  std::size_t m_nesting_depth;
+    //! Name for this scope (usually the corresponding filename of the
+    //! function corresponding to the scope).
+
+    std::string m_name;
+
+    //! Map from symbol names to symbol info.
+
+    std::map<std::string, symbol_record> m_symbols;
 
-  //! If true then no variables can be added.
+    //! Map from symbol names to subfunctions.
+
+    std::map<std::string, octave_value> m_subfunctions;
+
+    //! Map from data offset to persistent values in this scope.
+    std::map<std::size_t, octave_value> m_persistent_values;
+
+    //! The list of subfunctions (if any) in the order they appear in
+    //! the function file.
+
+    std::list<std::string> m_subfunction_names;
 
-  bool m_is_static;
+    //! The associated user code (may be null).
+
+    octave_user_code *m_code;
+
+    //! Simple name of the function corresponding to this scope.
+
+    std::string m_fcn_name;
+
+    //! The file name associated with m_code.
+
+    std::string m_fcn_file_name;
+
+    //! The directory associated with m_code.
+
+    std::string m_dir_name;
+
+    //! Parent of nested function (may be null).
+
+    std::weak_ptr<symbol_scope_rep> m_parent;
 
-  //! If true, this is the scope of a primary function.
-  bool m_is_primary_fcn_scope;
-};
+    //! Primary (top) parent of nested function (may be null).  Used
+    //! to determine whether two nested functions are related.
+
+    std::weak_ptr<symbol_scope_rep> m_primary_parent;
+
+    //! Child nested functions.
+
+    std::vector<symbol_scope> m_children;
+
+    //! If true, then this scope belongs to a nested function.
 
-class symbol_scope
-{
+    std::size_t m_nesting_depth;
+
+    //! If true then no variables can be added.
+
+    bool m_is_static;
+
+    //! If true, this is the scope of a primary function.
+    bool m_is_primary_fcn_scope;
+  };
+
 public:
 
   symbol_scope () = delete;
--- a/libinterp/corefcn/syscalls.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/syscalls.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -124,25 +124,34 @@
   if (args.length () != 2)
     print_usage ();
 
-  stream_list& streams = interp.get_stream_list ();
-
-  stream old_stream = streams.lookup (args(0), "dup2");
+  int i_old, i_new;
+  try
+    {
+      // Look up FID in Octave's list of open streams.
+      stream_list& streams = interp.get_stream_list ();
 
-  stream new_stream = streams.lookup (args(1), "dup2");
-
-  int i_old = old_stream.file_number ();
-  int i_new = new_stream.file_number ();
+      stream old_stream = streams.lookup (args(0), "dup2");
+      stream new_stream = streams.lookup (args(1), "dup2");
 
-  if (i_old >= 0 && i_new >= 0)
+      i_old = old_stream.file_number ();
+      i_new = new_stream.file_number ();
+    }
+  catch (execution_exception& ee)
     {
-      std::string msg;
+      // If the FIDs are not known to Octave, try the provided FIDs directly.
+      i_old = args(0).int_value (true);
+      i_new = args(1).int_value (true);
+    }
 
-      int status = sys::dup2 (i_old, i_new, msg);
+  if (i_old < 0 || i_new < 0)
+    // Bad FIDs, return error immediately
+    return ovl (-1, "");
 
-      return ovl (status, msg);
-    }
-  else
-    return ovl (-1, "");
+  std::string msg;
+
+  int status = sys::dup2 (i_old, i_new, msg);
+
+  return ovl (status, msg);
 }
 
 DEFMETHODX ("exec", Fexec, interp, args, ,
@@ -439,20 +448,25 @@
   if (args.length () != 3)
     print_usage ();
 
-  stream_list& streams = interp.get_stream_list ();
-
-  stream strm = streams.lookup (args(0), "fcntl");
-
-  int fid = strm.file_number ();
+  int fid;
+  try
+    {
+      // Look up FID in Octave's list of open streams.
+      stream_list& streams = interp.get_stream_list ();
+      stream strm = streams.lookup (args(0), "fcntl");
+      fid = strm.file_number ();
+    }
+  catch (execution_exception& ee)
+    {
+      // If the file is not known to Octave, try the provided file ID directly.
+      fid = args(0).int_value (true);
+    }
 
-  // FIXME: Do we want to use xint_value and throw a warning message
-  //        if input validation fails?
-  int req = args(1).int_value (true);
-  int arg = args(2).int_value (true);
+  if (fid < 0)
+    error ("fcntl: invalid file id FID");
 
-  // FIXME: Need better checking here?
-  if (fid < 0)
-    error ("fcntl: invalid file id");
+  int req = args(1).yint_value ("fcntl: REQUEST must be an integer");
+  int arg = args(2).yint_value ("fcntl: ARG must be an integer");
 
   octave_value_list retval;
   std::string msg;
@@ -469,7 +483,7 @@
       if (status < 0)
         retval = ovl (-1.0, msg);
       else
-        retval = ovl (0.0, "");
+        retval = ovl (status, "");
     }
 
   return retval;
@@ -727,7 +741,7 @@
 
   std::string name = args(0).xstring_value ("mkfifo: FILE must be a string");
 
-  int octal_mode = args(1).xint_value ("mkfifo: MODE must be an integer");
+  int octal_mode = args(1).yint_value ("mkfifo: MODE must be an integer");
 
   if (octal_mode < 0)
     error ("mkfifo: MODE must be a positive integer value");
@@ -908,9 +922,21 @@
 
   if (args(0).is_scalar_type ())
     {
-      stream_list& streams = interp.get_stream_list ();
+      int fid;
+      try
+        {
+          // Look up FID in Octave's list of open streams.
+          stream_list& streams = interp.get_stream_list ();
+          fid = streams.get_file_number (args(0));
+        }
+      catch (execution_exception& ee)
+        {
+          // If the file is not known to Octave, try provided file ID directly.
+          fid = args(0).int_value (true);
+        }
 
-      int fid = streams.get_file_number (args(0));
+      if (fid < 0)
+        error ("stat: invalid file id FID");
 
       sys::file_fstat fs (fid);
 
@@ -1232,12 +1258,12 @@
   if (nargin != 1 && nargin != 2)
     print_usage ();
 
-  pid_t pid = args(0).xint_value ("waitpid: OPTIONS must be an integer");
+  pid_t pid = args(0).yint_value ("waitpid: OPTIONS must be an integer");
 
   int options = 0;
 
   if (nargin == 2)
-    options = args(1).xint_value ("waitpid: PID must be an integer value");
+    options = args(1).yint_value ("waitpid: PID must be an integer value");
 
   std::string msg;
   int status;
@@ -1259,7 +1285,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WIFEXITED: STATUS must be an integer");
+  int status = args(0).yint_value ("WIFEXITED: STATUS must be an integer");
 
   return ovl (sys::wifexited (status));
 }
@@ -1278,7 +1304,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WEXITSTATUS: STATUS must be an integer");
+  int status = args(0).yint_value ("WEXITSTATUS: STATUS must be an integer");
 
   return ovl (sys::wexitstatus (status));
 }
@@ -1295,7 +1321,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WIFSIGNALED: STATUS must be an integer");
+  int status = args(0).yint_value ("WIFSIGNALED: STATUS must be an integer");
 
   return ovl (sys::wifsignaled (status));
 }
@@ -1314,7 +1340,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WTERMSIG: STATUS must be an integer");
+  int status = args(0).yint_value ("WTERMSIG: STATUS must be an integer");
 
   return ovl (sys::wtermsig (status));
 }
@@ -1335,7 +1361,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WCOREDUMP: STATUS must be an integer");
+  int status = args(0).yint_value ("WCOREDUMP: STATUS must be an integer");
 
   return ovl (sys::wcoredump (status));
 }
@@ -1355,7 +1381,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WIFSTOPPED: STATUS must be an integer");
+  int status = args(0).yint_value ("WIFSTOPPED: STATUS must be an integer");
 
   return ovl (sys::wifstopped (status));
 }
@@ -1374,7 +1400,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WSTOPSIG: STATUS must be an integer");
+  int status = args(0).yint_value ("WSTOPSIG: STATUS must be an integer");
 
   return ovl (sys::wstopsig (status));
 }
@@ -1391,7 +1417,7 @@
   if (args.length () != 1)
     print_usage ();
 
-  int status = args(0).xint_value ("WIFCONTINUED: STATUS must be an integer");
+  int status = args(0).yint_value ("WIFCONTINUED: STATUS must be an integer");
 
   return ovl (sys::wifcontinued (status));
 }
--- a/libinterp/corefcn/sysdep.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/sysdep.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -907,7 +907,7 @@
   if (result != ERROR_SUCCESS)
     return result;
 
-  unwind_action restore_keys ([=] () { reg_close_key_wrapper (h_subkey); });
+  unwind_action restore_keys ([h_subkey] () { reg_close_key_wrapper (h_subkey); });
 
   std::wstring wname = sys::u8_to_wstring (name);
   DWORD length = 0;
--- a/libinterp/corefcn/text-engine.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/text-engine.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,10 +28,10 @@
 
 #include "octave-config.h"
 
+#include <list>
 #include <memory>
 #include <string>
 
-#include "base-list.h"
 #include "caseless-str.h"
 #include "dMatrix.h"
 
@@ -51,9 +51,7 @@
 
 class text_processor;
 
-class
-OCTINTERP_API
-text_element
+class OCTINTERP_API text_element
 {
 public:
 
@@ -64,9 +62,7 @@
   virtual void accept (text_processor& p) = 0;
 };
 
-class
-OCTINTERP_API
-text_element_string : public text_element
+class OCTINTERP_API text_element_string : public text_element
 {
 public:
 
@@ -84,9 +80,7 @@
   std::string m_str;
 };
 
-class
-OCTINTERP_API
-text_element_symbol : public text_element
+class OCTINTERP_API text_element_symbol : public text_element
 {
 public:
 
@@ -109,17 +103,15 @@
   int m_symbol;
 };
 
-class
-OCTINTERP_API
-text_element_list
-  : public text_element, public base_list<text_element *>
+class OCTINTERP_API text_element_list
+  : public text_element, public std::list<text_element *>
 {
 public:
 
   OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE (text_element_list)
 
   text_element_list (text_element *e)
-    : text_element (), base_list<text_element*> ()
+    : text_element (), std::list<text_element*> ()
   {
     push_back (e);
   }
@@ -137,9 +129,7 @@
   void accept (text_processor& p);
 };
 
-class
-OCTINTERP_API
-text_element_subscript : public text_element
+class OCTINTERP_API text_element_subscript : public text_element
 {
 public:
 
@@ -164,9 +154,7 @@
   text_element *m_elem;
 };
 
-class
-OCTINTERP_API
-text_element_superscript : public text_element
+class OCTINTERP_API text_element_superscript : public text_element
 {
 public:
 
@@ -191,9 +179,7 @@
   text_element *m_elem;
 };
 
-class
-OCTINTERP_API
-text_element_combined : public text_element_list
+class OCTINTERP_API text_element_combined : public text_element_list
 {
 public:
 
@@ -209,9 +195,7 @@
   void accept (text_processor& p);
 };
 
-class
-OCTINTERP_API
-text_element_fontstyle : public text_element
+class OCTINTERP_API text_element_fontstyle : public text_element
 {
 public:
 
@@ -239,9 +223,7 @@
   fontstyle m_style;
 };
 
-class
-OCTINTERP_API
-text_element_fontname : public text_element
+class OCTINTERP_API text_element_fontname : public text_element
 {
 public:
 
@@ -261,9 +243,7 @@
   std::string m_name;
 };
 
-class
-OCTINTERP_API
-text_element_fontsize : public text_element
+class OCTINTERP_API text_element_fontsize : public text_element
 {
 public:
 
@@ -283,9 +263,7 @@
   double m_size;
 };
 
-class
-OCTINTERP_API
-text_element_color : public text_element
+class OCTINTERP_API text_element_color : public text_element
 {
 public:
 
@@ -328,9 +306,7 @@
   Matrix m_rgb;
 };
 
-class
-OCTINTERP_API
-text_processor
+class OCTINTERP_API text_processor
 {
 public:
 
@@ -389,9 +365,7 @@
 TEXT_ELEMENT_ACCEPT(text_element_fontsize)
 TEXT_ELEMENT_ACCEPT(text_element_color)
 
-class
-OCTINTERP_API
-text_parser
+class OCTINTERP_API text_parser
 {
 public:
 
@@ -406,9 +380,7 @@
                               const caseless_str& interpreter);
 };
 
-class
-OCTINTERP_API
-text_parser_none : public text_parser
+class OCTINTERP_API text_parser_none : public text_parser
 {
 public:
 
@@ -425,9 +397,7 @@
   }
 };
 
-class
-OCTINTERP_API
-text_parser_tex : public text_parser
+class OCTINTERP_API text_parser_tex : public text_parser
 {
 public:
 
--- a/libinterp/corefcn/text-renderer.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/text-renderer.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 class base_text_renderer;
 class text_element;
 
-class
-OCTINTERP_API
-text_renderer
+class OCTINTERP_API text_renderer
 {
 public:
 
--- a/libinterp/corefcn/time.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/time.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,7 +69,7 @@
   octave_value v = m.getfield (k);
 
   if (! v.isempty ())
-    retval = v.xint_value ("%s: invalid TM_STRUCT argument", who);
+    retval = v.yint_value ("%s: invalid TM_STRUCT argument", who);
 
   return retval;
 }
--- a/libinterp/corefcn/toplev.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/toplev.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -380,12 +380,6 @@
         { "ENABLE_DOCS", false },
 #endif
 
-#if defined (OCTAVE_ENABLE_FLOAT_TRUNCATE)
-        { "ENABLE_FLOAT_TRUNCATE", true },
-#else
-        { "ENABLE_FLOAT_TRUNCATE", false },
-#endif
-
 #if defined (OCTAVE_ENABLE_OPENMP)
         { "ENABLE_OPENMP", true },
 #else
--- a/libinterp/corefcn/tril.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/tril.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,7 @@
       octave_idx_type j2 = std::min (std::max (zero, nr + k), nc);
       octave_idx_type n = j1 * nr + ((j2 - j1) * (nr-(j1-k) + nr-(j2-1-k))) / 2;
       Array<T> r (dim_vector (n, 1));
-      T *rvec = r.fortran_vec ();
+      T *rvec = r.rwdata ();
       for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_idx_type ii = std::min (std::max (zero, j - k), nr);
@@ -70,7 +70,7 @@
   else
     {
       Array<T> r (a.dims ());
-      T *rvec = r.fortran_vec ();
+      T *rvec = r.rwdata ();
       for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_idx_type ii = std::min (std::max (zero, j - k), nr);
@@ -100,7 +100,7 @@
       octave_idx_type n
         = ((j2 - j1) * ((j1+1-k) + (j2-k))) / 2 + (nc - j2) * nr;
       Array<T> r (dim_vector (n, 1));
-      T *rvec = r.fortran_vec ();
+      T *rvec = r.rwdata ();
       for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_idx_type ii = std::min (std::max (zero, j + 1 - k), nr);
@@ -113,7 +113,7 @@
   else
     {
       Array<T> r (a.dims ());
-      T *rvec = r.fortran_vec ();
+      T *rvec = r.rwdata ();
       for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_idx_type ii = std::min (std::max (zero, j + 1 - k), nr);
@@ -208,7 +208,7 @@
 
   octave_value arg = args(0);
 
-  dim_vector dims = arg.dims ();
+  const dim_vector& dims = arg.dims ();
   if (dims.ndims () != 2)
     error ("%s: need a 2-D matrix", name.c_str ());
   else if (k < -dims(0))
--- a/libinterp/corefcn/typecast.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/typecast.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -81,7 +81,7 @@
     error ("typecast: incorrect number of input values to make output value");
 
   ArrayType retval (get_vec_dims (old_dims, n));
-  T *dest = retval.fortran_vec ();
+  T *dest = retval.rwdata ();
   std::memcpy (dest, data, n * sizeof (T));
 
   return retval;
@@ -100,7 +100,7 @@
     error ("typecast: incorrect number of input values to make output value");
 
   ArrayType retval (get_vec_dims (old_dims, n));
-  VT *dest = reinterpret_cast<VT *> (retval.fortran_vec ());
+  VT *dest = reinterpret_cast<VT *> (retval.rwdata ());
   std::memcpy (dest, data, n * sizeof (VT));
 
   return retval;
@@ -323,7 +323,7 @@
   ArrayType retval (get_vec_dims (bitp.dims (), n));
 
   const bool *bits = bitp.data ();
-  char *packed = reinterpret_cast<char *> (retval.fortran_vec ());
+  char *packed = reinterpret_cast<char *> (retval.rwdata ());
 
   octave_idx_type m = n * sizeof (T);
 
@@ -471,7 +471,7 @@
   boolNDArray retval (get_vec_dims (array.dims (), n));
 
   const char *packed = reinterpret_cast<const char *> (array.data ());
-  bool *bits = retval.fortran_vec ();
+  bool *bits = retval.rwdata ();
 
   octave_idx_type m = n / std::numeric_limits<unsigned char>::digits;
 
--- a/libinterp/corefcn/utils.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/utils.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -803,6 +803,35 @@
   return retval;
 }
 
+void
+display_file_lines (std::ostream& os, const std::string& file_name, int start, int end, int target_line, const std::string& marker, const std::string& who)
+{
+  std::ifstream fs = octave::sys::ifstream (file_name.c_str (), std::ios::in);
+
+  if (! fs)
+    os << who << ": unable to open '" << file_name << "' for reading!\n";
+  else
+    {
+      int line_num = 1;
+      std::string text;
+
+      while (std::getline (fs, text) && line_num <= end)
+        {
+          if (line_num >= start)
+            {
+              os << line_num;
+
+              if (line_num == target_line)
+                os << marker;
+
+              os << "\t" << text << "\n";
+            }
+
+          line_num++;
+        }
+    }
+}
+
 // Replace backslash escapes in a string with the real values.
 
 std::string
@@ -1266,7 +1295,7 @@
         }
       else
         {
-          int val = args(0).xint_value ("errno: argument must be string or integer");
+          int val = args(0).yint_value ("errno: argument must be string or integer");
 
           retval = octave_errno::set (val);
         }
--- a/libinterp/corefcn/utils.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/utils.h	Fri Apr 12 15:10:26 2024 +0200
@@ -51,9 +51,7 @@
 //! Extracting options separately for multiple (e.g. 1000+) function calls
 //! avoids expensive repetitive parsing of the very same options.
 
-class
-OCTINTERP_API
-make_valid_name_options
+class OCTINTERP_API make_valid_name_options
 {
 public:
 
@@ -137,6 +135,9 @@
 
 extern OCTINTERP_API std::string fcn_file_in_path (const std::string&);
 
+extern OCTINTERP_API void
+display_file_lines (std::ostream& os, const std::string& file_name, int start, int end, int target_line, const std::string& marker, const std::string& who);
+
 extern OCTINTERP_API std::string do_string_escapes (const std::string& s);
 
 extern OCTINTERP_API const char * undo_string_escape (char c);
--- a/libinterp/corefcn/variables.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/variables.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -601,7 +601,7 @@
 
   if (nargin == 1)
     {
-      bool bval = args(0).xbool_value ("%s: argument must be a logical value", nm);
+      bool bval = args(0).ybool_value ("%s: argument must be a logical value", nm);
 
       var = bval;
     }
@@ -675,7 +675,7 @@
 
   if (nargin == 1)
     {
-      int ival = args(0).xint_value ("%s: argument must be an integer value", nm);
+      int ival = args(0).yint_value ("%s: argument must be an integer value", nm);
 
       if (ival < minval)
         error ("%s: arg must be greater than %d", nm, minval);
@@ -768,7 +768,7 @@
 
   int nargin = args.length ();
 
-  error_unless (var < nchoices);
+  panic_unless (var < nchoices);
 
   if (nargout > 0 || nargin == 0)
     retval = choices[var];
--- a/libinterp/corefcn/xdiv.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/xdiv.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include "Array-util.h"
 #include "CMatrix.h"
 #include "dMatrix.h"
@@ -713,7 +711,7 @@
   typedef typename MT::element_type T;
   const T *aa = a.data ();
   const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
+  T *xx = x.rwdata ();
 
   for (octave_idx_type j = 0; j < l; j++)
     {
@@ -797,7 +795,7 @@
   typedef typename MT::element_type T;
   const T *aa = a.data ();
   const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
+  T *xx = x.rwdata ();
 
   for (octave_idx_type j = 0; j < n; j++)
     {
@@ -878,7 +876,7 @@
   typedef typename MT::element_type T;
   const T *aa = a.data ();
   const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
+  T *xx = x.rwdata ();
 
   for (octave_idx_type i = 0; i < lk; i++)
     xx[i] = (dd[i] != S () ? aa[i] / dd[i] : T ());
@@ -953,7 +951,7 @@
   typedef typename MT::element_type T;
   const T *aa = a.data ();
   const S *dd = d.data ();
-  T *xx = x.fortran_vec ();
+  T *xx = x.rwdata ();
 
   for (octave_idx_type i = 0; i < lk; i++)
     xx[i] = (dd[i] != S () ? aa[i] / dd[i] : T ());
--- a/libinterp/corefcn/xpow.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/corefcn/xpow.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include <limits>
 
 #include "Array-util.h"
@@ -83,8 +81,9 @@
 static inline bool
 xisint (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;
+
   return (octave::math::x_nint (x) == x
           && x < out_of_range_top
           && x >= std::numeric_limits<int>::min ());
@@ -1259,8 +1258,8 @@
 {
   octave_value retval;
 
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -1342,8 +1341,8 @@
 octave_value
 elem_xpow (const NDArray& a, const ComplexNDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -1437,8 +1436,8 @@
 octave_value
 elem_xpow (const ComplexNDArray& a, const NDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -1482,8 +1481,8 @@
 octave_value
 elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -2579,8 +2578,8 @@
 {
   octave_value retval;
 
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -2662,8 +2661,8 @@
 octave_value
 elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -2757,8 +2756,8 @@
 octave_value
 elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
@@ -2802,8 +2801,8 @@
 octave_value
 elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b)
 {
-  dim_vector a_dims = a.dims ();
-  dim_vector b_dims = b.dims ();
+  const dim_vector& a_dims = a.dims ();
+  const dim_vector& b_dims = b.dims ();
 
   if (a_dims != b_dims)
     {
--- a/libinterp/dldfcn/__delaunayn__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/__delaunayn__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -155,7 +155,7 @@
   if (n > dim + 1)
     {
       p = p.transpose ();
-      double *pt_array = p.fortran_vec ();
+      double *pt_array = p.rwdata ();
       boolT ismalloc = false;
 
       std::string cmd = "qhull d " + options;
@@ -174,7 +174,7 @@
       if (! errfile)
         error ("__delaunayn__: unable to redirect Qhull errors to /dev/null");
 
-      unwind_action close_errfile ([=] () { std::fclose (errfile); });
+      unwind_action close_errfile ([errfile] () { std::fclose (errfile); });
 
       qhT context = { };
       qhT *qh = &context;
--- a/libinterp/dldfcn/__glpk__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/__glpk__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -332,7 +332,7 @@
       if (tmp.is_defined ())                                            \
         {                                                               \
           if (! tmp.isempty ())                                        \
-            VAL = tmp.xint_value ("glpk: invalid value in PARAM" NAME); \
+            VAL = tmp.yint_value ("glpk: invalid value in PARAM" NAME); \
           else                                                          \
             error ("glpk: invalid value in PARAM" NAME);                \
         }                                                               \
@@ -356,7 +356,7 @@
 
   Matrix C = args(0).xmatrix_value ("__glpk__: invalid value of C");
 
-  double *c = C.fortran_vec ();
+  double *c = C.rwdata ();
   Array<int> rn;
   Array<int> cn;
   ColumnVector a;
@@ -417,7 +417,7 @@
   //             for each constraint in the constraint matrix.
   Matrix B = args(2).xmatrix_value ("__glpk__: invalid value of B");
 
-  double *b = B.fortran_vec ();
+  double *b = B.rwdata ();
 
   // 4th Input.  An array of length mrowsc containing the lower
   //             bound on each of the variables.
@@ -426,7 +426,7 @@
   if (LB.numel () < mrowsc)
     error ("__glpk__: invalid dimensions for LB");
 
-  double *lb = LB.fortran_vec ();
+  double *lb = LB.rwdata ();
 
   // LB argument, default: Free
   Array<int> freeLB (dim_vector (mrowsc, 1));
@@ -448,7 +448,7 @@
   if (UB.numel () < mrowsc)
     error ("__glpk__: invalid dimensions for UB");
 
-  double *ub = UB.fortran_vec ();
+  double *ub = UB.rwdata ();
 
   Array<int> freeUB (dim_vector (mrowsc, 1));
   for (int i = 0; i < mrowsc; i++)
@@ -466,7 +466,7 @@
   //             in the constraint matrix.
   charMatrix CTYPE = args(5).xchar_matrix_value ("__glpk__: invalid value of CTYPE");
 
-  char *ctype = CTYPE.fortran_vec ();
+  char *ctype = CTYPE.rwdata ();
 
   // 7th Input.  A column array containing the types of the variables.
   charMatrix VTYPE = args(6).xchar_matrix_value ("__glpk__: invalid value of VARTYPE");
@@ -611,13 +611,13 @@
   double time = 0.0;
   int status = -1;
 
-  int errnum = glpk (sense, mrowsc, mrowsA, c, nz, rn.fortran_vec (),
-                     cn.fortran_vec (), a.fortran_vec (), b, ctype,
-                     freeLB.fortran_vec (), lb, freeUB.fortran_vec (),
-                     ub, vartype.fortran_vec (), isMIP, lpsolver,
-                     save_pb, scale, par, xmin.fortran_vec (), fmin,
-                     status, lambda.fortran_vec (),
-                     redcosts.fortran_vec (), time);
+  int errnum = glpk (sense, mrowsc, mrowsA, c, nz, rn.rwdata (),
+                     cn.rwdata (), a.rwdata (), b, ctype,
+                     freeLB.rwdata (), lb, freeUB.rwdata (),
+                     ub, vartype.rwdata (), isMIP, lpsolver,
+                     save_pb, scale, par, xmin.rwdata (), fmin,
+                     status, lambda.rwdata (),
+                     redcosts.rwdata (), time);
 
   octave_scalar_map extra;
 
--- a/libinterp/dldfcn/__init_fltk__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/__init_fltk__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -603,9 +603,21 @@
                   {
                     std::string valstr = fltk_label.substr (idx1 + 1, len - 1);
                     fltk_label.erase (idx1, len + 1);
-                    val = atoi (valstr.c_str ());
-                    if (val > 0 && val < 99)
-                      val++;
+
+                    // FIXME: Should we warn or error on invalid or out
+                    // of range values in VALSTR?  When atoi was used
+                    // for conversion instead of std::stoi we did not.
+                    // Was that intentional?
+
+                    try
+                      {
+                        val = std::stoi (valstr);
+
+                        if (val > 0 && val < 99)
+                          val++;
+                      }
+                    catch (const std::invalid_argument&) { }
+                    catch (const std::out_of_range&) { }
                   }
                 std::ostringstream valstream;
                 valstream << val;
--- a/libinterp/dldfcn/__ode15__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/__ode15__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -496,8 +496,8 @@
     jac = (*m_jacdcell) (m_dfdy, m_dfdyp, cj);
 
   octave_f77_int_type num_jac = to_f77_int (jac.numel ());
-  std::copy (jac.fortran_vec (),
-             jac.fortran_vec () + num_jac,
+  std::copy (jac.rwdata (),
+             jac.rwdata () + num_jac,
              SUNDenseMatrix_Data (JJ));
 }
 
@@ -1350,7 +1350,7 @@
 
   // Provided number of arguments in the ode callback function
   octave_idx_type num_event_args
-    = args(5).xidx_type_value ("__ode15__: NUM_EVENT_ARGS must be an integer");
+    = args(5).yidx_type_value ("__ode15__: NUM_EVENT_ARGS must be an integer");
 
   if (num_event_args != 2 && num_event_args != 3)
     error ("__ode15__: number of input arguments in event callback must be 2 or 3");
--- a/libinterp/dldfcn/__voronoi__.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/__voronoi__.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -164,7 +164,7 @@
 
   std::string cmd = "qhull v" + options;
 
-  int exitcode = qh_new_qhull (qh, dim, num_points, points.fortran_vec (),
+  int exitcode = qh_new_qhull (qh, dim, num_points, points.rwdata (),
                                ismalloc, &cmd[0], outfile, errfile);
 
   unwind_action free_memory ([qh] () { free_qhull_memory (qh); });
--- a/libinterp/dldfcn/audiodevinfo.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/audiodevinfo.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -1136,7 +1136,7 @@
   start = get_sample_number ();
   end = get_end_sample ();
 
-  unwind_action stop_audioplayer ([=] () { stop (); });
+  unwind_action stop_audioplayer ([this] () { stop (); });
 
   for (unsigned int i = start; i < end; i += buffer_size)
     {
@@ -1816,7 +1816,7 @@
 
   unsigned int frames = seconds * get_fs ();
 
-  unwind_action stop_audiorecorder ([=] () { stop (); });
+  unwind_action stop_audiorecorder ([this] () { stop (); });
 
   for (unsigned int i = 0; i < frames; i += buffer_size)
     {
--- a/libinterp/dldfcn/audioread.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/audioread.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -90,7 +90,7 @@
     error ("audioread: failed to open input file '%s': %s",
            filename.c_str (), sf_strerror (file));
 
-  unwind_action close_open_file ([=] () { sf_close (file); });
+  unwind_action close_open_file ([file] () { sf_close (file); });
 
   // FIXME: It would be nicer to use a C++ expandable data container and
   // read a file of unknown length into memory in chunks and determine the
@@ -128,7 +128,7 @@
 
   Matrix audio (items, info.channels);
 
-  double *paudio = audio.fortran_vec ();
+  double *paudio = audio.rwdata ();
 
   data += start * info.channels;
 
@@ -441,7 +441,7 @@
     error ("audiowrite: failed to open output file '%s': %s",
            filename.c_str (), sf_strerror (file));
 
-  unwind_action close_open_file ([=] () { sf_close (file); });
+  unwind_action close_open_file ([file] () { sf_close (file); });
 
   sf_command (file, SFC_SET_NORM_DOUBLE, nullptr, SF_TRUE);
   sf_command (file, SFC_SET_CLIPPING, nullptr, SF_TRUE) ;
@@ -644,7 +644,7 @@
     error ("audioinfo: failed to open input file '%s': %s",
            filename.c_str (), sf_strerror (file));
 
-  unwind_action close_open_file ([=] () { sf_close (file); });
+  unwind_action close_open_file ([file] () { sf_close (file); });
 
   octave_scalar_map result;
 
--- a/libinterp/dldfcn/convhulln.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/dldfcn/convhulln.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -178,7 +178,7 @@
 
   std::string cmd = "qhull" + options;
 
-  int exitcode = qh_new_qhull (qh, dim, num_points, points.fortran_vec (),
+  int exitcode = qh_new_qhull (qh, dim, num_points, points.rwdata (),
                                ismalloc, &cmd[0], outfile, errfile);
 
   unwind_action free_memory ([qh] () { free_qhull_memory (qh); });
--- a/libinterp/octave-value/cdef-class.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-class.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -730,12 +730,15 @@
       if (pfcn == nullptr)
         continue;
 
-      const int e = pfcn->ending_line ();
-      if (line <= e && e <= closest_match_end_line && pfcn->is_defined ()
+      octave::filepos end_pos = pfcn->end_pos ();
+
+      int end_line = end_pos.line ();
+
+      if (line <= end_line && end_line <= closest_match_end_line && pfcn->is_defined ()
           && pfcn->is_user_code ())
         {
           closest_match = fcn;
-          closest_match_end_line = e;
+          closest_match_end_line = end_line;
         }
     }
 
@@ -969,7 +972,7 @@
 
       // Method blocks
 
-      std::list<tree_classdef_methods_block *> mb_list = b->methods_list ();
+      std::list<tree_classdef_methods_block *> mb_list = b->method_list ();
 
       load_path& lp = interp.get_load_path ();
 
@@ -1083,7 +1086,7 @@
       //        evaluating default value expressions.
 
       std::list<tree_classdef_properties_block *> pb_list
-        = b->properties_list ();
+        = b->property_list ();
 
       for (auto& pb_p : pb_list)
         {
--- a/libinterp/octave-value/cdef-class.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-class.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,14 +48,11 @@
 class interpreter;
 class tree_classdef;
 
-class
-OCTINTERP_API
-cdef_class : public cdef_meta_object
+class OCTINTERP_API cdef_class : public cdef_meta_object
 {
 private:
 
-  class
-  cdef_class_rep : public cdef_meta_object_rep
+  class cdef_class_rep : public cdef_meta_object_rep
   {
   public:
     cdef_class_rep ()
--- a/libinterp/octave-value/cdef-manager.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-manager.h	Fri Apr 12 15:10:26 2024 +0200
@@ -39,9 +39,7 @@
 
 class interpreter;
 
-class
-OCTINTERP_API
-cdef_manager
+class OCTINTERP_API cdef_manager
 {
 public:
 
--- a/libinterp/octave-value/cdef-method.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-method.h	Fri Apr 12 15:10:26 2024 +0200
@@ -39,16 +39,13 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-cdef_method : public cdef_meta_object
+class OCTINTERP_API cdef_method : public cdef_meta_object
 {
   friend class cdef_class;
 
 private:
 
-  class
-  cdef_method_rep : public cdef_meta_object_rep
+  class cdef_method_rep : public cdef_meta_object_rep
   {
   public:
 
--- a/libinterp/octave-value/cdef-object.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-object.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,9 +45,7 @@
 // The actual base class is cdef_class_base, which is declared after
 // cdef_object, such that it can contain cdef_object objects.
 
-class
-OCTINTERP_API
-cdef_object_rep
+class OCTINTERP_API cdef_object_rep
 {
 public:
 
@@ -198,9 +196,7 @@
   }
 };
 
-class
-OCTINTERP_API
-cdef_object
+class OCTINTERP_API cdef_object
 {
 public:
 
@@ -350,9 +346,7 @@
   cdef_object_rep *m_rep;
 };
 
-class
-OCTINTERP_API
-cdef_object_base : public cdef_object_rep
+class OCTINTERP_API cdef_object_base : public cdef_object_rep
 {
 public:
 
@@ -388,9 +382,7 @@
   cdef_object m_klass;
 };
 
-class
-OCTINTERP_API
-cdef_object_array : public cdef_object_base
+class OCTINTERP_API cdef_object_array : public cdef_object_base
 {
 public:
 
@@ -456,9 +448,7 @@
   { }
 };
 
-class
-OCTINTERP_API
-cdef_object_scalar : public cdef_object_base
+class OCTINTERP_API cdef_object_scalar : public cdef_object_base
 {
 public:
 
@@ -543,9 +533,7 @@
   { }
 };
 
-class
-OCTINTERP_API
-handle_cdef_object : public cdef_object_scalar
+class OCTINTERP_API handle_cdef_object : public cdef_object_scalar
 {
 public:
 
@@ -579,9 +567,7 @@
   { }
 };
 
-class
-OCTINTERP_API
-value_cdef_object : public cdef_object_scalar
+class OCTINTERP_API value_cdef_object : public cdef_object_scalar
 {
 public:
 
@@ -610,9 +596,7 @@
   { }
 };
 
-class
-OCTINTERP_API
-cdef_meta_object_rep : public handle_cdef_object
+class OCTINTERP_API cdef_meta_object_rep : public handle_cdef_object
 {
 public:
 
@@ -664,9 +648,7 @@
   { }
 };
 
-class
-OCTINTERP_API
-cdef_meta_object : public cdef_object
+class OCTINTERP_API cdef_meta_object : public cdef_object
 {
 public:
 
--- a/libinterp/octave-value/cdef-package.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-package.h	Fri Apr 12 15:10:26 2024 +0200
@@ -42,16 +42,13 @@
 
 class interpreter;
 
-class
-OCTINTERP_API
-cdef_package : public cdef_meta_object
+class OCTINTERP_API cdef_package : public cdef_meta_object
 {
   friend class cdef_class;
 
 private:
 
-  class
-  cdef_package_rep : public cdef_meta_object_rep
+  class cdef_package_rep : public cdef_meta_object_rep
   {
   public:
 
--- a/libinterp/octave-value/cdef-property.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/cdef-property.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,16 +40,13 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-cdef_property : public cdef_meta_object
+class OCTINTERP_API cdef_property : public cdef_meta_object
 {
   friend class cdef_class;
 
 private:
 
-  class
-  cdef_property_rep : public cdef_meta_object_rep
+  class cdef_property_rep : public cdef_meta_object_rep
   {
   public:
 
--- a/libinterp/octave-value/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -97,6 +97,9 @@
   %reldir%/cdef-package.cc \
   %reldir%/cdef-property.cc \
   %reldir%/cdef-utils.cc \
+  %reldir%/ov-base-int-inst.cc \
+  %reldir%/ov-base-mat-inst.cc \
+  %reldir%/ov-base-scalar-inst.cc \
   %reldir%/ov-base.cc \
   %reldir%/ov-bool-mat.cc \
   %reldir%/ov-bool.cc \
--- a/libinterp/octave-value/ov-base-diag.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-diag.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -68,7 +68,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_diag<DMT,MT>::subsref - please report this bug");
     }
 
   return retval.next_subsref (type, idx);
@@ -254,7 +254,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_diag<DMT,MT>::subsasgn - please report this bug");
     }
 
   return retval;
@@ -553,7 +553,7 @@
 bool
 octave_base_diag<DMT, MT>::print_as_scalar () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   return (dv.all_ones () || dv.any_zero ());
 }
--- a/libinterp/octave-value/ov-base-diag.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-diag.h	Fri Apr 12 15:10:26 2024 +0200
@@ -43,9 +43,7 @@
 // Real matrix values.
 
 template <typename DMT, typename MT>
-class
-OCTINTERP_API
-octave_base_diag : public octave_base_value
+class OCTINTERP_API octave_base_diag : public octave_base_value
 {
 
 public:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-base-int-inst.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,60 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2024 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 "int8NDArray.h"
+#include "int16NDArray.h"
+#include "int32NDArray.h"
+#include "int64NDArray.h"
+#include "uint8NDArray.h"
+#include "uint16NDArray.h"
+#include "uint32NDArray.h"
+#include "uint64NDArray.h"
+
+#include "ov-base-int.cc"
+
+// instantiate template class with types that need to be exported from library
+
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<int8NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<int16NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<int32NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<int64NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<uint8NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<uint16NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<uint32NDArray>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_matrix<uint64NDArray>;
+
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_int8>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_int16>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_int32>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_int64>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_uint8>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_uint16>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_uint32>;
+template class OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API octave_base_int_scalar<octave_uint64>;
+
--- a/libinterp/octave-value/ov-base-int.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-int.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -58,10 +58,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-base-int.h"
 #include "ov-int-traits.h"
 #include "pr-output.h"
@@ -160,7 +156,7 @@
 octave_base_int_matrix<T>::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   octave_idx_type nel = dv.numel ();
 
   charNDArray chm (dv);
@@ -177,8 +173,8 @@
 
       val_type ival = tmp.value ();
 
-      static const bool is_signed = std::numeric_limits<val_type>::is_signed;
-      static const bool can_be_larger_than_uchar_max
+      static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;
+      static constexpr bool can_be_larger_than_uchar_max
         = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
 
       if (octave_base_int_helper<val_type, is_signed,
@@ -288,7 +284,7 @@
 bool
 octave_base_int_matrix<T>::save_ascii (std::ostream& os)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
 
   os << "# ndims: " << dv.ndims () << "\n";
 
@@ -334,7 +330,7 @@
 bool
 octave_base_int_matrix<T>::save_binary (std::ostream& os, bool)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -394,7 +390,7 @@
 
   T m (dv);
 
-  if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
+  if (! is.read (reinterpret_cast<char *> (m.rwdata ()), m.byte_size ()))
     return false;
 
   if (swap)
@@ -434,7 +430,7 @@
 #if defined (HAVE_HDF5)
 
   hid_t save_type_hid = save_type;
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -537,7 +533,7 @@
 
   T m (dv);
   if (H5Dread (data_hid, save_type_hid, octave_H5S_ALL, octave_H5S_ALL,
-               octave_H5P_DEFAULT, m.fortran_vec ()) >= 0)
+               octave_H5P_DEFAULT, m.rwdata ()) >= 0)
     {
       retval = true;
       this->m_matrix = m;
@@ -578,8 +574,8 @@
 
   val_type ival = tmp.value ();
 
-  static const bool is_signed = std::numeric_limits<val_type>::is_signed;
-  static const bool can_be_larger_than_uchar_max
+  static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;
+  static constexpr bool can_be_larger_than_uchar_max
     = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
 
   if (octave_base_int_helper<val_type, is_signed,
--- a/libinterp/octave-value/ov-base-int.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-int.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,10 +44,17 @@
 
 // base int matrix values.
 
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<int8NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<int16NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<int32NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<int64NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<uint8NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<uint16NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<uint32NDArray>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<uint64NDArray>;
+
 template <typename T>
-class
-OCTINTERP_API
-octave_base_int_matrix : public octave_base_matrix<T>
+class OCTINTERP_TEMPLATE_API octave_base_int_matrix : public octave_base_matrix<T>
 {
 public:
 
@@ -65,7 +72,7 @@
 
   OCTINTERP_API octave_base_value * try_narrowing_conversion ();
 
-  bool isreal () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool isreal () const { return true; }
 
   //  void increment () { matrix += 1; }
 
@@ -116,31 +123,45 @@
 
 // base int scalar values.
 
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_int8>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_int16>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_int32>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_int64>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_uint8>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_uint16>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_uint32>;
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<octave_uint64>;
+
 template <typename T>
-class
-OCTINTERP_API
-octave_base_int_scalar : public octave_base_scalar<T>
+class OCTINTERP_TEMPLATE_API octave_base_int_scalar : public octave_base_scalar<T>
 {
 public:
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_base_int_scalar () : octave_base_scalar<T> () { }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_base_int_scalar (const T& s) : octave_base_scalar<T> (s) { }
 
-  ~octave_base_int_scalar () = default;
+  OCTINTERP_OVERRIDABLE_FUNC_API ~octave_base_int_scalar () = default;
 
-  octave_base_value * clone () const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value * clone () const
   { return new octave_base_int_scalar (*this); }
-  octave_base_value * empty_clone () const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value * empty_clone () const
   { return new octave_base_int_scalar (); }
 
-  octave_base_value * try_narrowing_conversion () { return nullptr; }
-
-  bool is_maybe_function () const { return false; }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_value *
+  try_narrowing_conversion ()
+  { return nullptr; }
 
-  bool isreal () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_maybe_function () const
+  { return false; }
 
-  bool is_real_scalar () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool isreal () const
+  { return true; }
+
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_real_scalar () const
+  { return true; }
 
   //  void increment () { scalar += 1; }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-base-mat-inst.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,129 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2024 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-base-mat.cc"
+
+// instantiate template class with types that need to be exported from library
+
+template class OCTINTERP_API octave_base_matrix<boolNDArray>;
+template class OCTINTERP_API octave_base_matrix<charNDArray>;
+template class OCTINTERP_API octave_base_matrix<int8NDArray>;
+template class OCTINTERP_API octave_base_matrix<int16NDArray>;
+template class OCTINTERP_API octave_base_matrix<int32NDArray>;
+template class OCTINTERP_API octave_base_matrix<int64NDArray>;
+template class OCTINTERP_API octave_base_matrix<uint8NDArray>;
+template class OCTINTERP_API octave_base_matrix<uint16NDArray>;
+template class OCTINTERP_API octave_base_matrix<uint32NDArray>;
+template class OCTINTERP_API octave_base_matrix<uint64NDArray>;
+template class OCTINTERP_API octave_base_matrix<ComplexNDArray>;
+template class OCTINTERP_API octave_base_matrix<FloatComplexNDArray>;
+template class OCTINTERP_API octave_base_matrix<FloatNDArray>;
+template class OCTINTERP_API octave_base_matrix<NDArray>;
+
+
+// Cell is able to handle octave_value indexing by itself, so just forward
+// everything.
+
+template <>
+octave_value
+octave_base_matrix<Cell>::do_index_op (const octave_value_list& idx,
+                                       bool resize_ok)
+{
+  return m_matrix.index (idx, resize_ok);
+}
+
+template <>
+void
+octave_base_matrix<Cell>::assign (const octave_value_list& idx, const Cell& rhs)
+{
+  m_matrix.assign (idx, rhs);
+}
+
+template <>
+void
+octave_base_matrix<Cell>::assign (const octave_value_list& idx,
+                                  octave_value rhs)
+{
+  // FIXME: Really?
+  if (rhs.iscell ())
+    m_matrix.assign (idx, rhs.cell_value ());
+  else
+    m_matrix.assign (idx, Cell (rhs));
+}
+
+template <>
+void
+octave_base_matrix<Cell>::delete_elements (const octave_value_list& idx)
+{
+  m_matrix.delete_elements (idx);
+}
+
+// FIXME: this list of specializations is becoming so long that we should
+// really ask whether octave_cell should inherit from octave_base_matrix at all.
+
+template <>
+std::string
+octave_base_matrix<Cell>::edit_display (const float_display_format&,
+                                        octave_idx_type i,
+                                        octave_idx_type j) const
+{
+  octave_value val = m_matrix(i, j);
+
+  std::string tname = val.type_name ();
+  dim_vector dv = val.dims ();
+  std::string dimstr = dv.str ();
+  return "[" + dimstr + " " + tname + "]";
+}
+
+template <>
+octave_value
+octave_base_matrix<Cell>::fast_elem_extract (octave_idx_type n) const
+{
+  if (n < m_matrix.numel ())
+    return Cell (m_matrix(n));
+  else
+    return octave_value ();
+}
+
+template <>
+bool
+octave_base_matrix<Cell>::fast_elem_insert (octave_idx_type n,
+                                            const octave_value& x)
+{
+  const octave_base_matrix<Cell> *xrep
+    = dynamic_cast<const octave_base_matrix<Cell> *> (&x.get_rep ());
+
+  bool retval = xrep && xrep->m_matrix.numel () == 1 && n < m_matrix.numel ();
+  if (retval)
+    m_matrix(n) = xrep->m_matrix(0);
+
+  return retval;
+}
+
+template class OCTINTERP_API octave_base_matrix<Cell>;
--- a/libinterp/octave-value/ov-base-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -60,7 +60,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_matrix<T>::simple_subsref - please report this bug");
     }
 }
 
@@ -86,7 +86,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unpexpected: index not '(', '{', or '.' in - octave_base_matrix<MT>::subsref please report this bug");
     }
 
   return retval.next_subsref (type, idx);
@@ -145,7 +145,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unpexpected: index not '(', '{', or '.' in - octave_base_matrix<MT>::subsasgn please report this bug");
     }
 
   return retval;
@@ -260,7 +260,7 @@
       switch (n_idx)
         {
         case 0:
-          panic_impossible ();
+          error ("unexpected: zero indices in octave_base_matrix<MT>::assign - please report this bug");
           break;
 
         case 1:
@@ -323,8 +323,6 @@
 
   int nd = m_matrix.ndims ();
 
-  MT mrhs (dim_vector (1, 1), rhs);
-
   // If we catch an indexing error in index_vector, we flag an error in
   // index k.  Ensure it is the right value before each idx_vector call.
   // Same variable as used in the for loop in the default case.
@@ -336,7 +334,7 @@
       switch (n_idx)
         {
         case 0:
-          panic_impossible ();
+          error ("unexpected: zero indices in octave_base_matrix<MT>::assign - please report this bug");
           break;
 
         case 1:
@@ -347,7 +345,10 @@
             if (i.is_scalar () && i(0) < m_matrix.numel ())
               m_matrix(i(0)) = rhs;
             else
-              m_matrix.assign (i, mrhs);
+              {
+                MT mrhs (dim_vector (1, 1), rhs);
+                m_matrix.assign (i, mrhs);
+              }
           }
           break;
 
@@ -363,7 +364,10 @@
                 && i(0) < m_matrix.rows () && j(0) < m_matrix.columns ())
               m_matrix(i(0), j(0)) = rhs;
             else
-              m_matrix.assign (i, j, mrhs);
+              {
+                MT mrhs (dim_vector (1, 1), rhs);
+                m_matrix.assign (i, j, mrhs);
+              }
           }
           break;
 
@@ -395,7 +399,10 @@
                 m_matrix(j) = rhs;
               }
             else
-              m_matrix.assign (idx_vec, mrhs);
+              {
+                MT mrhs (dim_vector (1, 1), rhs);
+                m_matrix.assign (idx_vec, mrhs);
+              }
           }
           break;
         }
@@ -446,7 +453,7 @@
 octave_base_matrix<MT>::is_true () const
 {
   bool retval = false;
-  dim_vector dv = m_matrix.dims ();
+  const dim_vector& dv = m_matrix.dims ();
   int nel = dv.numel ();
 
   if (nel > 0)
@@ -471,7 +478,7 @@
 bool
 octave_base_matrix<MT>::print_as_scalar () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   return (dv.all_ones () || dv.any_zero ());
 }
--- a/libinterp/octave-value/ov-base-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,17 +45,17 @@
 // Real matrix values.
 
 template <typename MT>
-class
-OCTINTERP_API
-octave_base_matrix : public octave_base_value
+class OCTINTERP_TEMPLATE_API octave_base_matrix : public octave_base_value
 {
 public:
 
   typedef MT object_type;
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_base_matrix ()
     : octave_base_value (), m_matrix (), m_typ (), m_idx_cache () { }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_base_matrix (const MT& m, const MatrixType& t = MatrixType ())
     : octave_base_value (), m_matrix (m),
       m_typ (t.is_known () ? new MatrixType (t) : nullptr), m_idx_cache ()
@@ -64,6 +64,7 @@
       m_matrix.resize (dim_vector (0, 0));
   }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_base_matrix (const octave_base_matrix& m)
     : octave_base_value (), m_matrix (m.m_matrix),
       m_typ (m.m_typ ? new MatrixType (*m.m_typ) : nullptr),
@@ -71,14 +72,19 @@
                    : nullptr)
   { }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   ~octave_base_matrix () { clear_cached_info (); }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   std::size_t byte_size () const { return m_matrix.byte_size (); }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_value squeeze () const { return MT (m_matrix.squeeze ()); }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   octave_value full_value () const { return m_matrix; }
 
+  OCTINTERP_OVERRIDABLE_FUNC_API
   void maybe_economize () { m_matrix.maybe_economize (); }
 
   // We don't need to override all three forms of subsref.  The using
@@ -89,11 +95,11 @@
   OCTINTERP_API octave_value
   subsref (const std::string& type, const std::list<octave_value_list>& idx);
 
-  octave_value_list
+  OCTINTERP_API 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)
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx, int)
   { return subsref (type, idx); }
 
   OCTINTERP_API octave_value
@@ -117,58 +123,76 @@
 
   OCTINTERP_API void delete_elements (const octave_value_list& idx);
 
-  dim_vector dims () const { return m_matrix.dims (); }
+  OCTINTERP_OVERRIDABLE_FUNC_API dim_vector
+  dims () const { return m_matrix.dims (); }
 
-  octave_idx_type numel () const { return m_matrix.numel (); }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type
+  numel () const { return m_matrix.numel (); }
 
-  int ndims () const { return m_matrix.ndims (); }
+  OCTINTERP_OVERRIDABLE_FUNC_API int
+  ndims () const { return m_matrix.ndims (); }
 
-  octave_idx_type nnz () const { return m_matrix.nnz (); }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type
+  nnz () const { return m_matrix.nnz (); }
 
-  octave_value reshape (const dim_vector& new_dims) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  reshape (const dim_vector& new_dims) const
   { return MT (m_matrix.reshape (new_dims)); }
 
-  octave_value permute (const Array<int>& vec, bool inv = false) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  permute (const Array<int>& vec, bool inv = false) const
   { return MT (m_matrix.permute (vec, inv)); }
 
-  octave_value resize (const dim_vector& dv, bool fill = false) const;
-
-  octave_value all (int dim = 0) const { return m_matrix.all (dim); }
-  octave_value any (int dim = 0) const { return m_matrix.any (dim); }
+  OCTINTERP_API octave_value
+  resize (const dim_vector& dv, bool fill = false) const;
 
-  MatrixType matrix_type () const { return m_typ ? *m_typ : MatrixType (); }
-  MatrixType matrix_type (const MatrixType& _typ) const;
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value all (int dim = 0) const
+  { return m_matrix.all (dim); }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value any (int dim = 0) const
+  { return m_matrix.any (dim); }
 
-  octave_value diag (octave_idx_type k = 0) const
+  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType matrix_type () const
+  { return m_typ ? *m_typ : MatrixType (); }
+  OCTINTERP_API MatrixType matrix_type (const MatrixType& _typ) const;
+
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  diag (octave_idx_type k = 0) const
   { return octave_value (m_matrix.diag (k)); }
 
-  octave_value diag (octave_idx_type m, octave_idx_type n) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  diag (octave_idx_type m, octave_idx_type n) const
   { return octave_value (m_matrix.diag (m, n)); }
 
-  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
   { return octave_value (m_matrix.sort (dim, mode)); }
-  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
-                     sortmode mode = ASCENDING) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
+        sortmode mode = ASCENDING) const
   { return octave_value (m_matrix.sort (sidx, dim, mode)); }
 
-  sortmode issorted (sortmode mode = UNSORTED) const
+  OCTINTERP_OVERRIDABLE_FUNC_API sortmode issorted (sortmode mode = UNSORTED) const
   { return m_matrix.issorted (mode); }
 
-  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const
+  OCTINTERP_OVERRIDABLE_FUNC_API Array<octave_idx_type>
+  sort_rows_idx (sortmode mode = ASCENDING) const
   { return m_matrix.sort_rows_idx (mode); }
 
-  sortmode is_sorted_rows (sortmode mode = UNSORTED) const
+  OCTINTERP_OVERRIDABLE_FUNC_API sortmode
+  is_sorted_rows (sortmode mode = UNSORTED) const
   { return m_matrix.is_sorted_rows (mode); }
 
-  bool is_matrix_type () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool
+  is_matrix_type () const { return true; }
 
-  bool is_full_num_matrix () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool
+  is_full_num_matrix () const { return true; }
 
-  bool isnumeric () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool isnumeric () const { return true; }
 
-  bool is_defined () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }
 
-  bool is_constant () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }
 
   OCTINTERP_API bool is_true () const;
 
@@ -187,13 +211,13 @@
   edit_display (const float_display_format& fmt,
                 octave_idx_type i, octave_idx_type j) const;
 
-  MT& matrix_ref ()
+  OCTINTERP_OVERRIDABLE_FUNC_API MT& matrix_ref ()
   {
     clear_cached_info ();
     return m_matrix;
   }
 
-  const MT& matrix_ref () const
+  OCTINTERP_OVERRIDABLE_FUNC_API const MT& matrix_ref () const
   {
     return m_matrix;
   }
@@ -206,20 +230,22 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data () const { return m_matrix.data (); }
+  OCTINTERP_OVERRIDABLE_FUNC_API const void *
+  mex_get_data () const { return m_matrix.data (); }
 
 protected:
 
   MT m_matrix;
 
-  octave::idx_vector set_idx_cache (const octave::idx_vector& idx) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave::idx_vector
+  set_idx_cache (const octave::idx_vector& idx) const
   {
     delete m_idx_cache;
     m_idx_cache = new octave::idx_vector (idx);
     return idx;
   }
 
-  void clear_cached_info () const
+  OCTINTERP_OVERRIDABLE_FUNC_API void clear_cached_info () const
   {
     delete m_typ; m_typ = nullptr;
     delete m_idx_cache; m_idx_cache = nullptr;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/octave-value/ov-base-scalar-inst.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,46 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2024 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-base-scalar.cc"
+
+// instantiate template class with types that need to be exported from library
+
+template class OCTINTERP_API octave_base_scalar<bool>;
+template class OCTINTERP_API octave_base_scalar<double>;
+template class OCTINTERP_API octave_base_scalar<float>;
+template class OCTINTERP_API octave_base_scalar<Complex>;
+template class OCTINTERP_API octave_base_scalar<FloatComplex>;
+template class OCTINTERP_API octave_base_scalar<octave_int8>;
+template class OCTINTERP_API octave_base_scalar<octave_int16>;
+template class OCTINTERP_API octave_base_scalar<octave_int32>;
+template class OCTINTERP_API octave_base_scalar<octave_int64>;
+template class OCTINTERP_API octave_base_scalar<octave_uint8>;
+template class OCTINTERP_API octave_base_scalar<octave_uint16>;
+template class OCTINTERP_API octave_base_scalar<octave_uint32>;
+template class OCTINTERP_API octave_base_scalar<octave_uint64>;
--- a/libinterp/octave-value/ov-base-scalar.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-scalar.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -61,7 +61,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_scalar<T>::subsref - please report this bug");
     }
 
   return retval.next_subsref (type, idx);
@@ -99,7 +99,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_scalar<T>::subsasgn - please report this bug");
     }
 
   return retval;
--- a/libinterp/octave-value/ov-base-scalar.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-scalar.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,28 +44,28 @@
 // Real scalar values.
 
 template <typename ST>
-class
-OCTINTERP_API
-octave_base_scalar : public octave_base_value
+class OCTINTERP_API octave_base_scalar : public octave_base_value
 {
 public:
 
   typedef ST scalar_type;
 
-  octave_base_scalar ()
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar ()
     : octave_base_value (), scalar () { }
 
-  octave_base_scalar (const ST& s)
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar (const ST& s)
     : octave_base_value (), scalar (s) { }
 
-  octave_base_scalar (const octave_base_scalar& s)
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_base_scalar (const octave_base_scalar& s)
     : octave_base_value (), scalar (s.scalar) { }
 
-  ~octave_base_scalar () = default;
+  OCTINTERP_OVERRIDABLE_FUNC_API ~octave_base_scalar () = default;
 
-  octave_value squeeze () const { return scalar; }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  squeeze () const { return scalar; }
 
-  octave_value full_value () const { return scalar; }
+  OCTINTERP_OVERRIDABLE_FUNC_API 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
@@ -75,71 +75,87 @@
   OCTINTERP_API octave_value
   subsref (const std::string& type, const std::list<octave_value_list>& idx);
 
-  octave_value_list subsref (const std::string& type,
-                             const std::list<octave_value_list>& idx, int)
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value_list
+  subsref (const std::string& type, const std::list<octave_value_list>& idx, int)
   { return subsref (type, idx); }
 
   OCTINTERP_API octave_value
   subsasgn (const std::string& type, const std::list<octave_value_list>& idx,
             const octave_value& rhs);
 
-  bool is_constant () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_constant () const { return true; }
 
-  bool is_defined () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool is_defined () const { return true; }
 
   OCTINTERP_API dim_vector dims () const;
 
-  octave_idx_type numel () const { return 1; }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_idx_type numel () const { return 1; }
 
-  int ndims () const { return 2; }
+  OCTINTERP_OVERRIDABLE_FUNC_API int ndims () const { return 2; }
 
-  octave_idx_type nnz () const { return (scalar != ST () ? 1 : 0); }
+  OCTINTERP_OVERRIDABLE_FUNC_API 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 () const { return sizeof (ST); }
+  OCTINTERP_OVERRIDABLE_FUNC_API std::size_t
+  byte_size () const { return sizeof (ST); }
 
-  octave_value all (int = 0) const { return (scalar != ST ()); }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  all (int = 0) const { return (scalar != ST ()); }
 
-  octave_value any (int = 0) const { return (scalar != ST ()); }
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  any (int = 0) const { return (scalar != ST ()); }
 
   OCTINTERP_API octave_value diag (octave_idx_type k = 0) const;
 
   OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  octave_value sort (octave_idx_type, sortmode) const
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  sort (octave_idx_type, sortmode) const
   { return octave_value (scalar); }
-  octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type,
-                     sortmode) const
+
+  OCTINTERP_OVERRIDABLE_FUNC_API octave_value
+  sort (Array<octave_idx_type>& sidx, octave_idx_type, sortmode) const
   {
     sidx.resize (dim_vector (1, 1));
     sidx(0) = 0;
     return octave_value (scalar);
   }
 
-  sortmode issorted (sortmode mode = UNSORTED) const
+  OCTINTERP_OVERRIDABLE_FUNC_API sortmode
+  issorted (sortmode mode = UNSORTED) const
   { return mode == UNSORTED ? ASCENDING : mode; }
 
-  Array<octave_idx_type> sort_rows_idx (sortmode) const
+  OCTINTERP_OVERRIDABLE_FUNC_API Array<octave_idx_type>
+  sort_rows_idx (sortmode) const
   {
     return Array<octave_idx_type> (dim_vector (1, 1),
                                    static_cast<octave_idx_type> (0));
   }
 
-  sortmode is_sorted_rows (sortmode mode = UNSORTED) const
+  OCTINTERP_OVERRIDABLE_FUNC_API sortmode
+  is_sorted_rows (sortmode mode = UNSORTED) const
   { return mode == UNSORTED ? ASCENDING : mode; }
 
-  MatrixType matrix_type () const { return MatrixType::Diagonal; }
-  MatrixType matrix_type (const MatrixType&) const
+  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType
+  matrix_type () const
+  { return MatrixType::Diagonal; }
+
+  OCTINTERP_OVERRIDABLE_FUNC_API MatrixType
+  matrix_type (const MatrixType&) const
   { return matrix_type (); }
 
-  bool is_maybe_function () const { return false; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool
+  is_maybe_function () const { return false; }
 
-  bool is_scalar_type () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool
+  is_scalar_type () const { return true; }
 
-  bool isnumeric () const { return true; }
+  OCTINTERP_OVERRIDABLE_FUNC_API bool
+  isnumeric () const { return true; }
 
   OCTINTERP_API bool is_true () const;
 
@@ -161,11 +177,14 @@
 
   // This function exists to support the MEX interface.
   // You should not use it anywhere else.
-  const void * mex_get_data () const { return &scalar; }
+  OCTINTERP_OVERRIDABLE_FUNC_API const void *
+  mex_get_data () const { return &scalar; }
 
-  const ST& scalar_ref () const { return scalar; }
+  OCTINTERP_OVERRIDABLE_FUNC_API const ST& scalar_ref () const
+  { return scalar; }
 
-  ST& scalar_ref () { return scalar; }
+  OCTINTERP_OVERRIDABLE_FUNC_API ST& scalar_ref ()
+  { return scalar; }
 
   OCTINTERP_API octave_value fast_elem_extract (octave_idx_type n) const;
 
--- a/libinterp/octave-value/ov-base-sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -128,7 +128,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_sparse<T>::subsref - please report this bug");
     }
 
   return retval.next_subsref (type, idx);
@@ -173,7 +173,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_base_sparse<T>::subsasgn - please report this bug");
     }
 
   return retval;
@@ -245,7 +245,7 @@
 octave_base_sparse<T>::is_true () const
 {
   bool retval = false;
-  dim_vector dv = matrix.dims ();
+  const dim_vector& dv = matrix.dims ();
   octave_idx_type nel = dv.numel ();
   octave_idx_type nz = nnz ();
 
@@ -274,7 +274,7 @@
 bool
 octave_base_sparse<T>::print_as_scalar () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   return (dv.all_ones () || dv.any_zero ());
 }
@@ -400,7 +400,7 @@
 bool
 octave_base_sparse<T>::save_ascii (std::ostream& os)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
 
   // Ensure that additional memory is deallocated
   matrix.maybe_compress ();
--- a/libinterp/octave-value/ov-base-sparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base-sparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -46,9 +46,7 @@
 class octave_sparse_bool_matrix;
 
 template <typename T>
-class
-OCTINTERP_API
-octave_base_sparse : public octave_base_value
+class OCTINTERP_API octave_base_sparse : public octave_base_value
 {
 public:
 
--- a/libinterp/octave-value/ov-base.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -100,9 +100,6 @@
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value,
                                      "<unknown type>", "unknown");
 
-// 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
@@ -343,7 +340,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in octave_base_value::subsasgn - please report this bug");
         }
     }
   else
@@ -532,8 +529,8 @@
         err_wrong_type_arg (ee, "octave_base_value::" #F "_value ()", type_name ()); \
       }                                                                 \
                                                                         \
-    static const double out_of_range_top                                \
-      = static_cast<double> (std::numeric_limits<T>::max ()) + 1.;      \
+    static constexpr double out_of_range_top                            \
+      = static_cast<double> (std::numeric_limits<T>::max ()) + 1.0;     \
     if (require_int && octave::math::x_nint (d) != d)                   \
       error_with_cfn ("conversion of %g to " #T " value failed", d);    \
     else if (d < std::numeric_limits<T>::min ())                        \
@@ -1507,7 +1504,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in make_idx_args - please report this bug");
           break;
         }
     }
--- a/libinterp/octave-value/ov-base.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-base.h	Fri Apr 12 15:10:26 2024 +0200
@@ -179,12 +179,19 @@
 #define OCTAVE_EMPTY_CPP_ARG /* empty */
 
 #define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA                          \
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG)
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG,        \
+                                         OCTAVE_EMPTY_CPP_ARG)
+
+#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API(API)                 \
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (OCTAVE_EMPTY_CPP_ARG, API)
 
 #define DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA                     \
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(virtual)
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (virtual, OCTAVE_EMPTY_CPP_ARG)
 
-#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(VIRTUAL)                \
+#define DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA_API(API)            \
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2 (virtual, API)
+
+#define DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA2(VIRTUAL, API)           \
   public:                                                             \
     VIRTUAL int type_id () const { return s_t_id; }                   \
     VIRTUAL std::string type_name () const { return s_t_name; }       \
@@ -192,20 +199,24 @@
     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&);                   \
+    API static void register_type ();                                 \
+    API static void register_type (octave::type_info&);               \
                                                                       \
   private:                                                            \
-    static int s_t_id;                                                \
-    static const std::string s_t_name;                                \
-    static const std::string s_c_name;
+    static API int s_t_id;                                            \
+    static API const std::string s_t_name;                            \
+    static API const std::string s_c_name;
 
 #define DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS(cls, type)         \
-  template <> void cls<type>::register_type ();                       \
-  template <> void cls<type>::register_type (octave::type_info&);     \
-  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;
+  DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API (cls, type,          \
+                                                  OCTAVE_EMPTY_CPP_ARG)
+
+#define DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API(cls, type, API) \
+  template <> API void cls<type>::register_type ();                   \
+  template <> API void cls<type>::register_type (octave::type_info&); \
+  template <> API int cls<type>::s_t_id;                              \
+  template <> API const std::string cls<type>::s_t_name;              \
+  template <> API const std::string cls<type>::s_c_name;
 
 // FIXME: The 'new' operator below creates an 8-byte memory leak for every
 // registered data type (of which there are 58 built-in to Octave, plus any
@@ -239,9 +250,7 @@
 // they need (if they are derived from octave_base_value instead of
 // octave_value).
 
-class
-OCTINTERP_API
-octave_base_value
+class OCTINTERP_API octave_base_value
 {
 public:
 
@@ -268,7 +277,7 @@
 
   friend class octave_value;
 
-  octave_base_value ();
+  OCTINTERP_API octave_base_value ();
 
   octave_base_value (const octave_base_value&) : octave_base_value () { }
 
@@ -279,7 +288,7 @@
   clone () const { return new octave_base_value (*this); }
 
   // Empty clone.
-  virtual octave_base_value *
+  virtual OCTINTERP_API octave_base_value *
   empty_clone () const;
 
   // Unique clone.  Usually clones, but may be overridden to fake the
@@ -298,76 +307,77 @@
   numeric_demotion_function () const
   { return type_conv_info (); }
 
-  virtual octave_value squeeze () const;
+  virtual OCTINTERP_API octave_value squeeze () const;
 
-  virtual octave_value full_value () const;
+  virtual OCTINTERP_API octave_value full_value () 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 ();
+  virtual OCTINTERP_API octave_value as_double_or_copy ();
 
-  virtual octave_value as_double () const;
-  virtual octave_value as_single () const;
+  virtual OCTINTERP_API octave_value as_double () const;
+  virtual OCTINTERP_API octave_value as_single () 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 OCTINTERP_API octave_value as_int8 () const;
+  virtual OCTINTERP_API octave_value as_int16 () const;
+  virtual OCTINTERP_API octave_value as_int32 () const;
+  virtual OCTINTERP_API octave_value as_int64 () 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 OCTINTERP_API octave_value as_uint8 () const;
+  virtual OCTINTERP_API octave_value as_uint16 () const;
+  virtual OCTINTERP_API octave_value as_uint32 () const;
+  virtual OCTINTERP_API octave_value as_uint64 () const;
 
   virtual octave_base_value * try_narrowing_conversion ()
   { return nullptr; }
 
   virtual void maybe_economize () { }
 
-  virtual Matrix size ();
+  virtual OCTINTERP_API Matrix size ();
 
-  virtual octave_idx_type xnumel (const octave_value_list&);
+  virtual OCTINTERP_API octave_idx_type xnumel (const octave_value_list&);
 
   // FIXME: Do we really need all three of these versions of subsref?
 
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   subsref (const std::string& type,
            const std::list<octave_value_list>& idx);
 
-  virtual octave_value_list
+  virtual OCTINTERP_API octave_value_list
   subsref (const std::string& type,
            const std::list<octave_value_list>& idx,
            int nargout);
 
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   subsref (const std::string& type,
            const std::list<octave_value_list>& idx,
            bool auto_add);
 
-  virtual octave_value_list
+  virtual OCTINTERP_API octave_value_list
   simple_subsref (char type, octave_value_list& idx, int nargout);
 
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   do_index_op (const octave_value_list& idx, bool resize_ok = false);
 
   virtual void assign (const std::string&, const octave_value&) { }
 
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   subsasgn (const std::string& type,
             const std::list<octave_value_list>& idx,
             const octave_value& rhs);
 
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   simple_subsasgn (char type, octave_value_list& idx,
                    const octave_value& rhs);
 
-  virtual octave_value
+  virtual OCTINTERP_API 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 OCTINTERP_API octave::idx_vector
+  index_vector (bool require_integers = false) const;
 
   virtual dim_vector dims () const { return dim_vector (); }
 
@@ -392,21 +402,23 @@
 
   virtual std::size_t byte_size () const { return 0; }
 
-  virtual octave_idx_type nnz () const;
+  virtual OCTINTERP_API octave_idx_type nnz () const;
 
-  virtual octave_idx_type nzmax () const;
+  virtual OCTINTERP_API octave_idx_type nzmax () const;
 
-  virtual octave_idx_type nfields () const;
+  virtual OCTINTERP_API octave_idx_type nfields () const;
 
-  virtual octave_value reshape (const dim_vector&) const;
+  virtual OCTINTERP_API octave_value reshape (const dim_vector&) const;
 
-  virtual octave_value permute (const Array<int>& vec, bool = false) const;
-
-  virtual octave_value resize (const dim_vector&, bool fill = false) const;
+  virtual OCTINTERP_API octave_value
+  permute (const Array<int>& vec, bool = false) const;
 
-  virtual MatrixType matrix_type () const;
+  virtual OCTINTERP_API octave_value
+  resize (const dim_vector&, bool fill = false) const;
 
-  virtual MatrixType matrix_type (const MatrixType& typ) const;
+  virtual OCTINTERP_API MatrixType matrix_type () const;
+
+  virtual OCTINTERP_API MatrixType matrix_type (const MatrixType& typ) const;
 
   virtual bool is_defined () const { return false; }
 
@@ -466,9 +478,9 @@
 
   virtual bool is_all_va_args () const { return false; }
 
-  virtual octave_value all (int = 0) const;
+  virtual OCTINTERP_API octave_value all (int = 0) const;
 
-  virtual octave_value any (int = 0) const;
+  virtual OCTINTERP_API octave_value any (int = 0) const;
 
   virtual builtin_type_t builtin_type () const { return btyp_unknown; }
 
@@ -557,27 +569,33 @@
 
   virtual void erase_subfunctions () { }
 
-  virtual short int short_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API short int
+  short_value (bool = false, bool = false) const;
 
-  virtual unsigned short int ushort_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API unsigned short int
+  ushort_value (bool = false, bool = false) const;
 
-  virtual int int_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API int
+  int_value (bool = false, bool = false) const;
 
-  virtual unsigned int uint_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API unsigned int
+  uint_value (bool = false, bool = false) const;
 
-  virtual int nint_value (bool = false) const;
+  virtual OCTINTERP_API int nint_value (bool = false) const;
 
-  virtual long int long_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API long int
+  long_value (bool = false, bool = false) const;
 
-  virtual unsigned long int ulong_value (bool = false, bool = false) const;
-
-  virtual int64_t int64_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API unsigned long int
+  ulong_value (bool = false, bool = false) const;
 
-  virtual uint64_t uint64_value (bool = false, bool = false) const;
+  virtual OCTINTERP_API int64_t int64_value (bool = false, bool = false) const;
+
+  virtual OCTINTERP_API uint64_t uint64_value (bool = false, bool = false) const;
 
-  virtual double double_value (bool = false) const;
+  virtual OCTINTERP_API double double_value (bool = false) const;
 
-  virtual float float_value (bool = false) const;
+  virtual OCTINTERP_API float float_value (bool = false) const;
 
   virtual double scalar_value (bool frc_str_conv = false) const
   { return double_value (frc_str_conv); }
@@ -585,110 +603,110 @@
   virtual float float_scalar_value (bool frc_str_conv = false) const
   { return float_value (frc_str_conv); }
 
-  virtual Cell cell_value () const;
+  virtual OCTINTERP_API Cell cell_value () const;
 
-  virtual Matrix matrix_value (bool = false) const;
+  virtual OCTINTERP_API Matrix matrix_value (bool = false) const;
 
-  virtual FloatMatrix float_matrix_value (bool = false) const;
+  virtual OCTINTERP_API FloatMatrix float_matrix_value (bool = false) const;
 
-  virtual NDArray array_value (bool = false) const;
+  virtual OCTINTERP_API NDArray array_value (bool = false) const;
 
-  virtual FloatNDArray float_array_value (bool = false) const;
+  virtual OCTINTERP_API FloatNDArray float_array_value (bool = false) const;
 
-  virtual Complex complex_value (bool = false) const;
+  virtual OCTINTERP_API Complex complex_value (bool = false) const;
 
-  virtual FloatComplex float_complex_value (bool = false) const;
+  virtual OCTINTERP_API FloatComplex float_complex_value (bool = false) const;
 
-  virtual ComplexMatrix complex_matrix_value (bool = false) const;
+  virtual OCTINTERP_API ComplexMatrix complex_matrix_value (bool = false) const;
 
-  virtual FloatComplexMatrix float_complex_matrix_value (bool = false) const;
+  virtual OCTINTERP_API FloatComplexMatrix float_complex_matrix_value (bool = false) const;
 
-  virtual ComplexNDArray complex_array_value (bool = false) const;
+  virtual OCTINTERP_API ComplexNDArray complex_array_value (bool = false) const;
 
-  virtual FloatComplexNDArray float_complex_array_value (bool = false) const;
+  virtual OCTINTERP_API FloatComplexNDArray float_complex_array_value (bool = false) const;
 
-  virtual bool bool_value (bool = false) const;
+  virtual OCTINTERP_API bool bool_value (bool = false) const;
 
-  virtual boolMatrix bool_matrix_value (bool = false) const;
+  virtual OCTINTERP_API boolMatrix bool_matrix_value (bool = false) const;
 
-  virtual boolNDArray bool_array_value (bool = false) const;
+  virtual OCTINTERP_API boolNDArray bool_array_value (bool = false) const;
 
-  virtual charMatrix char_matrix_value (bool force = false) const;
+  virtual OCTINTERP_API charMatrix char_matrix_value (bool force = false) const;
 
-  virtual charNDArray char_array_value (bool = false) const;
+  virtual OCTINTERP_API charNDArray char_array_value (bool = false) const;
 
-  virtual SparseMatrix sparse_matrix_value (bool = false) const;
+  virtual OCTINTERP_API SparseMatrix sparse_matrix_value (bool = false) const;
 
-  virtual SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
+  virtual OCTINTERP_API SparseComplexMatrix sparse_complex_matrix_value (bool = false) const;
 
-  virtual SparseBoolMatrix sparse_bool_matrix_value (bool = false) const;
+  virtual OCTINTERP_API SparseBoolMatrix sparse_bool_matrix_value (bool = false) const;
 
-  virtual DiagMatrix diag_matrix_value (bool = false) const;
+  virtual OCTINTERP_API DiagMatrix diag_matrix_value (bool = false) const;
 
-  virtual FloatDiagMatrix float_diag_matrix_value (bool = false) const;
+  virtual OCTINTERP_API FloatDiagMatrix float_diag_matrix_value (bool = false) const;
 
-  virtual ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
+  virtual OCTINTERP_API ComplexDiagMatrix complex_diag_matrix_value (bool = false) const;
 
-  virtual FloatComplexDiagMatrix
+  virtual OCTINTERP_API FloatComplexDiagMatrix
   float_complex_diag_matrix_value (bool = false) const;
 
-  virtual PermMatrix perm_matrix_value () const;
+  virtual OCTINTERP_API PermMatrix perm_matrix_value () const;
 
-  virtual octave_int8 int8_scalar_value () const;
+  virtual OCTINTERP_API octave_int8 int8_scalar_value () const;
 
-  virtual octave_int16 int16_scalar_value () const;
+  virtual OCTINTERP_API octave_int16 int16_scalar_value () const;
 
-  virtual octave_int32 int32_scalar_value () const;
+  virtual OCTINTERP_API octave_int32 int32_scalar_value () const;
 
-  virtual octave_int64 int64_scalar_value () const;
+  virtual OCTINTERP_API octave_int64 int64_scalar_value () const;
 
-  virtual octave_uint8 uint8_scalar_value () const;
+  virtual OCTINTERP_API octave_uint8 uint8_scalar_value () const;
 
-  virtual octave_uint16 uint16_scalar_value () const;
+  virtual OCTINTERP_API octave_uint16 uint16_scalar_value () const;
 
-  virtual octave_uint32 uint32_scalar_value () const;
+  virtual OCTINTERP_API octave_uint32 uint32_scalar_value () const;
 
-  virtual octave_uint64 uint64_scalar_value () const;
+  virtual OCTINTERP_API octave_uint64 uint64_scalar_value () const;
 
-  virtual int8NDArray int8_array_value () const;
+  virtual OCTINTERP_API int8NDArray int8_array_value () const;
 
-  virtual int16NDArray int16_array_value () const;
+  virtual OCTINTERP_API int16NDArray int16_array_value () const;
 
-  virtual int32NDArray int32_array_value () const;
+  virtual OCTINTERP_API int32NDArray int32_array_value () const;
 
-  virtual int64NDArray int64_array_value () const;
+  virtual OCTINTERP_API int64NDArray int64_array_value () const;
 
-  virtual uint8NDArray uint8_array_value () const;
+  virtual OCTINTERP_API uint8NDArray uint8_array_value () const;
 
-  virtual uint16NDArray uint16_array_value () const;
+  virtual OCTINTERP_API uint16NDArray uint16_array_value () const;
 
-  virtual uint32NDArray uint32_array_value () const;
+  virtual OCTINTERP_API uint32NDArray uint32_array_value () const;
 
-  virtual uint64NDArray uint64_array_value () const;
+  virtual OCTINTERP_API uint64NDArray uint64_array_value () const;
 
-  virtual string_vector string_vector_value (bool pad = false) const;
+  virtual OCTINTERP_API string_vector string_vector_value (bool pad = false) const;
 
-  virtual std::string string_value (bool force = false) const;
+  virtual OCTINTERP_API std::string string_value (bool force = false) const;
 
-  virtual Array<std::string> cellstr_value () const;
+  virtual OCTINTERP_API Array<std::string> cellstr_value () const;
 
-  virtual octave::range<double> range_value () const;
+  virtual OCTINTERP_API octave::range<double> range_value () const;
 
   // For now, enable only range<double>.
 
-  virtual octave_map map_value () const;
+  virtual OCTINTERP_API octave_map map_value () const;
 
-  virtual octave_scalar_map scalar_map_value () const;
+  virtual OCTINTERP_API octave_scalar_map scalar_map_value () const;
 
-  virtual string_vector map_keys () const;
+  virtual OCTINTERP_API string_vector map_keys () const;
 
-  virtual bool isfield (const std::string&) const;
+  virtual OCTINTERP_API bool isfield (const std::string&) const;
 
-  virtual std::size_t nparents () const;
+  virtual OCTINTERP_API std::size_t nparents () const;
 
-  virtual std::list<std::string> parent_class_name_list () const;
+  virtual OCTINTERP_API std::list<std::string> parent_class_name_list () const;
 
-  virtual string_vector parent_class_names () const;
+  virtual OCTINTERP_API string_vector parent_class_names () const;
 
   virtual octave_base_value * find_parent_class (const std::string&)
   { return nullptr; }
@@ -699,72 +717,74 @@
   virtual bool is_instance_of (const std::string&) const
   { return false; }
 
-  virtual octave_classdef * classdef_object_value (bool silent = false);
+  virtual OCTINTERP_API octave_classdef * classdef_object_value (bool silent = false);
 
-  virtual octave_function * function_value (bool silent = false);
+  virtual OCTINTERP_API octave_function * function_value (bool silent = false);
 
-  virtual octave_user_function * user_function_value (bool silent = false);
+  virtual OCTINTERP_API octave_user_function * user_function_value (bool silent = false);
 
-  virtual octave_user_script * user_script_value (bool silent = false);
+  virtual OCTINTERP_API octave_user_script * user_script_value (bool silent = false);
 
-  virtual octave_user_code * user_code_value (bool silent = false);
+  virtual OCTINTERP_API octave_user_code * user_code_value (bool silent = false);
 
-  virtual octave_fcn_handle * fcn_handle_value (bool silent = false);
+  virtual OCTINTERP_API octave_fcn_handle * fcn_handle_value (bool silent = false);
 
-  virtual octave_value_list list_value () const;
+  virtual OCTINTERP_API octave_value_list list_value () const;
 
-  virtual octave_value convert_to_str (bool pad = false, bool force = false,
-                                       char type = '\'') const;
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
+  convert_to_str (bool pad = false, bool force = false, char type = '\'') const;
+  virtual OCTINTERP_API octave_value
   convert_to_str_internal (bool pad, bool force, char type) const;
 
-  virtual void convert_to_row_or_column_vector ();
+  virtual OCTINTERP_API 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 OCTINTERP_API std::string xstring_value () const;
 
   virtual bool print_as_scalar () const { return false; }
 
-  virtual void print (std::ostream& os, bool pr_as_read_syntax = false);
+  virtual OCTINTERP_API void
+  print (std::ostream& os, bool pr_as_read_syntax = false);
 
-  virtual void
+  virtual OCTINTERP_API void
   print_raw (std::ostream& os, bool pr_as_read_syntax = false) const;
 
-  virtual bool
+  virtual OCTINTERP_API bool
   print_name_tag (std::ostream& os, const std::string& name) const;
 
-  virtual void
+  virtual OCTINTERP_API void
   print_with_name (std::ostream& output_buf, const std::string& name,
                    bool print_padding = true);
 
   virtual void short_disp (std::ostream& os) const { os << "..."; }
 
-  virtual float_display_format get_edit_display_format () const;
+  virtual OCTINTERP_API float_display_format get_edit_display_format () const;
 
   virtual std::string edit_display (const float_display_format&,
                                     octave_idx_type, octave_idx_type) const
   { return "#VAL"; }
 
-  virtual void print_info (std::ostream& os, const std::string& prefix) const;
+  virtual OCTINTERP_API void
+  print_info (std::ostream& os, const std::string& prefix) const;
 
-  virtual bool save_ascii (std::ostream& os);
+  virtual OCTINTERP_API bool save_ascii (std::ostream& os);
 
-  virtual bool load_ascii (std::istream& is);
+  virtual OCTINTERP_API bool load_ascii (std::istream& is);
 
-  virtual bool save_binary (std::ostream& os, bool save_as_floats);
+  virtual OCTINTERP_API bool save_binary (std::ostream& os, bool save_as_floats);
 
-  virtual bool load_binary (std::istream& is, bool swap,
-                            octave::mach_info::float_format fmt);
+  virtual OCTINTERP_API bool
+  load_binary (std::istream& is, bool swap, octave::mach_info::float_format fmt);
 
-  virtual bool
+  virtual OCTINTERP_API bool
   save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats);
 
-  virtual bool
+  virtual OCTINTERP_API bool
   load_hdf5 (octave_hdf5_id loc_id, const char *name);
 
-  virtual int
+  virtual OCTINTERP_API 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;
@@ -775,28 +795,29 @@
 
   virtual const octave_idx_type * mex_get_jc () const { return nullptr; }
 
-  virtual mxArray * as_mxArray (bool interleaved) const;
+  virtual OCTINTERP_API mxArray * as_mxArray (bool interleaved) const;
 
-  virtual octave_value diag (octave_idx_type k = 0) const;
+  virtual OCTINTERP_API octave_value diag (octave_idx_type k = 0) const;
 
-  virtual octave_value diag (octave_idx_type m, octave_idx_type n) const;
+  virtual OCTINTERP_API octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
-  virtual octave_value sort (octave_idx_type dim = 0,
-                             sortmode mode = ASCENDING) const;
-  virtual octave_value sort (Array<octave_idx_type>& sidx,
-                             octave_idx_type dim = 0,
-                             sortmode mode = ASCENDING) const;
+  virtual OCTINTERP_API octave_value
+  sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const;
 
-  virtual sortmode issorted (sortmode mode = UNSORTED) const;
+  virtual OCTINTERP_API octave_value
+  sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
+        sortmode mode = ASCENDING) const;
 
-  virtual Array<octave_idx_type>
+  virtual OCTINTERP_API sortmode issorted (sortmode mode = UNSORTED) const;
+
+  virtual OCTINTERP_API Array<octave_idx_type>
   sort_rows_idx (sortmode mode = ASCENDING) const;
 
-  virtual sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
+  virtual OCTINTERP_API sortmode is_sorted_rows (sortmode mode = UNSORTED) const;
 
-  virtual void lock ();
+  virtual OCTINTERP_API void lock ();
 
-  virtual void unlock ();
+  virtual OCTINTERP_API void unlock ();
 
   virtual bool islocked () const { return false; }
 
@@ -804,11 +825,11 @@
 
   virtual void maybe_call_dtor () { }
 
-  virtual octave_value dump () const;
+  virtual OCTINTERP_API octave_value dump () const;
 
-  virtual octave_value storable_value ();
+  virtual OCTINTERP_API octave_value storable_value ();
 
-  virtual octave_base_value * make_storable_value ();
+  virtual OCTINTERP_API octave_base_value * make_storable_value ();
 
   // Standard mappers.  Register new ones here.
   enum unary_mapper_t
@@ -877,26 +898,26 @@
     num_unary_mappers = umap_unknown
   };
 
-  virtual octave_value map (unary_mapper_t) const;
+  virtual OCTINTERP_API octave_value map (unary_mapper_t) const;
 
   // These are fast indexing & assignment shortcuts for extracting
   // or inserting a single scalar from/to an array.
 
   // Extract the n-th element, aka val(n).  Result is undefined if val is not
   // an array type or n is out of range.  Never error.
-  virtual octave_value
+  virtual OCTINTERP_API octave_value
   fast_elem_extract (octave_idx_type n) const;
 
   // Assign the n-th element, aka val(n) = x.  Returns false if val is not an
   // array type, x is not a matching scalar type, or n is out of range.
   // Never error.
-  virtual bool
+  virtual OCTINTERP_API bool
   fast_elem_insert (octave_idx_type n, const octave_value& x);
 
   // This is a helper for the above, to be overridden in scalar types.  The
   // whole point is to handle the insertion efficiently with just *two* VM
   // calls, which is basically the theoretical minimum.
-  virtual bool
+  virtual OCTINTERP_API bool
   fast_elem_insert_self (void *where, builtin_type_t btyp) const;
 
 protected:
@@ -954,9 +975,7 @@
   DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA
 };
 
-class
-OCTINTERP_API
-octave_base_dld_value : public octave_base_value
+class OCTINTERP_TEMPLATE_API octave_base_dld_value : public octave_base_value
 {
 public:
 
@@ -974,9 +993,6 @@
   octave::auto_shlib m_containing_dynamic_library;
 };
 
-OCTAVE_DEPRECATED (8, "Vsparse_auto_mutate is obsolete and is now always false")
-extern OCTINTERP_API bool Vsparse_auto_mutate;
-
 // Utility function to convert C++ arguments used in subsref/subsasgn into an
 // octave_value_list object that can be used to call a function/method in the
 // interpreter.
--- a/libinterp/octave-value/ov-bool-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -52,9 +52,6 @@
 #include "ovl.h"
 #include "oct-hdf5.h"
 #include "ops.h"
-#include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-bool.h"
 #include "ov-bool-mat.h"
 #include "ov-re-mat.h"
@@ -65,8 +62,6 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 
-template class octave_base_matrix<boolNDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_bool_matrix,
                                      "bool matrix", "logical");
 
@@ -237,7 +232,7 @@
 bool
 octave_bool_matrix::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () > 2)
     {
       NDArray tmp = array_value ();
@@ -336,10 +331,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = boolMatrix (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_bool_matrix::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_bool_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -348,7 +343,7 @@
 octave_bool_matrix::save_binary (std::ostream& os, bool /* save_as_floats */)
 {
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -414,7 +409,7 @@
   if (! is.read (htmp, nel))
     return false;
   boolNDArray m(dv);
-  bool *mtmp = m.fortran_vec ();
+  bool *mtmp = m.rwdata ();
   for (octave_idx_type i = 0; i < nel; i++)
     mtmp[i] = (htmp[i] ? 1 : 0);
   m_matrix = m;
@@ -430,7 +425,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
--- a/libinterp/octave-value/ov-bool-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,8 +48,9 @@
 
 // Character matrix values.
 
-class
-octave_bool_matrix : public octave_base_matrix<boolNDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<boolNDArray>;
+
+class octave_bool_matrix : public octave_base_matrix<boolNDArray>
 {
 public:
 
@@ -241,7 +242,7 @@
 
 protected:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-bool-sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -180,7 +180,7 @@
 bool
 octave_sparse_bool_matrix::save_binary (std::ostream& os, bool)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -321,7 +321,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
--- a/libinterp/octave-value/ov-bool-sparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool-sparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,9 +47,7 @@
 
 class octave_value_list;
 
-class
-OCTINTERP_API
-octave_sparse_bool_matrix : public octave_base_sparse<SparseBoolMatrix>
+class OCTINTERP_API octave_sparse_bool_matrix : public octave_base_sparse<SparseBoolMatrix>
 {
 public:
 
@@ -152,7 +150,7 @@
 
 protected:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-bool.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -42,8 +42,6 @@
 #include "ov-bool.h"
 #include "ov-bool-mat.h"
 #include "ov-base.h"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-re-mat.h"
 #include "ov-scalar.h"
 #include "pr-output.h"
@@ -51,13 +49,6 @@
 #include "ls-oct-text.h"
 #include "ls-hdf5.h"
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_scalar<bool>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_bool, "bool", "logical");
 
 static octave_base_value *
--- a/libinterp/octave-value/ov-bool.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-bool.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,9 @@
 
 // Real scalar values.
 
-class
-OCTINTERP_API
-octave_bool : public octave_base_scalar<bool>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<bool>;
+
+class OCTINTERP_API octave_bool : public octave_base_scalar<bool>
 {
 public:
 
@@ -258,7 +258,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-builtin.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-builtin.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,9 +47,7 @@
 
 // Builtin functions.
 
-class
-OCTINTERP_API
-octave_builtin : public octave_function
+class OCTINTERP_API octave_builtin : public octave_function
 {
 public:
 
@@ -118,7 +116,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-cell.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cell.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -48,8 +48,6 @@
 #include "oct-hdf5.h"
 #include "unwind-prot.h"
 #include "utils.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-fcn-handle.h"
 #include "ov-re-mat.h"
 #include "ov-scalar.h"
@@ -62,85 +60,6 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 
-// Cell is able to handle octave_value indexing by itself, so just forward
-// everything.
-
-template <>
-octave_value
-octave_base_matrix<Cell>::do_index_op (const octave_value_list& idx,
-                                       bool resize_ok)
-{
-  return m_matrix.index (idx, resize_ok);
-}
-
-template <>
-void
-octave_base_matrix<Cell>::assign (const octave_value_list& idx, const Cell& rhs)
-{
-  m_matrix.assign (idx, rhs);
-}
-
-template <>
-void
-octave_base_matrix<Cell>::assign (const octave_value_list& idx,
-                                  octave_value rhs)
-{
-  // FIXME: Really?
-  if (rhs.iscell ())
-    m_matrix.assign (idx, rhs.cell_value ());
-  else
-    m_matrix.assign (idx, Cell (rhs));
-}
-
-template <>
-void
-octave_base_matrix<Cell>::delete_elements (const octave_value_list& idx)
-{
-  m_matrix.delete_elements (idx);
-}
-
-// FIXME: this list of specializations is becoming so long that we should
-// really ask whether octave_cell should inherit from octave_base_matrix at all.
-
-template <>
-std::string
-octave_base_matrix<Cell>::edit_display (const float_display_format&,
-                                        octave_idx_type i,
-                                        octave_idx_type j) const
-{
-  octave_value val = m_matrix(i, j);
-
-  std::string tname = val.type_name ();
-  dim_vector dv = val.dims ();
-  std::string dimstr = dv.str ();
-  return "[" + dimstr + " " + tname + "]";
-}
-
-template <>
-octave_value
-octave_base_matrix<Cell>::fast_elem_extract (octave_idx_type n) const
-{
-  if (n < m_matrix.numel ())
-    return Cell (m_matrix(n));
-  else
-    return octave_value ();
-}
-
-template <>
-bool
-octave_base_matrix<Cell>::fast_elem_insert (octave_idx_type n,
-    const octave_value& x)
-{
-  const octave_cell *xrep = dynamic_cast<const octave_cell *> (&x.get_rep ());
-
-  bool retval = xrep && xrep->m_matrix.numel () == 1 && n < m_matrix.numel ();
-  if (retval)
-    m_matrix(n) = xrep->m_matrix(0);
-
-  return retval;
-}
-
-template class octave_base_matrix<Cell>;
 
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_cell, "cell", "cell");
 
@@ -189,7 +108,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_cell::simple_subsref - please report this bug");
     }
 
   return retval;
@@ -235,7 +154,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug");
     }
 
   // FIXME: perhaps there should be an
@@ -285,7 +204,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_cell::subsref - please report this bug");
     }
 
   // FIXME: perhaps there should be an
@@ -392,7 +311,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug");
         }
     }
 
@@ -466,7 +385,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_cell::subsasgn - please report this bug");
     }
 
   return retval;
@@ -752,7 +671,7 @@
   else
     {
       indent (os);
-      dim_vector dv = m_matrix.dims ();
+      const dim_vector& dv = m_matrix.dims ();
       os << '{' << dv.str () << " Cell Array}";
       newline (os);
     }
@@ -788,7 +707,7 @@
 bool
 octave_cell::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () > 2)
     {
       os << "# ndims: " << dv.ndims () << "\n";
@@ -930,10 +849,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = Cell (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_cell::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_cell::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -941,7 +860,7 @@
 bool
 octave_cell::save_binary (std::ostream& os, bool save_as_floats)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -1052,7 +971,7 @@
 {
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -1318,7 +1237,7 @@
 
         for (int i = 0; i < nargin; i++)
           dims(i) = (args(i).isempty ()
-                     ? 0 : args(i).xidx_type_value ("cell: dimension must be a scalar integer"));
+                     ? 0 : args(i).yidx_type_value ("cell: dimension must be a scalar integer"));
       }
       break;
     }
--- a/libinterp/octave-value/ov-cell.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cell.h	Fri Apr 12 15:10:26 2024 +0200
@@ -46,8 +46,9 @@
 
 // Cells.
 
-class
-octave_cell : public octave_base_matrix<Cell>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<Cell>;
+
+class octave_cell : public octave_base_matrix<Cell>
 {
 public:
 
@@ -190,7 +191,7 @@
 
   mutable std::unique_ptr<Array<std::string>> m_cellstr_cache;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-ch-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-ch-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -48,15 +48,10 @@
 #include "unistr-wrappers.h"
 
 #include "mxarray.h"
-#include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-ch-mat.h"
 #include "errwarn.h"
 #include "pr-output.h"
 
-template class octave_base_matrix<charNDArray>;
-
 octave::idx_vector
 octave_char_matrix::index_vector (bool /* require_integers */) const
 {
@@ -324,7 +319,7 @@
         std::size_t output_length = in_m.numel ();                             \
         charNDArray ch_array = charNDArray (in_m.dims ());                     \
         const uint8_t *in = reinterpret_cast<const uint8_t *> (in_m.data ());  \
-        uint8_t *buf = reinterpret_cast<uint8_t *> (ch_array.fortran_vec ());  \
+        uint8_t *buf = reinterpret_cast<uint8_t *> (ch_array.rwdata ());       \
         U8_FCN (in, m_matrix.numel (), nullptr, buf, &output_length);          \
         if (output_length != static_cast<std::size_t> (m_matrix.numel ()))     \
           {                                                                    \
--- a/libinterp/octave-value/ov-ch-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-ch-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,8 +48,9 @@
 
 // Character matrix values.
 
-class
-octave_char_matrix : public octave_base_matrix<charNDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<charNDArray>;
+
+class octave_char_matrix : public octave_base_matrix<charNDArray>
 {
 protected:
 
--- a/libinterp/octave-value/ov-class.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-class.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -134,7 +134,7 @@
               // distribute the elements of the parent object to
               // the elements of MAP.
 
-              dim_vector parent_dims = parent.dims ();
+              const dim_vector& parent_dims = parent.dims ();
 
               m_map.resize (parent_dims);
 
@@ -331,7 +331,7 @@
     }
   else
     {
-      dim_vector dv = dims ();
+      const dim_vector& dv = dims ();
 
       int nd = dv.ndims ();
 
@@ -438,7 +438,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unpexpected: index not '(', '{', or '.' in - octave_class::subsref please report this bug");
         }
 
       // FIXME: perhaps there should be an
@@ -748,7 +748,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unpexpected: index not '(', '{', or '.' in - octave_class::subsasgn_common please report this bug");
         }
     }
 
@@ -833,7 +833,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unpexpected: index not '(', '{', or '.' in - octave_class::subsref please report this bug");
     }
 
   return retval;
@@ -1285,7 +1285,7 @@
       m_c_name = classname;
     }
   else
-    panic_impossible ();
+    error ("unexpected: len < 0 in octave_class::load_ascii - please report this bug");
 
   return true;
 }
@@ -1412,7 +1412,7 @@
   else if (len == 0)
     m_map = octave_map (dim_vector (1, 1));
   else
-    panic_impossible ();
+    error ("unexpected: len < 0 in octave_class::load_binary - please report this bug");
 
   return success;
 }
@@ -2090,8 +2090,7 @@
 // The following class can be removed once the
 // octave_value::function_value method is removed.
 
-class
-octave_inline_fcn : public octave_function
+class octave_inline_fcn : public octave_function
 {
 public:
 
@@ -2129,8 +2128,7 @@
 //   return class_name () == "inline";
 // }
 
-class
-octave_inline : public octave_class
+class octave_inline : public octave_class
 {
 public:
 
--- a/libinterp/octave-value/ov-class.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-class.h	Fri Apr 12 15:10:26 2024 +0200
@@ -50,8 +50,7 @@
 
 // Data structures.
 
-class
-octave_class : public octave_base_value
+class octave_class : public octave_base_value
 {
 public:
 
@@ -139,7 +138,7 @@
   // of elements is numel () * nfields ().
   octave_idx_type numel () const
   {
-    dim_vector dv = dims ();
+    const dim_vector& dv = dims ();
     return dv.numel ();
   }
 
--- a/libinterp/octave-value/ov-classdef.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-classdef.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -396,7 +396,7 @@
           else
             {
               octave_value val = prop.get_value (m_object, false);
-              dim_vector dims = val.dims ();
+              const dim_vector& dims = val.dims ();
 
               os << std::setw (max_len+2) << nm << ": ";
               if (val.is_string ())
@@ -656,7 +656,7 @@
         {
           octave::tree_parameter_list *ret_list = uf->return_list ();
 
-          if (ret_list && ret_list->length () == 1)
+          if (ret_list && ret_list->size () == 1)
             return (ret_list->front ()->name () == nm);
         }
     }
--- a/libinterp/octave-value/ov-classdef.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-classdef.h	Fri Apr 12 15:10:26 2024 +0200
@@ -43,8 +43,7 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-class
-octave_classdef : public octave_base_value
+class octave_classdef : public octave_base_value
 {
 public:
 
--- a/libinterp/octave-value/ov-colon.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-colon.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,8 +44,7 @@
 
 // A type to represent ':' as used for indexing.
 
-class
-octave_magic_colon : public octave_base_value
+class octave_magic_colon : public octave_base_value
 {
 public:
 
@@ -78,7 +77,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-complex.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-complex.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -43,8 +43,6 @@
 #include "ov-complex.h"
 #include "ov-flt-complex.h"
 #include "ov-base.h"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-cx-mat.h"
 #include "ov-scalar.h"
 #include "errwarn.h"
@@ -54,14 +52,6 @@
 #include "ls-oct-text.h"
 #include "ls-hdf5.h"
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-extern template class octave_base_scalar<FloatComplex>;
-
-template class octave_base_scalar<Complex>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex,
                                      "complex scalar", "double");
 
--- a/libinterp/octave-value/ov-complex.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-complex.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "mx-base.h"
 #include "str-vec.h"
 
@@ -48,9 +47,9 @@
 
 // Complex scalar values.
 
-class
-OCTINTERP_API
-octave_complex : public octave_base_scalar<Complex>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<Complex>;
+
+class OCTINTERP_API octave_complex : public octave_base_scalar<Complex>
 {
 public:
 
@@ -87,8 +86,8 @@
   octave_value any (int = 0) const
   {
     return (scalar != Complex (0, 0)
-            && ! (lo_ieee_isnan (scalar.real ())
-                  || lo_ieee_isnan (scalar.imag ())));
+            && ! (octave::math::isnan (scalar.real ())
+                  || octave::math::isnan (scalar.imag ())));
   }
 
   builtin_type_t builtin_type () const { return btyp_complex; }
@@ -206,7 +205,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 typedef octave_complex octave_complex_scalar;
--- a/libinterp/octave-value/ov-cs-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cs-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -43,8 +43,7 @@
 
 // Lists.
 
-class
-octave_cs_list : public octave_base_value
+class octave_cs_list : public octave_base_value
 {
 public:
 
@@ -91,7 +90,7 @@
   // The list of Octave values.
   octave_value_list m_list;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-cx-diag.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-diag.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -231,7 +231,7 @@
     }
 
   ComplexDiagMatrix m (r, c);
-  Complex *im = m.fortran_vec ();
+  Complex *im = m.rwdata ();
   octave_idx_type len = m.length ();
   read_doubles (is, reinterpret_cast<double *> (im),
                 static_cast<save_type> (tmp), 2 * len, swap, fmt);
--- a/libinterp/octave-value/ov-cx-diag.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-diag.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 
 // Real diagonal matrix values.
 
-class
-octave_complex_diag_matrix
+class octave_complex_diag_matrix
   : public octave_base_diag<ComplexDiagMatrix, ComplexMatrix>
 {
 public:
@@ -98,7 +97,7 @@
 
   OCTINTERP_API bool chk_valid_scalar (const octave_value&, Complex&) const;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-cx-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -50,8 +50,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-complex.h"
 #include "ov-cx-mat.h"
 #include "ov-flt-cx-mat.h"
@@ -65,8 +63,6 @@
 #include "ls-utils.h"
 
 
-template class octave_base_matrix<ComplexNDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_complex_matrix,
                                      "complex matrix", "double");
 
@@ -320,7 +316,7 @@
 bool
 octave_complex_matrix::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () > 2)
     {
       ComplexNDArray tmp = complex_array_value ();
@@ -413,10 +409,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = ComplexMatrix (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_complex_matrix::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_complex_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -424,7 +420,7 @@
 bool
 octave_complex_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -505,7 +501,7 @@
         return false;
 
       ComplexNDArray m(dv);
-      Complex *im = m.fortran_vec ();
+      Complex *im = m.rwdata ();
       read_doubles (is, reinterpret_cast<double *> (im),
                     static_cast<save_type> (tmp), 2 * dv.numel (), swap, fmt);
 
@@ -525,7 +521,7 @@
       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
         return false;
       ComplexMatrix m (nr, nc);
-      Complex *im = m.fortran_vec ();
+      Complex *im = m.rwdata ();
       octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;
       read_doubles (is, reinterpret_cast<double *> (im),
                     static_cast<save_type> (tmp), 2*len, swap, fmt);
@@ -544,7 +540,7 @@
 {
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -703,7 +699,7 @@
     }
 
   ComplexNDArray m (dv);
-  Complex *reim = m.fortran_vec ();
+  Complex *reim = m.rwdata ();
   if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,
                octave_H5P_DEFAULT, reim)
       >= 0)
--- a/libinterp/octave-value/ov-cx-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,9 @@
 
 // Complex matrix values.
 
-class
-OCTINTERP_API
-octave_complex_matrix : public octave_base_matrix<ComplexNDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<ComplexNDArray>;
+
+class OCTINTERP_API octave_complex_matrix : public octave_base_matrix<ComplexNDArray>
 {
 public:
 
@@ -181,7 +181,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-cx-sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -182,7 +182,7 @@
 octave_sparse_complex_matrix::save_binary (std::ostream& os,
     bool save_as_floats)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -327,7 +327,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
--- a/libinterp/octave-value/ov-cx-sparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-cx-sparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,9 +47,7 @@
 
 class octave_value_list;
 
-class
-OCTINTERP_API
-octave_sparse_complex_matrix : public octave_base_sparse<SparseComplexMatrix>
+class OCTINTERP_API octave_sparse_complex_matrix : public octave_base_sparse<SparseComplexMatrix>
 {
 public:
 
@@ -144,7 +142,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-dld-fcn.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-dld-fcn.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 
 // Dynamically-linked functions.
 
-class
-OCTINTERP_API
-octave_dld_function : public octave_builtin
+class OCTINTERP_API octave_dld_function : public octave_builtin
 {
 public:
 
@@ -106,7 +104,7 @@
   // on the file to see if it has changed.
   bool m_system_fcn_file;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-fcn-handle.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -825,7 +825,7 @@
       error ("function handle cannot be indexed with %c", type[0]);
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in base_fcn_handle::subsref - please report this bug");
     }
 
   // FIXME: perhaps there should be an
@@ -2693,7 +2693,7 @@
 
   tree_statement_list *b = f->body ();
 
-  panic_if (b->length () != 1);
+  panic_if (b->size () != 1);
 
   tree_statement *s = b->front ();
 
--- a/libinterp/octave-value/ov-fcn-handle.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-fcn-handle.h	Fri Apr 12 15:10:26 2024 +0200
@@ -182,9 +182,7 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-octave_fcn_handle : public octave_base_value
+class OCTINTERP_API octave_fcn_handle : public octave_base_value
 {
 public:
 
@@ -383,7 +381,7 @@
 
   octave::base_fcn_handle * get_rep () const { return m_rep.get (); }
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 extern bool
--- a/libinterp/octave-value/ov-fcn.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-fcn.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,29 +27,40 @@
 #  include "config.h"
 #endif
 
+#include "lo-array-errwarn.h"
 #include "unwind-prot.h"
 
 #include "error.h"
+#include "filepos.h"
+#include "interpreter-private.h"
+#include "interpreter.h"
+#include "ov-fcn.h"
 #include "ovl.h"
-#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"
 
 octave_base_value *
 octave_function::clone () const
 {
-  panic_impossible ();
+  error ("unexpected call to octave_function::clone - please report this bug");
 }
 
 octave_base_value *
 octave_function::empty_clone () const
 {
-  panic_impossible ();
+  error ("unexpected call to octave_function::empty_clone - please report this bug");
+}
+
+octave::filepos
+octave_function::beg_pos () const
+{
+  error ("unexpected call to octave_function::beg_pos - please report this bug");
+}
+
+octave::filepos
+octave_function::end_pos () const
+{
+  error ("unexpected call to octave_function::end_pos - please report this bug");
 }
 
 octave_value_list
--- a/libinterp/octave-value/ov-fcn.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-fcn.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,6 +40,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class filepos;
 class stack_frame;
 class tree_evaluator;
 class tree_walker;
@@ -48,9 +49,7 @@
 
 // Functions.
 
-class
-OCTINTERP_API
-octave_function : public octave_base_value
+class OCTINTERP_API octave_function : public octave_base_value
 {
 public:
 
@@ -76,6 +75,9 @@
 
   virtual std::string src_file_name () const { return ""; }
 
+  virtual octave::filepos beg_pos () const;
+  virtual octave::filepos end_pos () const;
+
   // The name to show in the profiler (also used as map-key).
   virtual std::string profiler_name () const { return name (); }
 
--- a/libinterp/octave-value/ov-float.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-float.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,8 +46,6 @@
 #include "ov-scalar.h"
 #include "ov-float.h"
 #include "ov-base.h"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-flt-re-mat.h"
 #include "ov-typeinfo.h"
 #include "pr-output.h"
@@ -59,8 +57,6 @@
 #include "ls-hdf5.h"
 
 
-template class octave_base_scalar<float>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_scalar, "float scalar",
                                      "single");
 
--- a/libinterp/octave-value/ov-float.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-float.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 #include "mx-base.h"
@@ -50,9 +49,9 @@
 
 // Real scalar values.
 
-class
-OCTINTERP_API
-octave_float_scalar : public octave_base_scalar<float>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<float>;
+
+class OCTINTERP_API octave_float_scalar : public octave_base_scalar<float>
 {
 public:
 
@@ -83,7 +82,7 @@
   { return octave::idx_vector (scalar); }
 
   octave_value any (int = 0) const
-  { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
+  { return (scalar != 0 && ! octave::math::isnan (scalar)); }
 
   builtin_type_t builtin_type () const { return btyp_float; }
 
@@ -275,7 +274,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-flt-complex.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-complex.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -40,9 +40,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-complex.h"
-#include "ov-base.h"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-flt-cx-mat.h"
 #include "ov-float.h"
 #include "ov-flt-complex.h"
@@ -53,13 +50,6 @@
 #include "ls-oct-text.h"
 #include "ls-hdf5.h"
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<float>;
-
-template class octave_base_scalar<FloatComplex>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex,
                                      "float complex scalar", "single");
 
--- a/libinterp/octave-value/ov-flt-complex.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-complex.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "mx-base.h"
 #include "str-vec.h"
 
@@ -48,9 +47,9 @@
 
 // Complex scalar values.
 
-class
-OCTINTERP_API
-octave_float_complex : public octave_base_scalar<FloatComplex>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<FloatComplex>;
+
+class OCTINTERP_API octave_float_complex : public octave_base_scalar<FloatComplex>
 {
 public:
 
@@ -83,8 +82,8 @@
   octave_value any (int = 0) const
   {
     return (scalar != FloatComplex (0, 0)
-            && ! (lo_ieee_isnan (scalar.real ())
-                  || lo_ieee_isnan (scalar.imag ())));
+            && ! (octave::math::isnan (scalar.real ())
+                  || octave::math::isnan (scalar.imag ())));
   }
 
   builtin_type_t builtin_type () const { return btyp_float_complex; }
@@ -197,7 +196,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 typedef octave_float_complex octave_float_complex_scalar;
--- a/libinterp/octave-value/ov-flt-cx-diag.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-cx-diag.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -200,7 +200,7 @@
     }
 
   FloatComplexDiagMatrix m (r, c);
-  FloatComplex *re = m.fortran_vec ();
+  FloatComplex *re = m.rwdata ();
   octave_idx_type len = m.length ();
   read_floats (is, reinterpret_cast<float *> (re),
                static_cast<save_type> (tmp), 2 * len, swap, fmt);
--- a/libinterp/octave-value/ov-flt-cx-diag.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-cx-diag.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 // Real diagonal matrix values.
 
-class
-OCTINTERP_API
-octave_float_complex_diag_matrix
+class OCTINTERP_API octave_float_complex_diag_matrix
   : public octave_base_diag<FloatComplexDiagMatrix, FloatComplexMatrix>
 {
 public:
@@ -95,7 +93,7 @@
   bool chk_valid_scalar (const octave_value&,
                          FloatComplex&) const;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-flt-cx-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -50,8 +50,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-complex.h"
 #include "ov-flt-complex.h"
 #include "ov-cx-mat.h"
@@ -69,8 +67,6 @@
 #include "ls-utils.h"
 
 
-template class octave_base_matrix<FloatComplexNDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_complex_matrix,
                                      "float complex matrix", "single");
 
@@ -294,7 +290,7 @@
 bool
 octave_float_complex_matrix::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dv.ndims () > 2)
     {
@@ -388,10 +384,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = FloatComplexMatrix (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_float_complex_matrix::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_float_complex_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -399,7 +395,7 @@
 bool
 octave_float_complex_matrix::save_binary (std::ostream& os, bool)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -470,7 +466,7 @@
         return false;
 
       FloatComplexNDArray m(dv);
-      FloatComplex *im = m.fortran_vec ();
+      FloatComplex *im = m.rwdata ();
       read_floats (is, reinterpret_cast<float *> (im),
                    static_cast<save_type> (tmp), 2 * dv.numel (), swap, fmt);
 
@@ -490,7 +486,7 @@
       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
         return false;
       FloatComplexMatrix m (nr, nc);
-      FloatComplex *im = m.fortran_vec ();
+      FloatComplex *im = m.rwdata ();
       octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;
       read_floats (is, reinterpret_cast<float *> (im),
                    static_cast<save_type> (tmp), 2*len, swap, fmt);
@@ -511,7 +507,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -656,7 +652,7 @@
     }
 
   FloatComplexNDArray m (dv);
-  FloatComplex *reim = m.fortran_vec ();
+  FloatComplex *reim = m.rwdata ();
   if (H5Dread (data_hid, complex_type, octave_H5S_ALL, octave_H5S_ALL,
                octave_H5P_DEFAULT, reim)
       >= 0)
--- a/libinterp/octave-value/ov-flt-cx-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-cx-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,9 @@
 
 // Complex matrix values.
 
-class
-OCTINTERP_API
-octave_float_complex_matrix : public octave_base_matrix<FloatComplexNDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<FloatComplexNDArray>;
+
+class OCTINTERP_API octave_float_complex_matrix : public octave_base_matrix<FloatComplexNDArray>
 {
 public:
 
@@ -177,7 +177,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-flt-re-diag.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-re-diag.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -218,7 +218,7 @@
     }
 
   FloatDiagMatrix m (r, c);
-  float *re = m.fortran_vec ();
+  float *re = m.rwdata ();
   octave_idx_type len = m.length ();
   read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt);
 
--- a/libinterp/octave-value/ov-flt-re-diag.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-re-diag.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 // Real diagonal matrix values.
 
-class
-OCTINTERP_API
-octave_float_diag_matrix
+class OCTINTERP_API octave_float_diag_matrix
   : public octave_base_diag<FloatDiagMatrix, FloatMatrix>
 {
 public:
@@ -105,7 +103,7 @@
   bool chk_valid_scalar (const octave_value&,
                          float&) const;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-flt-re-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -63,8 +63,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-scalar.h"
 #include "ov-float.h"
 #include "ov-flt-complex.h"
@@ -84,8 +82,6 @@
 #include "ls-hdf5.h"
 
 
-template class octave_base_matrix<FloatNDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_float_matrix, "float matrix",
                                      "single");
 
@@ -328,7 +324,7 @@
 octave_float_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nel = dv.numel ();
 
   charNDArray chm (dv);
@@ -370,7 +366,7 @@
 bool
 octave_float_matrix::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dv.ndims () > 2)
     {
@@ -464,10 +460,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = FloatMatrix (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_float_matrix::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_float_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -475,7 +471,7 @@
 bool
 octave_float_matrix::save_binary (std::ostream& os, bool)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -545,7 +541,7 @@
         return false;
 
       FloatNDArray m(dv);
-      float *re = m.fortran_vec ();
+      float *re = m.rwdata ();
       read_floats (is, re, static_cast<save_type> (tmp), dv.numel (),
                    swap, fmt);
 
@@ -565,7 +561,7 @@
       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
         return false;
       FloatMatrix m (nr, nc);
-      float *re = m.fortran_vec ();
+      float *re = m.rwdata ();
       octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;
       read_floats (is, re, static_cast<save_type> (tmp), len, swap, fmt);
 
@@ -584,7 +580,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -698,7 +694,7 @@
     }
 
   FloatNDArray m (dv);
-  float *re = m.fortran_vec ();
+  float *re = m.rwdata ();
   if (H5Dread (data_hid, H5T_NATIVE_FLOAT, octave_H5S_ALL, octave_H5S_ALL,
                octave_H5P_DEFAULT, re) >= 0)
     {
--- a/libinterp/octave-value/ov-flt-re-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-flt-re-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,9 @@
 
 // Real matrix values.
 
-class
-OCTINTERP_API
-octave_float_matrix : public octave_base_matrix<FloatNDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<FloatNDArray>;
+
+class OCTINTERP_API octave_float_matrix : public octave_base_matrix<FloatNDArray>
 {
 public:
 
@@ -220,7 +220,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-int-traits.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-int-traits.h	Fri Apr 12 15:10:26 2024 +0200
@@ -39,8 +39,7 @@
 #include "ov-uint64.h"
 
 template <typename T>
-class
-octave_value_int_traits
+class octave_value_int_traits
 {
 public:
   typedef T scalar_type;
--- a/libinterp/octave-value/ov-int16.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-int16.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-int16.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_int16_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_int16_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<int16NDArray>;
-
-template class octave_base_int_matrix<int16NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int16_matrix,
                                      "int16 matrix", "int16");
 
-template class octave_base_scalar<octave_int16>;
-
-template class octave_base_int_scalar<octave_int16>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int16_scalar,
                                      "int16 scalar", "int16");
--- a/libinterp/octave-value/ov-int32.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-int32.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-int32.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_int32_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_int32_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<int32NDArray>;
-
-template class octave_base_int_matrix<int32NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int32_matrix,
                                      "int32 matrix", "int32");
 
-template class octave_base_scalar<octave_int32>;
-
-template class octave_base_int_scalar<octave_int32>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int32_scalar,
                                      "int32 scalar", "int32");
--- a/libinterp/octave-value/ov-int64.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-int64.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-int64.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_int64_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_int64_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<int64NDArray>;
-
-template class octave_base_int_matrix<int64NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int64_matrix,
                                      "int64 matrix", "int64");
 
-template class octave_base_scalar<octave_int64>;
-
-template class octave_base_int_scalar<octave_int64>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int64_scalar,
                                      "int64 scalar", "int64");
--- a/libinterp/octave-value/ov-int8.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-int8.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-int8.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_int8_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_int8_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<int8NDArray>;
-
-template class octave_base_int_matrix<int8NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int8_matrix,
                                      "int8 matrix", "int8");
 
-template class octave_base_scalar<octave_int8>;
-
-template class octave_base_int_scalar<octave_int8>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_int8_scalar,
                                      "int8 scalar", "int8");
--- a/libinterp/octave-value/ov-intx.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-intx.h	Fri Apr 12 15:10:26 2024 +0200
@@ -49,9 +49,9 @@
 #include "ov-re-mat.h"
 #include "ov-scalar.h"
 
-class
-OCTINTERP_API
-OCTAVE_VALUE_INT_MATRIX_T
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_int_matrix<intNDArray<OCTAVE_INT_T>>;
+
+class OCTINTERP_API OCTAVE_VALUE_INT_MATRIX_T
   : public octave_base_int_matrix<intNDArray<OCTAVE_INT_T>>
 {
 public:
@@ -146,12 +146,12 @@
   matrix_value (bool = false) const
   {
     Matrix retval;
-    dim_vector dv = dims ();
+    const dim_vector& dv = dims ();
     if (dv.ndims () > 2)
       error ("invalid conversion of %s to Matrix", type_name ().c_str ());
 
     retval = Matrix (dv(0), dv(1));
-    double *vec = retval.fortran_vec ();
+    double *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).double_value ();
@@ -163,12 +163,12 @@
   float_matrix_value (bool = false) const
   {
     FloatMatrix retval;
-    dim_vector dv = dims ();
+    const dim_vector& dv = dims ();
     if (dv.ndims () > 2)
       error ("invalid conversion of %s to FloatMatrix", type_name ().c_str ());
 
     retval = FloatMatrix (dv(0), dv(1));
-    float *vec = retval.fortran_vec ();
+    float *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).float_value ();
@@ -180,12 +180,12 @@
   complex_matrix_value (bool = false) const
   {
     ComplexMatrix retval;
-    dim_vector dv = dims ();
+    const dim_vector& dv = dims ();
     if (dv.ndims () > 2)
       error ("invalid conversion of %s to Matrix", type_name ().c_str ());
 
     retval = ComplexMatrix (dv(0), dv(1));
-    Complex *vec = retval.fortran_vec ();
+    Complex *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = Complex (m_matrix(i).double_value ());
@@ -197,12 +197,12 @@
   float_complex_matrix_value (bool = false) const
   {
     FloatComplexMatrix retval;
-    dim_vector dv = dims ();
+    const dim_vector& dv = dims ();
     if (dv.ndims () > 2)
       error ("invalid conversion of %s to FloatMatrix", type_name ().c_str ());
 
     retval = FloatComplexMatrix (dv(0), dv(1));
-    FloatComplex *vec = retval.fortran_vec ();
+    FloatComplex *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = FloatComplex (m_matrix(i).float_value ());
@@ -214,7 +214,7 @@
   array_value (bool = false) const
   {
     NDArray retval (m_matrix.dims ());
-    double *vec = retval.fortran_vec ();
+    double *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).double_value ();
@@ -225,7 +225,7 @@
   float_array_value (bool = false) const
   {
     FloatNDArray retval (m_matrix.dims ());
-    float *vec = retval.fortran_vec ();
+    float *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).float_value ();
@@ -236,7 +236,7 @@
   complex_array_value (bool = false) const
   {
     ComplexNDArray retval (m_matrix.dims ());
-    Complex *vec = retval.fortran_vec ();
+    Complex *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = Complex (m_matrix(i).double_value ());
@@ -247,7 +247,7 @@
   float_complex_array_value (bool = false) const
   {
     FloatComplexNDArray retval (m_matrix.dims ());
-    FloatComplex *vec = retval.fortran_vec ();
+    FloatComplex *vec = retval.rwdata ();
     octave_idx_type nel = m_matrix.numel ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = FloatComplex (m_matrix(i).float_value ());
@@ -264,7 +264,7 @@
     if (warn && m_matrix.any_element_not_one_or_zero ())
       warn_logical_conversion ();
 
-    bool *vec = retval.fortran_vec ();
+    bool *vec = retval.rwdata ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).bool_value ();
 
@@ -278,7 +278,7 @@
 
     octave_idx_type nel = numel ();
 
-    char *vec = retval.fortran_vec ();
+    char *vec = retval.rwdata ();
     for (octave_idx_type i = 0; i < nel; i++)
       vec[i] = m_matrix(i).char_value ();
 
@@ -383,9 +383,11 @@
 
   static octave_hdf5_id s_hdf5_save_type;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_int_scalar<OCTAVE_INT_T>;
+
 class
 OCTINTERP_API
 OCTAVE_VALUE_INT_SCALAR_T
@@ -696,5 +698,5 @@
 
   static octave_hdf5_id s_hdf5_save_type;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
--- a/libinterp/octave-value/ov-java.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-java.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -104,7 +104,7 @@
   java_local_ref (JNIEnv *env, T obj)
     : m_jobj (obj), m_detached (false), m_env (env) { }
 
-  ~java_local_ref (void) { release (); }
+  ~java_local_ref () { release (); }
 
   T& operator = (T obj)
   {
@@ -119,7 +119,7 @@
   operator bool () const { return (m_jobj != 0); }
   operator T () { return m_jobj; }
 
-  void detach (void) { m_detached = true; }
+  void detach () { m_detached = true; }
 
 protected:
 
@@ -129,11 +129,11 @@
 
 private:
 
-  java_local_ref (void)
+  java_local_ref ()
     : m_jobj (0), m_detached (false), m_env (0)
   { }
 
-  void release (void)
+  void release ()
   {
     if (m_env && m_jobj && ! m_detached)
       m_env->DeleteLocalRef (m_jobj);
@@ -641,6 +641,7 @@
 
   return jvm_lib_path;
 }
+
 #endif
 
 //! Initialize the java virtual machine (jvm) and field #jvm if necessary.
@@ -903,6 +904,14 @@
   return env;
 }
 
+#else
+
+OCTAVE_NORETURN static void
+error_unexpected (const char *name)
+{
+  error ("unexpected call to %s when HAVE_JAVA is not defined - please report this bug", name);
+}
+
 #endif
 
 bool
@@ -925,7 +934,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::is_java_string");
 
 #endif
 }
@@ -957,7 +966,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::is_instance_of");
 
 #endif
 }
@@ -1444,7 +1453,7 @@
           const JAVA_TYPE ## Array jarr = reinterpret_cast<JAVA_TYPE ## Array> (jobj); \
           const jsize len = jni_env->GetArrayLength (jarr); \
           OCTAVE_ID ## NDArray d (dim_vector (len, 1)); \
-          JAVA_TYPE *buffer = reinterpret_cast<JAVA_TYPE *> (d.fortran_vec ()); \
+          JAVA_TYPE *buffer = reinterpret_cast<JAVA_TYPE *> (d.rwdata ()); \
           jni_env->Get ## JAVA_TYPE_CAP ## ArrayRegion (jarr, 0, len, buffer); \
           retval = d; \
           break; \
@@ -1497,7 +1506,7 @@
                                        (jni_env->CallObjectMethod (jobj,
                                            mID)));
                   jni_env->GetDoubleArrayRegion (dv, 0, m.numel (),
-                                                 m.fortran_vec ());
+                                                 m.rwdata ());
                   retval = m;
                   break;
                 }
@@ -1513,7 +1522,7 @@
                                              mID)));
                       jni_env->GetByteArrayRegion (dv, 0, m.numel (),
                                                    reinterpret_cast<jbyte *>
-                                                   (m.fortran_vec ()));
+                                                   (m.rwdata ()));
                       retval = m;
                       break;
                     }
@@ -1527,7 +1536,7 @@
                                              mID)));
                       jni_env->GetByteArrayRegion (dv, 0, m.numel (),
                                                    reinterpret_cast<jbyte *>
-                                                   (m.fortran_vec ()));
+                                                   (m.rwdata ()));
                       retval = m;
                       break;
                     }
@@ -1544,7 +1553,7 @@
                                             mID)));
                       jni_env->GetIntArrayRegion (dv, 0, m.numel (),
                                                   reinterpret_cast<jint *>
-                                                  (m.fortran_vec ()));
+                                                  (m.rwdata ()));
                       retval = m;
                       break;
                     }
@@ -1558,7 +1567,7 @@
                                             mID)));
                       jni_env->GetIntArrayRegion (dv, 0, m.numel (),
                                                   reinterpret_cast<jint *>
-                                                  (m.fortran_vec ()));
+                                                  (m.rwdata ()));
                       retval = m;
                       break;
                     }
@@ -1613,7 +1622,7 @@
                 {
                   Matrix m (1, len);
                   jni_env->GetDoubleArrayRegion (jarr, 0, len,
-                                                 m.fortran_vec ());
+                                                 m.rwdata ());
                   retval = m;
                 }
               else
@@ -1648,7 +1657,7 @@
                           m.resize (cols, rows);
                         }
                       jni_env->GetDoubleArrayRegion
-                      (row, 0, cols, m.fortran_vec () + r * cols);
+                      (row, 0, cols, m.rwdata () + r * cols);
                     }
                   retval = m.transpose ();
                 }
@@ -1826,7 +1835,7 @@
     {
       Matrix m = val.matrix_value ();
       jdoubleArray dv = jni_env->NewDoubleArray (m.numel ());
-      jni_env->SetDoubleArrayRegion (dv, 0, m.numel (), m.fortran_vec ());
+      jni_env->SetDoubleArrayRegion (dv, 0, m.numel (), m.rwdata ());
       jobj = dv;
       jcls = jni_env->GetObjectClass (jobj);
     }
@@ -1836,7 +1845,7 @@
     {
       jclass_ref mcls (jni_env, find_octave_class (jni_env,
                        "org/octave/Matrix"));
-      dim_vector dims = val.dims ();
+      const dim_vector& dims = val.dims ();
       jintArray_ref iv (jni_env, jni_env->NewIntArray (dims.ndims ()));
       jint *iv_data = jni_env->GetIntArrayElements (jintArray (iv), nullptr);
 
@@ -1850,7 +1859,7 @@
           NDArray m = val.array_value ();
           jdoubleArray_ref dv (jni_env, jni_env->NewDoubleArray (m.numel ()));
           jni_env->SetDoubleArrayRegion (jdoubleArray (dv), 0, m.numel (),
-                                         m.fortran_vec ());
+                                         m.rwdata ());
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([D[I)V");
           jobj = jni_env->NewObject (jclass (mcls), mID, jdoubleArray (dv),
                                      jintArray (iv));
@@ -1862,7 +1871,7 @@
           jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
           jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
                                        reinterpret_cast<jbyte *>
-                                       (m.fortran_vec ()));
+                                       (m.rwdata ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
           jobj = jni_env->NewObject
                  (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
@@ -1874,7 +1883,7 @@
           jbyteArray_ref bv (jni_env, jni_env->NewByteArray (m.numel ()));
           jni_env->SetByteArrayRegion (jbyteArray (bv), 0, m.numel (),
                                        reinterpret_cast<jbyte *>
-                                       (m.fortran_vec ()));
+                                       (m.rwdata ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([B[I)V");
           jobj = jni_env->NewObject
                  (jclass (mcls), mID, jbyteArray (bv), jintArray (iv));
@@ -1886,7 +1895,7 @@
           jintArray_ref v (jni_env, jni_env->NewIntArray (m.numel ()));
           jni_env->SetIntArrayRegion (jintArray (v), 0, m.numel (),
                                       reinterpret_cast<jint *>
-                                      (m.fortran_vec ()));
+                                      (m.rwdata ()));
           jmethodID mID = jni_env->GetMethodID (mcls, "<init>", "([I[I)V");
           jobj = jni_env->NewObject
                  (jclass (mcls), mID, jintArray (v), jintArray (iv));
@@ -2183,7 +2192,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::dims");
 
 #endif
 }
@@ -2248,7 +2257,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::subsref");
 
 #endif
 }
@@ -2338,7 +2347,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::subsasgn");
 
 #endif
 }
@@ -2360,7 +2369,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::map_keys");
 
 #endif
 }
@@ -2386,7 +2395,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::convert_to_str_internal");
 
 #endif
 }
@@ -2496,7 +2505,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaMethod");
 
 #endif
 }
@@ -2517,7 +2526,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaMethod");
 
 #endif
 }
@@ -2577,7 +2586,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaMethod");
 
 #endif
 }
@@ -2600,7 +2609,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaMethod");
 
 #endif
 }
@@ -2656,7 +2665,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaObject");
 
 #endif
 }
@@ -2677,7 +2686,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_javaObject");
 
 #endif
 }
@@ -2723,7 +2732,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_get");
 
 #endif
 }
@@ -2742,7 +2751,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_get");
 
 #endif
 }
@@ -2790,7 +2799,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_get");
 
 #endif
 }
@@ -2811,7 +2820,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_get");
 
 #endif
 }
@@ -2858,7 +2867,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_set");
 
 #endif
 }
@@ -2878,7 +2887,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_set");
 
 #endif
 }
@@ -2929,7 +2938,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_set");
 
 #endif
 }
@@ -2952,7 +2961,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::do_java_set");
 
 #endif
 }
@@ -3002,7 +3011,7 @@
   // This shouldn't happen because construction of octave_java
   // objects is supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::init");
 
 #endif
 }
@@ -3031,7 +3040,7 @@
   // This shouldn't happen because construction of octave_java objects is
   // supposed to be impossible if Java is not available.
 
-  panic_impossible ();
+  error_unexpected ("octave_java::release");
 
 #endif
 }
--- a/libinterp/octave-value/ov-lazy-idx.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-lazy-idx.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 // Lazy indices that stay in idx_vector form until the conversion to NDArray is
 // actually needed.
 
-class
-OCTINTERP_API
-octave_lazy_index : public octave_base_value
+class OCTINTERP_API octave_lazy_index : public octave_base_value
 {
 public:
 
@@ -277,7 +275,7 @@
   static octave_base_value *
   numeric_conversion_function (const octave_base_value&);
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-legacy-range.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-legacy-range.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -50,8 +50,7 @@
 #include "ls-hdf5.h"
 #include "ls-utils.h"
 
-class
-Range
+class Range
 {
 public:
 
--- a/libinterp/octave-value/ov-legacy-range.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-legacy-range.h	Fri Apr 12 15:10:26 2024 +0200
@@ -57,8 +57,7 @@
 // of this type used by the interpreter.  The action of maybe_mutate is
 // performed by octave_legacy_range::try_narrowing_conversion.
 
-class
-octave_legacy_range : public octave_base_value
+class octave_legacy_range : public octave_base_value
 {
 public:
 
@@ -105,7 +104,7 @@
 
   std::unique_ptr<Range> m_range;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-magic-int.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-magic-int.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -216,7 +216,7 @@
 }
 
 template <typename T>
-OCTAVE_NORETURN bool
+bool
 octave_base_magic_int<T>::load_ascii (std::istream&)
 {
   error ("octave_base_magic_int<T>::load_ascii: internal error");
@@ -232,7 +232,7 @@
 }
 
 template <typename T>
-OCTAVE_NORETURN bool
+bool
 octave_base_magic_int<T>::load_binary (std::istream&, bool,
                                        octave::mach_info::float_format)
 {
--- a/libinterp/octave-value/ov-magic-int.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-magic-int.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,8 +47,7 @@
 // type conversion.
 
 template <typename T>
-class
-octave_base_magic_int : public octave_base_scalar<T>
+class octave_base_magic_int : public octave_base_scalar<T>
 {
 public:
 
@@ -275,9 +274,7 @@
   octave_value map (octave_base_value::unary_mapper_t umap) const;
 };
 
-class
-OCTINTERP_API
-octave_magic_uint : public octave_base_magic_int<octave_uint64>
+class OCTINTERP_API octave_magic_uint : public octave_base_magic_int<octave_uint64>
 {
 public:
 
@@ -298,12 +295,10 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
-class
-OCTINTERP_API
-octave_magic_int : public octave_base_magic_int<octave_int64>
+class OCTINTERP_API octave_magic_int : public octave_base_magic_int<octave_int64>
 {
 public:
 
@@ -324,7 +319,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-mex-fcn.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-mex-fcn.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,8 +47,7 @@
 
 // Dynamically-linked functions.
 
-class
-octave_mex_function : public octave_function
+class octave_mex_function : public octave_function
 {
 public:
 
@@ -122,7 +121,7 @@
   // on the file to see if it has changed.
   bool m_is_system_fcn_file;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-null-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-null-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 
 // The special [] value.
 
-class
-OCTINTERP_API
-octave_null_matrix : public octave_matrix
+class OCTINTERP_API octave_null_matrix : public octave_matrix
 {
   octave_null_matrix () : octave_matrix () { }
 
@@ -58,14 +56,12 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 // The special "" value
 
-class
-OCTINTERP_API
-octave_null_str : public octave_char_matrix_str
+class OCTINTERP_API octave_null_str : public octave_char_matrix_str
 {
   octave_null_str () : octave_char_matrix_str () { }
 
@@ -82,14 +78,12 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 // The special '' value
 
-class
-OCTINTERP_API
-octave_null_sq_str : public octave_char_matrix_sq_str
+class OCTINTERP_API octave_null_sq_str : public octave_char_matrix_sq_str
 {
   octave_null_sq_str () : octave_char_matrix_sq_str () { }
 
@@ -107,7 +101,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-oncleanup.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-oncleanup.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -54,7 +54,7 @@
         {
           octave::tree_parameter_list *pl = uptr->parameter_list ();
 
-          if (pl != nullptr && pl->length () > 0)
+          if (pl != nullptr && pl->size () > 0)
             warning ("onCleanup: cleanup action takes parameters");
         }
     }
--- a/libinterp/octave-value/ov-oncleanup.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-oncleanup.h	Fri Apr 12 15:10:26 2024 +0200
@@ -99,7 +99,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 
 protected:
 
--- a/libinterp/octave-value/ov-perm.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-perm.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -62,7 +62,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_perm_matrix::subsref - please report this bug");
     }
 
   return retval.next_subsref (type, idx);
@@ -397,7 +397,7 @@
 
   MArray<octave_idx_type> m (dim_vector (sz, 1));
 
-  if (! is.read (reinterpret_cast<char *> (m.fortran_vec ()), m.byte_size ()))
+  if (! is.read (reinterpret_cast<char *> (m.rwdata ()), m.byte_size ()))
     return false;
 
   if (swap)
@@ -442,7 +442,7 @@
 bool
 octave_perm_matrix::print_as_scalar () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   return (dv.all_ones () || dv.any_zero ());
 }
--- a/libinterp/octave-value/ov-perm.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-perm.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 #include "ov-typeinfo.h"
 #include "ovl.h"
 
-class
-OCTINTERP_API
-octave_perm_matrix : public octave_base_value
+class OCTINTERP_API octave_perm_matrix : public octave_base_value
 {
 public:
   octave_perm_matrix () : m_matrix (), m_dense_cache () { }
@@ -265,7 +263,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-range-traits.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-range-traits.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,8 +44,7 @@
 #include "ov-uint8.h"
 
 template <typename T>
-class
-octave_value_range_traits
+class octave_value_range_traits
 {
 public:
   typedef T scalar_type;
@@ -53,8 +52,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<bool>
+class octave_value_range_traits<bool>
 {
 public:
   typedef octave_bool scalar_type;
@@ -62,8 +60,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<float>
+class octave_value_range_traits<float>
 {
 public:
   typedef octave_float_scalar scalar_type;
@@ -71,8 +68,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<double>
+class octave_value_range_traits<double>
 {
 public:
   typedef octave_scalar scalar_type;
@@ -80,8 +76,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_int8>
+class octave_value_range_traits<octave_int8>
 {
 public:
   typedef octave_int8_scalar scalar_type;
@@ -89,8 +84,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_int16>
+class octave_value_range_traits<octave_int16>
 {
 public:
   typedef octave_int16_scalar scalar_type;
@@ -98,8 +92,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_int32>
+class octave_value_range_traits<octave_int32>
 {
 public:
   typedef octave_int32_scalar scalar_type;
@@ -107,8 +100,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_int64>
+class octave_value_range_traits<octave_int64>
 {
 public:
   typedef octave_int64_scalar scalar_type;
@@ -116,8 +108,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_uint8>
+class octave_value_range_traits<octave_uint8>
 {
 public:
   typedef octave_uint8_scalar scalar_type;
@@ -125,8 +116,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_uint16>
+class octave_value_range_traits<octave_uint16>
 {
 public:
   typedef octave_uint16_scalar scalar_type;
@@ -134,8 +124,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_uint32>
+class octave_value_range_traits<octave_uint32>
 {
 public:
   typedef octave_uint32_scalar scalar_type;
@@ -143,8 +132,7 @@
 };
 
 template <>
-class
-octave_value_range_traits<octave_uint64>
+class octave_value_range_traits<octave_uint64>
 {
 public:
   typedef octave_uint64_scalar scalar_type;
--- a/libinterp/octave-value/ov-range.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-range.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -163,7 +163,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in ov_range<T>::subsref - please report this bug");
     }
 
   return retval.next_subsref (type, idx);
--- a/libinterp/octave-value/ov-range.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-range.h	Fri Apr 12 15:10:26 2024 +0200
@@ -86,15 +86,14 @@
   int m_base = 0;
   int m_increment = 0;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 // For now, we only need ov_range<double> but we don't attempt to
 // enforce that restriction.
 
 template <typename T>
-class
-ov_range : public octave_base_value
+class ov_range : public octave_base_value
 {
 public:
 
@@ -523,10 +522,10 @@
 
   static octave_hdf5_id hdf5_save_type;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
-DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, double)
+DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS_API (ov_range, double, OCTINTERP_API)
 
 // For now, enable only ov_range<double>.
 
--- a/libinterp/octave-value/ov-re-diag.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-diag.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -296,7 +296,7 @@
     }
 
   DiagMatrix m (r, c);
-  double *re = m.fortran_vec ();
+  double *re = m.rwdata ();
   octave_idx_type len = m.length ();
   read_doubles (is, re, static_cast<save_type> (tmp), len, swap, fmt);
 
--- a/libinterp/octave-value/ov-re-diag.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-diag.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 // Real diagonal matrix values.
 
-class
-OCTINTERP_API
-octave_diag_matrix
+class OCTINTERP_API octave_diag_matrix
   : public octave_base_diag<DiagMatrix, Matrix>
 {
 public:
@@ -110,7 +108,7 @@
   bool chk_valid_scalar (const octave_value&,
                          double&) const;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-re-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -63,8 +63,6 @@
 #include "oct-stream.h"
 #include "ops.h"
 #include "ov-base.h"
-#include "ov-base-mat.h"
-#include "ov-base-mat.cc"
 #include "ov-scalar.h"
 #include "ov-re-mat.h"
 #include "ov-flt-re-mat.h"
@@ -85,8 +83,6 @@
 #include "ls-hdf5.h"
 
 
-template class octave_base_matrix<NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_matrix, "matrix", "double");
 
 static octave_base_value *
@@ -431,7 +427,7 @@
 octave_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nel = dv.numel ();
 
   charNDArray chm (dv);
@@ -473,7 +469,7 @@
 bool
 octave_matrix::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dv.ndims () > 2)
     {
@@ -567,10 +563,10 @@
       else if (nr == 0 || nc == 0)
         m_matrix = Matrix (nr, nc);
       else
-        panic_impossible ();
+        error ("unexpected dimensions in octave_matrix::load_ascii - please report this bug");
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -579,7 +575,7 @@
 octave_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -659,7 +655,7 @@
         return false;
 
       NDArray m(dv);
-      double *re = m.fortran_vec ();
+      double *re = m.rwdata ();
       read_doubles (is, re, static_cast<save_type> (tmp), dv.numel (),
                     swap, fmt);
 
@@ -679,7 +675,7 @@
       if (! is.read (reinterpret_cast<char *> (&tmp), 1))
         return false;
       Matrix m (nr, nc);
-      double *re = m.fortran_vec ();
+      double *re = m.rwdata ();
       octave_idx_type len = static_cast<octave_idx_type> (nr) * nc;
       read_doubles (is, re, static_cast<save_type> (tmp), len, swap, fmt);
 
@@ -699,7 +695,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -825,7 +821,7 @@
     }
 
   NDArray m (dv);
-  double *re = m.fortran_vec ();
+  double *re = m.rwdata ();
   if (H5Dread (data_hid, H5T_NATIVE_DOUBLE, octave_H5S_ALL, octave_H5S_ALL,
                octave_H5P_DEFAULT, re) >= 0)
     {
--- a/libinterp/octave-value/ov-re-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,9 @@
 
 // Real matrix values.
 
-class
-OCTINTERP_API
-octave_matrix : public octave_base_matrix<NDArray>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_matrix<NDArray>;
+
+class OCTINTERP_API octave_matrix : public octave_base_matrix<NDArray>
 {
 public:
 
@@ -246,7 +246,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-re-sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -162,7 +162,7 @@
 octave_sparse_matrix::convert_to_str_internal (bool, bool, char type) const
 {
   octave_value retval;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nel = dv.numel ();
 
   if (nel == 0)
@@ -222,7 +222,7 @@
 bool
 octave_sparse_matrix::save_binary (std::ostream& os, bool save_as_floats)
 {
-  dim_vector dv = this->dims ();
+  const dim_vector& dv = this->dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -364,7 +364,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
--- a/libinterp/octave-value/ov-re-sparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-re-sparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,7 @@
 
 class octave_value_list;
 
-class
-OCTINTERP_API
-octave_sparse_matrix : public octave_base_sparse<SparseMatrix>
+class OCTINTERP_API octave_sparse_matrix : public octave_base_sparse<SparseMatrix>
 {
 public:
 
@@ -150,7 +148,7 @@
 private:
   octave_value map (double (*fcn) (double)) const;
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-scalar.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-scalar.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,8 +46,6 @@
 #include "ov-scalar.h"
 #include "ov-float.h"
 #include "ov-base.h"
-#include "ov-base-scalar.h"
-#include "ov-base-scalar.cc"
 #include "ov-re-mat.h"
 #include "ov-typeinfo.h"
 #include "pr-output.h"
@@ -59,13 +57,6 @@
 #include "ls-oct-text.h"
 #include "ls-hdf5.h"
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<float>;
-
-template class octave_base_scalar<double>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_scalar, "scalar", "double");
 
 static octave_base_value *
--- a/libinterp/octave-value/ov-scalar.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-scalar.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,6 @@
 #include <iosfwd>
 #include <string>
 
-#include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "lo-utils.h"
 #include "mx-base.h"
@@ -49,9 +48,9 @@
 
 // Real scalar values.
 
-class
-OCTINTERP_API
-octave_scalar : public octave_base_scalar<double>
+extern template class OCTINTERP_EXTERN_TEMPLATE_API octave_base_scalar<double>;
+
+class OCTINTERP_API octave_scalar : public octave_base_scalar<double>
 {
 public:
 
@@ -82,7 +81,7 @@
   { return octave::idx_vector (scalar); }
 
   octave_value any (int = 0) const
-  { return (scalar != 0 && ! lo_ieee_isnan (scalar)); }
+  { return (scalar != 0 && ! octave::math::isnan (scalar)); }
 
   builtin_type_t builtin_type () const { return btyp_double; }
 
@@ -288,7 +287,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-str-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-str-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -312,7 +312,7 @@
     }
 
   std::string tname = type_name ();
-  dim_vector dv = m_matrix.dims ();
+  const dim_vector& dv = m_matrix.dims ();
   std::string dimstr = dv.str ();
   return "[" + dimstr + " " + tname + "]";
 }
@@ -320,7 +320,7 @@
 bool
 octave_char_matrix_str::save_ascii (std::ostream& os)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () > 2)
     {
       charNDArray tmp = char_array_value ();
@@ -344,8 +344,7 @@
           os << "# length: " << len << "\n";
           std::string tstr = chm.row_as_string (i);
           const char *tmp = tstr.data ();
-          if (tstr.length () > len)
-            panic_impossible ();
+          panic_if (tstr.length () > len);
           os.write (tmp, len);
           os << "\n";
         }
@@ -391,7 +390,7 @@
         m_matrix = tmp;
       else
         {
-          char *ftmp = tmp.fortran_vec ();
+          char *ftmp = tmp.rwdata ();
 
           octave::skip_preceeding_newline (is);
 
@@ -423,7 +422,7 @@
           // buffer so that we can properly handle
           // embedded NUL characters.
           charMatrix tmp (1, len);
-          char *ptmp = tmp.fortran_vec ();
+          char *ptmp = tmp.rwdata ();
 
           if (len > 0 && ! is.read (ptmp, len))
             error ("load: failed to load string constant");
@@ -451,7 +450,7 @@
           // Use this instead of a C-style character buffer so
           // that we can properly handle embedded NUL characters.
           charMatrix tmp (1, len);
-          char *ptmp = tmp.fortran_vec ();
+          char *ptmp = tmp.rwdata ();
 
           if (len > 0 && ! is.read (ptmp, len))
             error ("load: failed to load string constant");
@@ -463,7 +462,7 @@
         }
     }
   else
-    panic_impossible ();
+    error ("unexpected dimensions keyword (= '%s') octave_char_matrix::load_ascii - please report this bug", kw.c_str ());
 
   return true;
 }
@@ -472,7 +471,7 @@
 octave_char_matrix_str::save_binary (std::ostream& os,
                                      bool /* save_as_floats */)
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -529,7 +528,7 @@
         }
 
       charNDArray m(dv);
-      char *tmp = m.fortran_vec ();
+      char *tmp = m.rwdata ();
       is.read (tmp, dv.numel ());
 
       if (! is)
@@ -549,7 +548,7 @@
           if (swap)
             swap_bytes<4> (&len);
           charMatrix btmp (1, len);
-          char *pbtmp = btmp.fortran_vec ();
+          char *pbtmp = btmp.rwdata ();
           if (! is.read (pbtmp, len))
             return false;
           if (len > max_len)
@@ -572,7 +571,7 @@
 
 #if defined (HAVE_HDF5)
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int empty = save_hdf5_empty (loc_id, name, dv);
   if (empty)
     return (empty > 0);
@@ -680,7 +679,7 @@
         }
 
       charNDArray m (dv);
-      char *str = m.fortran_vec ();
+      char *str = m.rwdata ();
       if (H5Dread (data_hid, H5T_NATIVE_CHAR, octave_H5S_ALL, octave_H5S_ALL,
                    octave_H5P_DEFAULT, str) >= 0)
         {
--- a/libinterp/octave-value/ov-str-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-str-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,9 +48,7 @@
 // Character matrix values with special properties for use as
 // strings.
 
-class
-OCTINTERP_API
-octave_char_matrix_str : public octave_char_matrix
+class OCTINTERP_API octave_char_matrix_str : public octave_char_matrix
 {
 public:
 
@@ -181,13 +179,12 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 typedef octave_char_matrix_str octave_char_matrix_dq_str;
 
-class
-octave_char_matrix_sq_str : public octave_char_matrix_str
+class octave_char_matrix_sq_str : public octave_char_matrix_str
 {
 public:
 
@@ -267,7 +264,7 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-struct.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-struct.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -190,7 +190,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_struct::subsref - please report this bug");
     }
 
   // FIXME: perhaps there should be an
@@ -259,7 +259,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_struct::subsref - please report this bug");
     }
 
   // FIXME: perhaps there should be an
@@ -434,7 +434,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in octave_struct::subsasgn - please report this bug");
         }
     }
 
@@ -559,7 +559,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_struct::subsasgn - please report this bug");
     }
 
   retval.maybe_mutate ();
@@ -634,7 +634,7 @@
       increment_indent_level ();
 
       indent (os);
-      dim_vector dv = dims ();
+      const dim_vector& dv = dims ();
       os << dv.str () << " struct array containing the fields:";
       newline (os);
 
@@ -727,7 +727,7 @@
     }
 
   std::string tname = val.type_name ();
-  dim_vector dv = val.dims ();
+  const dim_vector& dv = val.dims ();
   std::string dimstr = dv.str ();
   return "[" + dimstr + " " + tname + "]";
 }
@@ -833,7 +833,7 @@
   else if (len == 0)
     m_map = octave_map (dv);
   else
-    panic_impossible ();
+    error ("unexpected: len < 0 in octave_struct::load_ascii - please report this bug");
 
   return success;
 }
@@ -845,7 +845,7 @@
 
   octave_idx_type nf = m.nfields ();
 
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 1)
     return false;
 
@@ -1382,7 +1382,7 @@
             {
               indent (os);
               os << key;
-              dim_vector dv = val.dims ();
+              const dim_vector& dv = val.dims ();
               os << ": " << dv.str () << ' ' << val.type_name ();
               newline (os);
             }
@@ -1443,7 +1443,7 @@
   octave_value val = m_map.contents (r);
 
   std::string tname = val.type_name ();
-  dim_vector dv = val.dims ();
+  const dim_vector& dv = val.dims ();
   std::string dimstr = dv.str ();
   return "[" + dimstr + " " + tname + "]";
 }
@@ -1519,7 +1519,7 @@
   else if (len == 0)
     m_map = octave_scalar_map ();
   else
-    panic_impossible ();
+    error ("unexpected: len < 0 in octave_scalar_struct::load_ascii - please report this bug");
 
   return true;
 }
@@ -1860,7 +1860,7 @@
     {
       if (args(i).iscell ())
         {
-          dim_vector argdims (args(i).dims ());
+          const dim_vector& argdims = args(i).dims ();
 
           if (! scalar (argdims))
             {
--- a/libinterp/octave-value/ov-struct.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-struct.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,7 @@
 
 // Data structures.
 
-class
-octave_struct : public octave_base_value
+class octave_struct : public octave_base_value
 {
 public:
 
@@ -170,11 +169,10 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
-class
-octave_scalar_struct : public octave_base_value
+class octave_scalar_struct : public octave_base_value
 {
 public:
 
@@ -297,7 +295,7 @@
 
   octave_value to_array ();
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov-typeinfo.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-typeinfo.h	Fri Apr 12 15:10:26 2024 +0200
@@ -39,9 +39,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-type_info
+class OCTINTERP_API type_info
 {
 public:
 
--- a/libinterp/octave-value/ov-uint16.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-uint16.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,8 +46,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-uint16.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -60,21 +58,8 @@
 octave_hdf5_id octave_uint16_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_uint16_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<uint16NDArray>;
-
-template class octave_base_int_matrix<uint16NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint16_matrix,
                                      "uint16 matrix", "uint16");
 
-template class octave_base_scalar<octave_uint16>;
-
-template class octave_base_int_scalar<octave_uint16>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint16_scalar,
                                      "uint16 scalar", "uint16");
--- a/libinterp/octave-value/ov-uint32.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-uint32.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-uint32.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_uint32_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_uint32_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<uint32NDArray>;
-
-template class octave_base_int_matrix<uint32NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint32_matrix,
                                      "uint32 matrix", "uint32");
 
-template class octave_base_scalar<octave_uint32>;
-
-template class octave_base_int_scalar<octave_uint32>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint32_scalar,
                                      "uint32 scalar", "uint32");
--- a/libinterp/octave-value/ov-uint64.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-uint64.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-uint64.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_uint64_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_uint64_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<uint64NDArray>;
-
-template class octave_base_int_matrix<uint64NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint64_matrix,
                                      "uint64 matrix", "uint64");
 
-template class octave_base_scalar<octave_uint64>;
-
-template class octave_base_int_scalar<octave_uint64>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint64_scalar,
                                      "uint64 scalar", "uint64");
--- a/libinterp/octave-value/ov-uint8.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-uint8.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,6 @@
 #  define HDF5_SAVE_TYPE 0
 #endif
 
-#include "ov-base-int.h"
-#include "ov-base-int.cc"
 #include "ov-uint8.h"
 #include "pr-output.h"
 #include "variables.h"
@@ -59,21 +57,8 @@
 octave_hdf5_id octave_uint8_matrix::s_hdf5_save_type = HDF5_SAVE_TYPE;
 octave_hdf5_id octave_uint8_scalar::s_hdf5_save_type = HDF5_SAVE_TYPE;
 
-// Prevent implicit instantiations on some systems (Windows, others?)
-// that can lead to duplicate definitions of static data members.
-
-extern template class octave_base_scalar<double>;
-
-template class octave_base_matrix<uint8NDArray>;
-
-template class octave_base_int_matrix<uint8NDArray>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint8_matrix,
                                      "uint8 matrix", "uint8");
 
-template class octave_base_scalar<octave_uint8>;
-
-template class octave_base_int_scalar<octave_uint8>;
-
 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_uint8_scalar,
                                      "uint8 scalar", "uint8");
--- a/libinterp/octave-value/ov-usr-fcn.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,6 +27,8 @@
 #  include "config.h"
 #endif
 
+#include <iostream>
+
 #include <sstream>
 
 #include "file-info.h"
@@ -40,12 +42,15 @@
 #include "defun.h"
 #include "error.h"
 #include "errwarn.h"
+#include "filepos.h"
 #include "input.h"
 #include "ovl.h"
 #include "ov-usr-fcn.h"
 #include "ov.h"
 #include "pager.h"
+#include "pt-cmd.h"
 #include "pt-eval.h"
+#include "pt-id.h"
 #include "pt-jump.h"
 #include "pt-misc.h"
 #include "pt-pr-code.h"
@@ -84,6 +89,16 @@
   delete m_file_info;
 }
 
+octave::filepos octave_user_code::beg_pos () const
+{
+  return m_cmd_list->beg_pos ();
+}
+
+octave::filepos octave_user_code::end_pos () const
+{
+  return m_cmd_list->end_pos ();
+}
+
 void
 octave_user_code::get_file_info ()
 {
@@ -210,18 +225,8 @@
 // Ugh.  This really needs to be simplified (code/data?
 // extrinsic/intrinsic state?).
 
-octave_user_function::octave_user_function
-(const octave::symbol_scope& scope, octave::tree_parameter_list *pl,
- octave::tree_parameter_list *rl, octave::tree_statement_list *cl)
-  : octave_user_code ("", "", scope, cl, ""),
-    m_param_list (pl), m_ret_list (rl),
-    m_lead_comm (), m_trail_comm (),
-    m_location_line (0), m_location_column (0),
-    m_system_fcn_file (false),
-    m_num_named_args (m_param_list ? m_param_list->length () : 0),
-    m_subfunction (false), m_inline_function (false),
-    m_anonymous_function (false), m_nested_function (false),
-    m_class_constructor (none), m_class_method (none)
+octave_user_function::octave_user_function (const octave::symbol_scope& scope, octave::tree_identifier *id, octave::tree_parameter_list *pl, octave::tree_parameter_list *rl, octave::tree_statement_list *cl)
+  : octave_user_code ("", "", scope, cl, ""), m_id (id), m_param_list (pl), m_ret_list (rl), m_num_named_args (m_param_list ? m_param_list->size () : 0)
 {
   if (m_cmd_list)
     m_cmd_list->mark_as_function_body ();
@@ -229,10 +234,32 @@
 
 octave_user_function::~octave_user_function ()
 {
+  delete m_id;
   delete m_param_list;
   delete m_ret_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
+}
+
+std::string
+octave_user_function::signature () const
+{
+  std::ostringstream buf;
+
+  octave::tree_print_code tpc (buf);
+
+  if (m_ret_list)
+    {
+      m_ret_list->accept (tpc);
+      buf << " = ";
+    }
+
+  buf << m_name << " ";
+
+  if (m_param_list)
+    m_param_list->accept (tpc);
+  else
+    buf << " ()";
+
+  return buf.str ();
 }
 
 octave_user_function *
@@ -243,17 +270,51 @@
   return this;
 }
 
+void
+octave_user_function::attach_trailing_comments (const octave::comment_list& lst)
+{
+  if (m_cmd_list && ! m_cmd_list->empty ())
+    {
+      octave::tree_statement *last_stmt = m_cmd_list->back ();
+
+      octave::tree_command *cmd = last_stmt->command ();
+
+      octave::tree_no_op_command *no_op_cmd = dynamic_cast <octave::tree_no_op_command *> (cmd);
+
+      if (no_op_cmd && (no_op_cmd->is_end_of_fcn_or_script () || no_op_cmd->is_end_of_file ()))
+        no_op_cmd->attach_trailing_comments (lst);
+    }
+}
+
+octave::comment_list octave_user_function::trailing_comments () const
+{
+  if (m_cmd_list && ! m_cmd_list->empty ())
+    {
+      octave::tree_statement *last_stmt = m_cmd_list->back ();
+
+      octave::tree_command *cmd = last_stmt->command ();
+
+      octave::tree_no_op_command *no_op_cmd = dynamic_cast <octave::tree_no_op_command *> (cmd);
+
+      if (no_op_cmd && (no_op_cmd->is_end_of_fcn_or_script () || no_op_cmd->is_end_of_file ()))
+        return no_op_cmd->trailing_comments ();
+    }
+
+  return octave::comment_list ();
+}
+
 // If there is no explicit end statement at the end of the function,
 // relocate the no_op that was generated for the end of file condition
 // to appear on the next line after the last statement in the file, or
 // the next line after the function keyword if there are no statements.
-// More precisely, the new location should probably be on the next line
-// after the end of the parameter list, but we aren't tracking that
-// information (yet).
 
 void
 octave_user_function::maybe_relocate_end_internal ()
 {
+  // This shouldn't happen, but check and return early anyway.
+  if (m_anonymous_function)
+    return;
+
   if (m_cmd_list && ! m_cmd_list->empty ())
     {
       octave::tree_statement *last_stmt = m_cmd_list->back ();
@@ -261,28 +322,37 @@
       if (last_stmt && last_stmt->is_end_of_fcn_or_script ()
           && last_stmt->is_end_of_file ())
         {
-          octave::tree_statement_list::reverse_iterator
-          next_to_last_elt = m_cmd_list->rbegin ();
-
+          octave::tree_statement_list::reverse_iterator next_to_last_elt = m_cmd_list->rbegin ();
           next_to_last_elt++;
 
-          int new_eof_line;
-          int new_eof_col;
+          octave::filepos new_eof_pos;
 
           if (next_to_last_elt == m_cmd_list->rend ())
             {
-              new_eof_line = beginning_line ();
-              new_eof_col = beginning_column ();
+              // Empty function body, just the end statement.  Set the
+              // new beginning of that statement to the end of the
+              // argument list (if any) or the end of the function name.
+
+              // M_ID is only nullptr if this is an anonymous function
+              // and we shouldn't be updating the end position for that.
+              // So if there is no name and no parameter list, just
+              // return early.
+
+              if (m_param_list)
+                new_eof_pos = m_param_list->end_pos ();
+              else if (m_id)
+                new_eof_pos = m_id->end_pos ();
+              else
+                return;
             }
           else
             {
               octave::tree_statement *next_to_last_stmt = *next_to_last_elt;
 
-              new_eof_line = next_to_last_stmt->line ();
-              new_eof_col = next_to_last_stmt->column ();
+              new_eof_pos = next_to_last_stmt->end_pos ();
             }
 
-          last_stmt->set_location (new_eof_line + 1, new_eof_col);
+          last_stmt->update_end_pos (new_eof_pos);
         }
     }
 }
@@ -317,9 +387,14 @@
 {
   std::ostringstream result;
 
+  octave::filepos bp = beg_pos ();
+
+  int bp_line = bp.line ();
+  int bp_column = bp.column ();
+
   if (is_anonymous_function ())
     result << "anonymous@" << fcn_file_name ()
-           << ':' << m_location_line << ':' << m_location_column;
+           << ':' << bp_line << ':' << bp_column;
   else if (is_subfunction ())
     result << parent_fcn_name () << '>' << name ();
   else if (is_class_method ())
@@ -328,7 +403,7 @@
     result << '@' << name ();
   else if (is_inline_function ())
     result << "inline@" << fcn_file_name ()
-           << ':' << m_location_line << ':' << m_location_column;
+           << ':' << bp_line << ':' << bp_column;
   else
     result << name ();
 
@@ -504,7 +579,7 @@
 octave_user_function::special_expr ()
 {
   panic_unless (is_special_expr ());
-  panic_if (m_cmd_list->length () != 1);
+  panic_if (m_cmd_list->size () != 1);
 
   octave::tree_statement *stmt = m_cmd_list->front ();
   return stmt->expression ();
@@ -516,8 +591,8 @@
   bool retval = false;
   if (Voptimize_subsasgn_calls
       && m_param_list && m_ret_list
-      && m_param_list->length () > 0 && ! m_param_list->varargs_only ()
-      && m_ret_list->length () == 1 && ! m_ret_list->takes_varargs ())
+      && m_param_list->size () > 0 && ! m_param_list->varargs_only ()
+      && m_ret_list->size () == 1 && ! m_ret_list->takes_varargs ())
     {
       octave::tree_identifier *par1 = m_param_list->front ()->ident ();
       octave::tree_identifier *ret1 = m_ret_list->front ()->ident ();
@@ -584,20 +659,23 @@
 octave_value
 octave_user_function::dump () const
 {
+  octave::filepos bp = beg_pos ();
+  octave::filepos ep = end_pos ();
+
   std::map<std::string, octave_value> m
-  = {{ "user_code", octave_user_code::dump () },
-    { "line", m_location_line },
-    { "col", m_location_column },
-    { "end_line", m_end_location_line },
-    { "end_col", m_end_location_column },
-    { "system_fcn_file", m_system_fcn_file },
-    { "num_named_args", m_num_named_args },
-    { "subfunction", m_subfunction },
-    { "inline_function", m_inline_function },
-    { "anonymous_function", m_anonymous_function },
-    { "nested_function", m_nested_function },
-    { "ctor_type", ctor_type_str () },
-    { "class_method", m_class_method }
+    = {{ "user_code", octave_user_code::dump () },
+       { "line", bp.line () },
+       { "col", bp.column () },
+       { "end_line", ep.line () },
+       { "end_col", ep.column () },
+       { "system_fcn_file", m_system_fcn_file },
+       { "num_named_args", m_num_named_args },
+       { "subfunction", m_subfunction },
+       { "inline_function", m_inline_function },
+       { "anonymous_function", m_anonymous_function },
+       { "nested_function", m_nested_function },
+       { "ctor_type", ctor_type_str () },
+       { "class_method", m_class_method }
   };
 
   return octave_value (m);
@@ -631,11 +709,11 @@
 
   if (val.is_defined ())
     {
-      // Fail spectacularly if SAVED_WARNING_STATES is not an
-      // octave_map (or octave_scalar_map) object.
+      // Fail if SAVED_WARNING_STATES is not an octave_map (or
+      // octave_scalar_map) object.
 
       if (! val.isstruct ())
-        panic_impossible ();
+        error ("unexpected: SAVED_WARNING_STATES is not a struct in octave_user_function::restore_warning_states - please report this bug");
 
       octave_map m = val.map_value ();
 
@@ -721,7 +799,7 @@
 
       tree_parameter_list *m_param_list = ufcn->parameter_list ();
 
-      retval = (m_param_list ? m_param_list->length () : 0);
+      retval = (m_param_list ? m_param_list->size () : 0);
       if (ufcn->takes_varargs ())
         retval = -1 - retval;
     }
@@ -843,7 +921,7 @@
 
       tree_parameter_list *m_ret_list = ufcn->return_list ();
 
-      retval = (m_ret_list ? m_ret_list->length () : 0);
+      retval = (m_ret_list ? m_ret_list->size () : 0);
 
       if (ufcn->takes_var_return ())
         retval = -1 - retval;
--- a/libinterp/octave-value/ov-usr-fcn.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov-usr-fcn.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,10 +31,12 @@
 #include <string>
 
 #include "comment-list.h"
+#include "filepos.h"
 #include "ovl.h"
 #include "ov-fcn.h"
 #include "ov-typeinfo.h"
 #include "symscope.h"
+#include "token.h"
 #include "unwind-prot.h"
 
 class string_vector;
@@ -43,8 +45,10 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class filepos;
 class file_info;
 class stack_frame;
+class tree_identifier;
 class tree_parameter_list;
 class tree_statement_list;
 class tree_evaluator;
@@ -53,8 +57,7 @@
 
 OCTAVE_END_NAMESPACE(octave)
 
-class
-octave_user_code : public octave_function
+class octave_user_code : public octave_function
 {
 protected:
 
@@ -79,6 +82,9 @@
 
   bool is_user_code () const { return true; }
 
+  octave::filepos beg_pos () const;
+  octave::filepos end_pos () const;
+
   std::string get_code_line (std::size_t line);
 
   std::deque<std::string> get_code_lines (std::size_t line,
@@ -146,8 +152,7 @@
 
 // Scripts.
 
-class
-octave_user_script : public octave_user_code
+class octave_user_script : public octave_user_code
 {
 public:
 
@@ -194,25 +199,25 @@
 
 private:
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 // User-defined functions.
 
-class
-octave_user_function : public octave_user_code
+class octave_user_function : public octave_user_code
 {
 public:
 
-  octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope::anonymous (),
-                        octave::tree_parameter_list *pl = nullptr,
-                        octave::tree_parameter_list *rl = nullptr,
-                        octave::tree_statement_list *cl = nullptr);
+  octave_user_function (const octave::symbol_scope& scope = octave::symbol_scope::anonymous (), octave::tree_identifier *id = nullptr,
+                        octave::tree_parameter_list *pl = nullptr, octave::tree_parameter_list *rl = nullptr, octave::tree_statement_list *cl = nullptr);
 
   OCTAVE_DISABLE_COPY_MOVE (octave_user_function)
 
   ~octave_user_function ();
 
+  // Declared calling form, generated from the parse tree.
+  std::string signature () const;
+
   octave_function * function_value (bool = false) { return this; }
 
   octave_user_function * user_function_value (bool = false) { return this; }
@@ -223,32 +228,18 @@
 
   octave_user_function * define_ret_list (octave::tree_parameter_list *t);
 
-  void stash_fcn_location (int line, int col)
-  {
-    m_location_line = line;
-    m_location_column = col;
-  }
-
-  int beginning_line () const { return m_location_line; }
-  int beginning_column () const { return m_location_column; }
+  void set_fcn_tok (const octave::token& fcn_tok) { m_fcn_tok = fcn_tok; }
+  void set_eq_tok (const octave::token& eq_tok) { m_eq_tok = eq_tok; }
 
-  void stash_fcn_end_location (int line, int col)
-  {
-    m_end_location_line = line;
-    m_end_location_column = col;
-  }
+  void attach_trailing_comments (const octave::comment_list& lst);
 
-  int ending_line () const { return m_end_location_line; }
-  int ending_column () const { return m_end_location_column; }
+  octave::filepos beg_pos () const { return m_fcn_tok.beg_pos(); }
+  // The end_pos function is defined in the octave_user_code class.
 
   void maybe_relocate_end ();
 
   void stash_parent_fcn_scope (const octave::symbol_scope& ps);
 
-  void stash_leading_comment (octave::comment_list *lc) { m_lead_comm = lc; }
-
-  void stash_trailing_comment (octave::comment_list *tc) { m_trail_comm = tc; }
-
   std::string profiler_name () const;
 
   std::string parent_fcn_name () const
@@ -385,9 +376,8 @@
 
   octave::tree_parameter_list * return_list () { return m_ret_list; }
 
-  octave::comment_list * leading_comment () { return m_lead_comm; }
-
-  octave::comment_list * trailing_comment () { return m_trail_comm; }
+  octave::comment_list leading_comments () const { return m_fcn_tok.leading_comments (); }
+  octave::comment_list trailing_comments () const;
 
   // If is_special_expr is true, retrieve the sigular expression that forms the
   // body.  May be null (even if is_special_expr is true).
@@ -411,6 +401,9 @@
   std::string ctor_type_str () const;
   std::string method_type_str () const;
 
+  // Name of this function.
+  octave::tree_identifier *m_id;
+
   // List of arguments for this function.  These are local variables.
   octave::tree_parameter_list *m_param_list;
 
@@ -418,43 +411,38 @@
   // this function.
   octave::tree_parameter_list *m_ret_list;
 
-  // The comments preceding the FUNCTION token.
-  octave::comment_list *m_lead_comm;
-
-  // The comments preceding the ENDFUNCTION token.
-  octave::comment_list *m_trail_comm;
+  // We don't keep track of an end token separately because functions
+  // may still be defined without an explicit END.  If there is an
+  // explicit END, the final statement will contain it.
 
-  // Location where this function was defined.
-  int m_location_line;
-  int m_location_column;
-  int m_end_location_line;
-  int m_end_location_column;
+  octave::token m_fcn_tok;
+  octave::token m_eq_tok;
 
   // True if this function came from a file that is considered to be a
   // system function.  This affects whether we check the time stamp
   // on the file to see if it has changed.
-  bool m_system_fcn_file;
+  bool m_system_fcn_file {false};
 
   // The number of arguments that have names.
   int m_num_named_args;
 
   // TRUE means this is a m_subfunction of a primary function.
-  bool m_subfunction;
+  bool m_subfunction {false};
 
   // TRUE means this is an inline function.
-  bool m_inline_function;
+  bool m_inline_function {false};
 
   // TRUE means this is an anonymous function.
-  bool m_anonymous_function;
+  bool m_anonymous_function {false};
 
   // TRUE means this is a nested function.
-  bool m_nested_function;
+  bool m_nested_function {false};
 
   // Enum describing whether this function is the constructor for class object.
-  class_method_type m_class_constructor;
+  class_method_type m_class_constructor {none};
 
   // Enum describing whether this function is a method for a class.
-  class_method_type m_class_method;
+  class_method_type m_class_method {none};
 
   void maybe_relocate_end_internal ();
 
@@ -467,7 +455,7 @@
 
   void restore_warning_states ();
 
-  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA_API (OCTINTERP_API)
 };
 
 #endif
--- a/libinterp/octave-value/ov.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -1058,9 +1058,14 @@
       m_rep = new octave_bool_matrix (mask, idx);
       break;
 
-    default:
-      panic_impossible ();
+    case octave::idx_vector::class_invalid:
+      error ("unexpected: invalid index in conversion to octave_value - please report this bug");
       break;
+
+      // We should have handled all possible enum values above.  Rely
+      // on compiler diagnostics to warn if we haven't.  For example,
+      // GCC's -Wswitch option, enabled by -Wall, will provide a
+      // warning.
     }
 
   // FIXME: needed?
@@ -1699,6 +1704,16 @@
 #endif
 }
 
+octave_idx_type
+octave_value::strict_idx_type_value (bool frc_str_conv) const
+{
+#if defined (OCTAVE_ENABLE_64)
+  return int64_value (true, frc_str_conv);
+#else
+  return int_value (true, frc_str_conv);
+#endif
+}
+
 Cell
 octave_value::cell_value () const
 {
@@ -2177,8 +2192,19 @@
 
 XVALUE_EXTRACTOR (octave_value_list, xlist_value, list_value)
 
+// Make some stricter versions of XVALUE_EXTRACTOR,
+// especially for parsing integer arguments that cannot be floating point.
+// See bug #65538.
+
+XVALUE_EXTRACTOR (int, yint_value, strict_int_value)
+
+XVALUE_EXTRACTOR (bool, ybool_value, strict_bool_value)
+
+XVALUE_EXTRACTOR (octave_idx_type, yidx_type_value, strict_idx_type_value)
+
 #undef XVALUE_EXTRACTOR
 
+
 octave_value
 octave_value::storable_value () const
 {
@@ -2565,7 +2591,7 @@
           return octave_scalar_map ();
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in octave_value::empty_conv - please report this bug");
         }
     }
   else
@@ -2957,9 +2983,8 @@
 
   double dval = val.double_value ();
   double intpart;
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<typename T::val_type>::max ())
-      + 1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<typename T::val_type>::max ()) + 1.0;
 
   if (dval >= out_of_range_top
       || dval < std::numeric_limits<typename T::val_type>::min ()
@@ -2994,8 +3019,7 @@
   // Map to unsigned.
   // Idea from https://stackoverflow.com/questions/10589559
 
-  static const UT offset
-    = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
+  static const UT offset = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
 
   UT au = static_cast<UT> (a) + offset;
   UT bu = static_cast<UT> (b) + offset;
@@ -3133,8 +3157,8 @@
       || (increment < 0 && base < limit))
     return 0;
 
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.0;
 
   double abs_increment = std::abs (increment);
 
--- a/libinterp/octave-value/ov.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ov.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,6 +36,8 @@
 #include <memory>
 #include <map>
 
+#include "panic.h"
+
 #include "data-conv.h"
 #include "idx-vector.h"
 #include "mach-info.h"
@@ -69,9 +71,7 @@
 #include "oct-stream.h"
 #include "ov-base.h"
 
-class
-OCTINTERP_API
-octave_value
+class OCTINTERP_API octave_value
 {
 public:
 
@@ -812,6 +812,9 @@
   int int_value (bool req_int = false, bool frc_str_conv = false) const
   { return m_rep->int_value (req_int, frc_str_conv); }
 
+  int strict_int_value (bool frc_str_conv = false) const
+  { return m_rep->int_value (true, frc_str_conv); }
+
   unsigned int
   uint_value (bool req_int = false, bool frc_str_conv = false) const
   { return m_rep->uint_value (req_int, frc_str_conv); }
@@ -838,6 +841,9 @@
   octave_idx_type
   idx_type_value (bool req_int = false, bool frc_str_conv = false) const;
 
+  octave_idx_type
+  strict_idx_type_value (bool frc_str_conv = false) const;
+
   double double_value (bool frc_str_conv = false) const
   { return m_rep->double_value (frc_str_conv); }
 
@@ -885,6 +891,9 @@
   bool bool_value (bool warn = false) const
   { return m_rep->bool_value (warn); }
 
+  bool strict_bool_value () const
+  { return m_rep->bool_value (true); }
+
   boolMatrix bool_matrix_value (bool warn = false) const
   { return m_rep->bool_matrix_value (warn); }
 
@@ -1104,6 +1113,8 @@
 
   OCTINTERP_API int xint_value (const char *fmt, ...) const;
 
+  OCTINTERP_API int yint_value (const char *fmt, ...) const;
+
   OCTINTERP_API unsigned int xuint_value (const char *fmt, ...) const;
 
   OCTINTERP_API int xnint_value (const char *fmt, ...) const;
@@ -1118,6 +1129,8 @@
 
   OCTINTERP_API octave_idx_type xidx_type_value (const char *fmt, ...) const;
 
+  OCTINTERP_API octave_idx_type yidx_type_value (const char *fmt, ...) const;
+
   OCTINTERP_API double xdouble_value (const char *fmt, ...) const;
 
   OCTINTERP_API float xfloat_value (const char *fmt, ...) const;
@@ -1152,6 +1165,8 @@
 
   OCTINTERP_API bool xbool_value (const char *fmt, ...) const;
 
+  OCTINTERP_API bool ybool_value (const char *fmt, ...) const;
+
   OCTINTERP_API boolMatrix xbool_matrix_value (const char *fmt, ...) const;
 
   OCTINTERP_API boolNDArray xbool_array_value (const char *fmt, ...) const;
@@ -1699,11 +1714,10 @@
 extern OCTINTERP_API void install_types (octave::type_info&);
 
 // Templated value extractors.
-// FIXME: would be more consistent to use panic_impossible(), rather than
-//        assert(), but including "error.h" leads to compilation errors.
+
 template <typename Value>
 inline Value octave_value_extract (const octave_value&)
-{ assert (false); }
+{ panic_impossible (); }
 
 #define DEF_VALUE_EXTRACTOR(VALUE,MPREFIX)                              \
   template <>                                                           \
@@ -1774,7 +1788,7 @@
   template <>                                                           \
   inline VALUE octave_value_extract<VALUE> (const octave_value&)        \
   {                                                                     \
-    assert (false);                                                     \
+    panic_impossible ();                                                \
     return DEFVAL;                                                      \
   }
 
--- a/libinterp/octave-value/ovl.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ovl.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -191,7 +191,7 @@
 
   for (octave_idx_type i = 0; i < n; i++)
     {
-      dim_vector dv = elem(i).dims ();
+      const dim_vector& dv = elem(i).dims ();
       if (! dv.all_ones ())
         return false;
     }
--- a/libinterp/octave-value/ovl.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave-value/ovl.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,9 +38,7 @@
 #include "ov.h"
 #include "Cell.h"
 
-class
-OCTINTERP_API
-octave_value_list
+class OCTINTERP_API octave_value_list
 {
 public:
 
--- a/libinterp/octave.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -85,6 +85,10 @@
           octave_print_terse_usage_and_exit ();
           break;
 
+        case 'G':
+          m_gui = false;
+          break;
+
         case 'H':
           m_read_history_file = false;
           break;
@@ -94,19 +98,35 @@
           break;
 
         case 'V':
-          m_verbose_flag = true;
+          m_init_trace = true;
           break;
 
-        case 'd':
-          // This is the same as yydebug in parse.y.
-          octave_debug++;
+        // FIXME: Disabled debug option for parser 2023-12-29.
+        // However, uncomment and restore option if Octave adds a debug option
+        // to immediately enter debug mode for a script.
+        // case 'd':
+        //   break;
+
+        case 'e':
+          if (octave_optarg_wrapper ())
+            {
+              if (m_code_to_eval.empty ())
+                m_code_to_eval = octave_optarg_wrapper ();
+              else
+                m_code_to_eval += (std::string (" ")
+                                   + octave_optarg_wrapper ());
+            }
           break;
 
         case 'f':
-          m_read_init_files = false;
+          m_read_user_files = false;
           m_read_site_files = false;
           break;
 
+        case 'g':
+          m_gui = true;
+          break;
+
         case 'h':
           octave_print_verbose_usage_and_exit ();
           break;
@@ -142,17 +162,6 @@
             m_doc_cache_file = octave_optarg_wrapper ();
           break;
 
-        case EVAL_OPTION:
-          if (octave_optarg_wrapper ())
-            {
-              if (m_code_to_eval.empty ())
-                m_code_to_eval = octave_optarg_wrapper ();
-              else
-                m_code_to_eval += (std::string (" ")
-                                   + octave_optarg_wrapper ());
-            }
-          break;
-
         case EXEC_PATH_OPTION:
           if (octave_optarg_wrapper ())
             m_exec_path = octave_optarg_wrapper ();
@@ -164,10 +173,6 @@
 #endif
           break;
 
-        case GUI_OPTION:
-          m_gui = true;
-          break;
-
         case IMAGE_PATH_OPTION:
           if (octave_optarg_wrapper ())
             m_image_path = octave_optarg_wrapper ();
@@ -187,12 +192,8 @@
           m_forced_line_editing = m_line_editing = true;
           break;
 
-        case NO_GUI_OPTION:
-          m_gui = false;
-          break;
-
-        case NO_INIT_FILE_OPTION:
-          m_read_init_files = false;
+        case NO_INIT_USER_OPTION:
+          m_read_user_files = false;
           break;
 
         case NO_INIT_PATH_OPTION:
@@ -203,7 +204,7 @@
           m_line_editing = false;
           break;
 
-        case NO_SITE_FILE_OPTION:
+        case NO_INIT_SITE_OPTION:
           m_read_site_files = false;
           break;
 
@@ -255,12 +256,16 @@
   m.assign ("no_window_system", no_window_system ());
   m.assign ("persist", persist ());
   m.assign ("read_history_file", read_history_file ());
-  m.assign ("read_init_files", read_init_files ());
+  // FIXME: read_init_files deprecated in Octave 10 in favor of read_user_files
+  m.assign ("read_init_files", read_user_files ());
+  m.assign ("read_user_files", read_user_files ());
   m.assign ("read_site_files", read_site_files ());
   m.assign ("server", server ());
   m.assign ("set_initial_path", set_initial_path ());
   m.assign ("traditional", traditional ());
-  m.assign ("verbose_flag", verbose_flag ());
+  m.assign ("init_trace", init_trace ());
+  // FIXME: --verbose deprecated in Octave 10.  Remove in Octave 12.
+  m.assign ("verbose", init_trace ());
   m.assign ("code_to_eval", code_to_eval ());
   m.assign ("command_line_path", string_vector (command_line_path ()));
   m.assign ("docstrings_file", docstrings_file ());
@@ -468,12 +473,12 @@
 For example, if you invoked Octave using the command
 
 @example
-octave --no-line-editing --silent
+octave --no-line-editing --quiet
 @end example
 
 @noindent
 @code{argv} would return a cell array of strings with the elements
-@option{--no-line-editing} and @option{--silent}.
+@option{--no-line-editing} and @option{--quiet}.
 
 If you write an executable Octave script, @code{argv} will return the list
 of arguments passed to the script.  @xref{Executable Octave Programs}, for
--- a/libinterp/octave.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/octave.h	Fri Apr 12 15:10:26 2024 +0200
@@ -67,12 +67,17 @@
   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 read_user_files () const { return m_read_user_files; }
+  OCTAVE_DEPRECATED (10, "cmdline_options::read_init_files is deprecated, use read_user_files")
+  bool read_init_files () const { return m_read_user_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; }
+
+  OCTAVE_DEPRECATED (10, "cmdline_options::verbose is deprecated, use init_trace")
+  bool verbose () const { return m_init_trace; }
+  bool init_trace () const { return m_init_trace; }
   std::string code_to_eval () const { return m_code_to_eval; }
   std::list<std::string> command_line_path () const
   { return m_command_line_path; }
@@ -99,12 +104,18 @@
   void no_window_system (bool arg) { m_no_window_system = arg; }
   void persist (bool arg) { m_persist = arg; }
   void read_history_file (bool arg) { m_read_history_file = arg; }
-  void read_init_files (bool arg) { m_read_init_files = arg; }
+  // FIXME: Alias for read_user_files() introduced in Octave 10.
+  // Remove at some point in the future.
   void read_site_files (bool arg) { m_read_site_files = arg; }
+  void read_user_files (bool arg) { m_read_user_files = arg; }
+  OCTAVE_DEPRECATED (10, "cmdline_options::read_init_files is deprecated, use read_user_files")
+  void read_init_files (bool arg) { read_user_files (arg); }
   void server (bool arg) { m_server = arg; }
   void set_initial_path (bool arg) { m_set_initial_path = arg; }
   void traditional (bool arg) { m_traditional = arg; }
-  void verbose_flag (bool arg) { m_verbose_flag = arg; }
+  OCTAVE_DEPRECATED (10, "cmdline_options::verbose is deprecated, use init_trace")
+  void verbose (bool arg) { m_init_trace = arg; }
+  void init_trace (bool arg) { m_init_trace = arg; }
   void code_to_eval (const std::string& arg) { m_code_to_eval = arg; }
   void command_line_path (const std::list<std::string>& arg)
   { m_command_line_path = arg; }
@@ -163,11 +174,11 @@
   bool m_read_history_file = true;
 
   // TRUE means we read ~/.octaverc and ./.octaverc.
-  // (--norc; --no-init-file; -f)
-  bool m_read_init_files = true;
+  // (--no-init-user; --no-init-file; --norc; -f)
+  bool m_read_user_files = true;
 
   // TRUE means we read the site-wide octaverc files.
-  // (--norc; --no-site-file; -f)
+  // (--no-init-site; --no-site-file; --norc; -f)
   bool m_read_site_files = true;
 
   // If TRUE, start the command server.
@@ -182,9 +193,10 @@
   // (--traditional)
   bool m_traditional = false;
 
-  // If TRUE, print verbose info in some cases.
-  // (--verbose; -V)
-  bool m_verbose_flag = false;
+  // If TRUE, print trace of files read during initialization
+  // (--init-trace, --verbose; -V)
+  // FIXME: --verbose and -V will eventually be deprecated and removed.
+  bool m_init_trace = false;
 
   // The code to evaluate at startup
   // (--eval CODE)
--- a/libinterp/operators/op-int.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/operators/op-int.h	Fri Apr 12 15:10:26 2024 +0200
@@ -702,8 +702,8 @@
   static octave_value                                           \
   elem_xpow (const T1 ## NDArray& a, const T2 ## NDArray& b)    \
   {                                                             \
-    dim_vector a_dims = a.dims ();                              \
-    dim_vector b_dims = b.dims ();                              \
+    const dim_vector& a_dims = a.dims ();                       \
+    const dim_vector& b_dims = b.dims ();                       \
     if (a_dims != b_dims)                                       \
       {                                                         \
         if (! is_valid_bsxfun ("operator .^", a_dims, b_dims))  \
@@ -723,8 +723,8 @@
   static octave_value                                           \
   elem_xpow (const T1 ## NDArray& a, const NDArray& b)          \
   {                                                             \
-    dim_vector a_dims = a.dims ();                              \
-    dim_vector b_dims = b.dims ();                              \
+    const dim_vector& a_dims = a.dims ();                       \
+    const dim_vector& b_dims = b.dims ();                       \
     if (a_dims != b_dims)                                       \
       {                                                         \
         if (! is_valid_bsxfun ("operator .^", a_dims, b_dims))  \
@@ -744,8 +744,8 @@
   static octave_value                                           \
   elem_xpow (const NDArray& a, const T2 ## NDArray& b)          \
   {                                                             \
-    dim_vector a_dims = a.dims ();                              \
-    dim_vector b_dims = b.dims ();                              \
+    const dim_vector& a_dims = a.dims ();                       \
+    const dim_vector& b_dims = b.dims ();                       \
     if (a_dims != b_dims)                                       \
       {                                                         \
         if (! is_valid_bsxfun ("operator .^", a_dims, b_dims))  \
@@ -765,8 +765,8 @@
   static octave_value                                           \
   elem_xpow (const T1 ## NDArray& a, const FloatNDArray& b)     \
   {                                                             \
-    dim_vector a_dims = a.dims ();                              \
-    dim_vector b_dims = b.dims ();                              \
+    const dim_vector& a_dims = a.dims ();                       \
+    const dim_vector& b_dims = b.dims ();                       \
     if (a_dims != b_dims)                                       \
       {                                                         \
         if (! is_valid_bsxfun ("operator .^", a_dims, b_dims))  \
@@ -786,8 +786,8 @@
   static octave_value                                           \
   elem_xpow (const FloatNDArray& a, const T2 ## NDArray& b)     \
   {                                                             \
-    dim_vector a_dims = a.dims ();                              \
-    dim_vector b_dims = b.dims ();                              \
+    const dim_vector& a_dims = a.dims ();                       \
+    const dim_vector& b_dims = b.dims ();                       \
     if (a_dims != b_dims)                                       \
       {                                                         \
         if (! is_valid_bsxfun ("operator .^", a_dims, b_dims))  \
--- a/libinterp/operators/op-mi.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/operators/op-mi.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -67,10 +67,10 @@
 
   uint64_t ival = val.value ();
 
-  static const uint64_t max_val
+  static constexpr uint64_t max_val
     = static_cast<uint64_t> (std::numeric_limits<int64_t>::max ());
 
-  static const uint64_t max_val_p1 = max_val + 1;
+  static constexpr uint64_t max_val_p1 = max_val + 1;
 
   if (ival <= max_val)
     {
@@ -84,7 +84,7 @@
       // should return int8(-128) but converting directly to int8 and
       // negating will not return the correct result.
 
-      static const int64_t min_signed_ival
+      static constexpr int64_t min_signed_ival
         = std::numeric_limits<int64_t>::min ();
 
       return octave_value (new octave_magic_int (min_signed_ival));
--- a/libinterp/operators/op-str-str.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/operators/op-str-str.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,8 +57,8 @@
   CONCAT2(oct_binop_, name) (const octave_base_value& a1,               \
                              const octave_base_value& a2)               \
   {                                                                     \
-    dim_vector a1_dims = a1.dims ();                                    \
-    dim_vector a2_dims = a2.dims ();                                    \
+    const dim_vector& a1_dims = a1.dims ();                             \
+    const dim_vector& a2_dims = a2.dims ();                             \
                                                                         \
     bool a1_is_scalar = a1_dims.all_ones ();                            \
     bool a2_is_scalar = a2_dims.all_ones ();                            \
--- a/libinterp/operators/op-struct.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/operators/op-struct.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -70,7 +70,7 @@
   OCTAVE_CAST_BASE_VALUE (const octave_matrix&, v2, a2);
 
   NDArray tmp = v2.array_value ();
-  dim_vector dv = tmp.dims ();
+  const dim_vector& dv = tmp.dims ();
 
   if (! dv.all_zero ())
     error ("invalid concatenation of structure with matrix");
@@ -87,7 +87,7 @@
   OCTAVE_CAST_BASE_VALUE (const octave_struct&, v2, a2);
 
   NDArray tmp = v1.array_value ();
-  dim_vector dv = tmp.dims ();
+  const dim_vector& dv = tmp.dims ();
 
   if (! dv.all_zero ())
     error ("invalid concatenation of structure with matrix");
--- a/libinterp/operators/ops.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/operators/ops.h	Fri Apr 12 15:10:26 2024 +0200
@@ -138,34 +138,37 @@
   }
 
 // FIXME: the following currently don't handle index.
-#define DEFNDASSIGNOP_OP(name, t1, t2, f, op)                           \
-  static octave_value                                                   \
-  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                 \
-                                 const octave_value_list& idx,          \
-                                 const octave_base_value& 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) ();                      \
-                                                                        \
-    return octave_value ();                                             \
+
+#define DEFNDASSIGNOP_OP(name, t1, t2, f, op)                                                           \
+  static octave_value                                                                                   \
+  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                                                 \
+                                 const octave_value_list& idx,                                          \
+                                 const octave_base_value& a2)                                           \
+  {                                                                                                     \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);                                            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);                                      \
+                                                                                                        \
+    if (! idx.empty ())                                                                                 \
+      error ("unexpected: index is not empty in oct_assignop_ " #name " - please report this bug");     \
+    v1.matrix_ref () op v2.CONCAT2 (f, _value) ();                                                      \
+                                                                                                        \
+    return octave_value ();                                                                             \
   }
 
-#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop)                       \
-  static octave_value                                                   \
-  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                 \
-                                 const octave_value_list& idx,          \
-                                 const octave_base_value& 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) ());                 \
-                                                                        \
-    return octave_value ();                                             \
+#define DEFNDASSIGNOP_FNOP(name, t1, t2, f, fnop)                                                       \
+  static octave_value                                                                                   \
+  CONCAT2 (oct_assignop_, name) (octave_base_value& a1,                                                 \
+                                 const octave_value_list& idx,                                          \
+                                 const octave_base_value& a2)                                           \
+  {                                                                                                     \
+    OCTAVE_CAST_BASE_VALUE (CONCAT2 (octave_, t1)&, v1, a1);                                            \
+    OCTAVE_CAST_BASE_VALUE (const CONCAT2 (octave_, t2)&, v2, a2);                                      \
+                                                                                                        \
+    if (! idx.empty ())                                                                                 \
+      error ("unexpected: index is not empty in oct_assignop_ " #name " - please report this bug");     \
+    fnop (v1.matrix_ref (), v2.CONCAT2 (f, _value) ());                                                 \
+                                                                                                        \
+    return octave_value ();                                                                             \
   }
 
 #define DEFASSIGNANYOP_FN(name, t1, f)                          \
--- a/libinterp/options.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/options.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,55 +33,71 @@
 // This is here so that it's more likely that the usage message and
 // the real set of options will agree.  Note: the '+' must come first
 // to prevent getopt from permuting arguments!
-static const char *short_opts = "+HWVdfhip:qvx";
+static const char *short_opts = "+GHWVde:fghip:qvx";
 
 // Long options.  See the comments in getopt.h for the meanings of the
 // fields in this structure.
 #define BUILT_IN_DOCSTRINGS_FILE_OPTION 1
 #define DOC_CACHE_FILE_OPTION 2
-#define EVAL_OPTION 3
-#define EXEC_PATH_OPTION 4
-#define EXPERIMENTAL_TERMINAL_WIDGET_OPTION 5
-#define GUI_OPTION 6
-#define IMAGE_PATH_OPTION 7
-#define INFO_FILE_OPTION 8
-#define INFO_PROG_OPTION 9
-#define LINE_EDITING_OPTION 10
-#define NO_GUI_OPTION 11
-#define NO_GUI_LIBS_OPTION 12
-#define NO_INIT_FILE_OPTION 13
-#define NO_INIT_PATH_OPTION 14
-#define NO_LINE_EDITING_OPTION 15
-#define NO_SITE_FILE_OPTION 16
-#define PERSIST_OPTION 17
-#define SERVER_OPTION 18
-#define TEXI_MACROS_FILE_OPTION 19
-#define TRADITIONAL_OPTION 20
+#define EXEC_PATH_OPTION 3
+#define EXPERIMENTAL_TERMINAL_WIDGET_OPTION 4
+#define IMAGE_PATH_OPTION 5
+#define INFO_FILE_OPTION 6
+#define INFO_PROG_OPTION 7
+#define LINE_EDITING_OPTION 8
+#define NO_GUI_LIBS_OPTION 9
+#define NO_INIT_USER_OPTION 10
+#define NO_INIT_PATH_OPTION 11
+#define NO_LINE_EDITING_OPTION 12
+#define NO_INIT_SITE_OPTION 13
+#define PERSIST_OPTION 14
+#define SERVER_OPTION 15
+#define TEXI_MACROS_FILE_OPTION 16
+#define TRADITIONAL_OPTION 17
 struct octave_getopt_options long_opts[] =
 {
+  // Alias for --traditional, not displayed in help
   { "braindead",                octave_no_arg,       nullptr, TRADITIONAL_OPTION },
+  // Option for developers, not displayed in help
   { "built-in-docstrings-file", octave_required_arg, nullptr, BUILT_IN_DOCSTRINGS_FILE_OPTION },
-  { "debug",                    octave_no_arg,       nullptr, 'd' },
+  // FIXME: Disabled debug option for parser 2023-12-29.
+  // Uncomment and restore code if Octave adds capability to
+  // immediately enter debug mode for a script.
+  // { "debug",                    octave_no_arg,       nullptr, 'd' },
+  // Option for developers, not displayed in help
   { "doc-cache-file",           octave_required_arg, nullptr, DOC_CACHE_FILE_OPTION },
   { "echo-commands",            octave_no_arg,       nullptr, 'x' },
-  { "eval",                     octave_required_arg, nullptr, EVAL_OPTION },
+  { "eval",                     octave_required_arg, nullptr, 'e' },
+  // Option for developers, not displayed in help
   { "exec-path",                octave_required_arg, nullptr, EXEC_PATH_OPTION },
   { "experimental-terminal-widget", octave_no_arg,   nullptr, EXPERIMENTAL_TERMINAL_WIDGET_OPTION },
-  { "force-gui",                octave_no_arg,       nullptr, GUI_OPTION },
-  { "gui",                      octave_no_arg,       nullptr, GUI_OPTION },
+  // Alias for --gui, not displayed in help, eventually will be deprecated
+  { "force-gui",                octave_no_arg,       nullptr, 'g' },
+  { "gui",                      octave_no_arg,       nullptr, 'g' },
   { "help",                     octave_no_arg,       nullptr, 'h' },
+  // Option for developers, not displayed in help
   { "image-path",               octave_required_arg, nullptr, IMAGE_PATH_OPTION },
+  // Option for developers, not displayed in help
   { "info-file",                octave_required_arg, nullptr, INFO_FILE_OPTION },
+  // Option for developers, not displayed in help
   { "info-program",             octave_required_arg, nullptr, INFO_PROG_OPTION },
+  // Option for developers, not displayed in help
+  { "init-trace",               octave_no_arg,       nullptr, 'V' },
   { "interactive",              octave_no_arg,       nullptr, 'i' },
   { "line-editing",             octave_no_arg,       nullptr, LINE_EDITING_OPTION },
-  { "no-gui",                   octave_no_arg,       nullptr, NO_GUI_OPTION },
+  { "no-gui",                   octave_no_arg,       nullptr, 'G' },
+  // Option for developers, not displayed in help
   { "no-gui-libs",              octave_no_arg,       nullptr, NO_GUI_LIBS_OPTION },
   { "no-history",               octave_no_arg,       nullptr, 'H' },
-  { "no-init-file",             octave_no_arg,       nullptr, NO_INIT_FILE_OPTION },
+  { "no-init-all",              octave_no_arg,       nullptr, 'f' },
+  // Alias for --no-init-user, not displayed in help
+  { "no-init-file",             octave_no_arg,       nullptr, NO_INIT_USER_OPTION },
   { "no-init-path",             octave_no_arg,       nullptr, NO_INIT_PATH_OPTION },
+  { "no-init-user",             octave_no_arg,       nullptr, NO_INIT_PATH_OPTION },
   { "no-line-editing",          octave_no_arg,       nullptr, NO_LINE_EDITING_OPTION },
-  { "no-site-file",             octave_no_arg,       nullptr, NO_SITE_FILE_OPTION },
+  { "no-init-site",             octave_no_arg,       nullptr, NO_INIT_SITE_OPTION },
+  // Alias for --no-init-site, not displayed in help
+  { "no-site-file",             octave_no_arg,       nullptr, NO_INIT_SITE_OPTION },
   { "no-window-system",         octave_no_arg,       nullptr, 'W' },
   { "norc",                     octave_no_arg,       nullptr, 'f' },
   { "path",                     octave_required_arg, nullptr, 'p' },
@@ -89,8 +105,10 @@
   { "quiet",                    octave_no_arg,       nullptr, 'q' },
   { "server",                   octave_no_arg,       nullptr, SERVER_OPTION },
   { "silent",                   octave_no_arg,       nullptr, 'q' },
+  // Option for developers, not displayed in help
   { "texi-macros-file",         octave_required_arg, nullptr, TEXI_MACROS_FILE_OPTION },
   { "traditional",              octave_no_arg,       nullptr, TRADITIONAL_OPTION },
+  // Alias for --init-trace, not displayed in help, eventually will be deprecated
   { "verbose",                  octave_no_arg,       nullptr, 'V' },
   { "version",                  octave_no_arg,       nullptr, 'v' },
   { nullptr,                    0,                   nullptr, 0 }
--- a/libinterp/parse-tree/anon-fcn-validator.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/anon-fcn-validator.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-anon_fcn_validator::anon_fcn_validator (tree_parameter_list *,
-                                        tree_expression *expr)
-  : m_ok (true), m_line (-1), m_column (-1), m_message ()
+anon_fcn_validator::anon_fcn_validator (tree_parameter_list *, tree_expression *expr)
 {
   expr->accept (*this);
 }
@@ -80,10 +78,9 @@
 anon_fcn_validator::error (tree_expression& expr)
 {
   m_ok = false;
-  m_line = expr.line ();
-  m_column = expr.column ();
-  m_message
-    = "invalid use of operator " + expr.oper () + " in anonymous function";
+  m_beg_pos = expr.beg_pos ();
+  m_end_pos = expr.end_pos ();
+  m_message = "invalid use of operator " + expr.oper () + " in anonymous function";
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/anon-fcn-validator.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/anon-fcn-validator.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,6 +30,7 @@
 
 #include <string>
 
+#include "filepos.h"
 #include "pt-walk.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
@@ -59,16 +60,16 @@
 
   bool ok () const { return m_ok; }
 
-  int line () const { return m_line; }
-  int column () const { return m_column; }
+  filepos beg_pos () const { return m_beg_pos; }
+  filepos end_pos () const { return m_end_pos; }
 
   std::string message () const { return m_message; }
 
 private:
 
-  bool m_ok;
-  int m_line;
-  int m_column;
+  bool m_ok {true};
+  filepos m_beg_pos;
+  filepos m_end_pos;
   std::string m_message;
 
   void error (tree_expression& expr);
--- a/libinterp/parse-tree/bp-table.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/bp-table.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -305,7 +305,7 @@
                    "condition is not empty, but has nothing to evaluate");
           else
             {
-              if (stmt_list->length () == 1
+              if (stmt_list->size () == 1
                   && (stmt = stmt_list->front ())
                   && stmt->is_expression ())
                 {
@@ -370,6 +370,9 @@
       // allow "in" and "at" to be implicit
       if (args(pos).is_string ())
         {
+          // Default value.
+          tok = dbstop_in;
+
           std::string arg = args(pos).string_value ();
           if (arg == "in")
             {
@@ -386,10 +389,16 @@
               tok = dbstop_if;
               pos++;
             }
-          else if (atoi (args(pos).string_value ().c_str ()) > 0)
-            tok = dbstop_at;
           else
-            tok = dbstop_in;
+            {
+              try
+                {
+                  if (std::stoi (args(pos).string_value ()) > 0)
+                    tok = dbstop_at;
+                }
+              catch (const std::invalid_argument&) { }
+              catch (const std::out_of_range&) { }
+            }
         }
       else
         tok = dbstop_at;
@@ -431,8 +440,27 @@
               // FIXME: we really want to distinguish number
               // vs. method name here.
 
-              if (atoi (arg.c_str ()) == 0)
+              // FIXME: I'm not sure what the
+
+              bool int_conv_ok = true;
+
+              try
+                {
+                  if (std::stoi (arg) == 0)
+                    int_conv_ok = false;
+                }
+              catch (const std::invalid_argument&)
                 {
+                  int_conv_ok = false;
+                }
+              catch (const std::out_of_range&)
+                {
+                  int_conv_ok = false;
+                }
+
+              if (! int_conv_ok)
+                {
+                  // Assume we are looking at a function name.
                   // We have class and function names but already
                   // stored the class name in fcn_name.
                   class_name = fcn_name;
@@ -458,12 +486,25 @@
             {
               if (args(pos).is_string ())
                 {
-                  int line = atoi (args(pos).string_value ().c_str ());
+                  std::string str = args(pos).string_value ();
+
+                  try
+                    {
+                      int line = std::stoi (str);
 
-                  if (line > 0)
-                    lines.insert (line);
-                  else
-                    break;        // may be "if" or a method name
+                      if (line > 0)
+                        lines.insert (line);
+                      else
+                        break; // may be "if" or a method name
+                    }
+                  catch (const std::invalid_argument&)
+                    {
+                      break; // may be "if" or a method name
+                    }
+                  catch (const std::out_of_range&)
+                    {
+                      error ("dbstop: location value out of range '%s'", str.c_str ());
+                    }
                 }
               else if (args(pos).isnumeric ())
                 {
@@ -624,12 +665,10 @@
 
 // Return the sub/nested/main function of MAIN_FCN that contains
 // line number LINENO of the source file.
-// If END_LINE != 0, *END_LINE is set to last line of the returned function.
+// If FOUND_ENDING_LINE != 0, *FOUND_ENDING_LINE is set to last line of the returned function.
 
 static octave_user_code *
-find_fcn_by_line (octave_user_code *main_fcn,
-                  int lineno,
-                  int *end_line = nullptr)
+find_fcn_by_line (octave_user_code *main_fcn, int lineno, int *found_end_line = nullptr)
 {
   octave_user_code *retval = nullptr;
   octave_user_code *next_fcn = nullptr;  // 1st function starting after lineno
@@ -645,21 +684,26 @@
           auto *dbg_subfcn = str_val_p.second.user_function_value ();
 
           // Check if lineno is within dbg_subfcn.
-          // FIXME: we could break when beginning_line() > lineno,
+          // FIXME: we could break when the beginning line > lineno,
           // but that makes the code "fragile"
           // if the order of walking subfcns changes,
           // for a minor speed improvement in non-critical code.
-          if (dbg_subfcn->ending_line () < earliest_end
-              && dbg_subfcn->ending_line () >= lineno
-              && dbg_subfcn->beginning_line () <= lineno)
+
+          filepos beg_pos = dbg_subfcn->beg_pos ();
+          filepos end_pos = dbg_subfcn->end_pos ();
+
+          int beginning_line = beg_pos.line ();
+          int ending_line = end_pos.line ();
+
+          if (ending_line < earliest_end && ending_line >= lineno && beginning_line <= lineno)
             {
-              earliest_end = dbg_subfcn->ending_line ();
+              earliest_end = ending_line;
               retval = find_fcn_by_line (dbg_subfcn, lineno, &earliest_end);
             }
 
           // Find the first fcn starting after lineno.
           // This is used if line is not inside any function.
-          if (dbg_subfcn->beginning_line () >= lineno && ! next_fcn)
+          if (beginning_line >= lineno && ! next_fcn)
             next_fcn = dbg_subfcn;
         }
     }
@@ -668,8 +712,11 @@
   // or in the main function, which we check now.
   if (main_fcn->is_user_function ())
     {
-      int e = dynamic_cast<octave_user_function *> (main_fcn)->ending_line ();
-      if (e >= lineno && e < earliest_end)
+      filepos end_pos = dynamic_cast<octave_user_function *> (main_fcn)->end_pos ();
+
+      int ending_line = end_pos.line ();
+
+      if (ending_line >= lineno && ending_line < earliest_end)
         retval = main_fcn;
 
       if (! retval)
@@ -681,8 +728,8 @@
         retval = main_fcn;
     }
 
-  if (end_line && earliest_end < *end_line)
-    *end_line = earliest_end;
+  if (found_end_line && earliest_end < *found_end_line)
+    *found_end_line = earliest_end;
 
   return retval;
 }
--- a/libinterp/parse-tree/comment-list.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/comment-list.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -37,12 +37,7 @@
 comment_list *
 comment_list::dup () const
 {
-  comment_list *new_cl = new comment_list ();
-
-  for (const auto& elt : *this)
-    new_cl->append (elt);
-
-  return new_cl;
+  return new comment_list (*this);
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/comment-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/comment-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,10 +28,10 @@
 
 #include "octave-config.h"
 
+#include <list>
+#include <memory>
 #include <string>
 
-#include "base-list.h"
-
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 extern std::string get_comment_text ();
@@ -40,8 +40,7 @@
 
 extern void save_comment_text (const std::string& text);
 
-class
-comment_elt
+class comment_elt
 {
 public:
 
@@ -107,20 +106,45 @@
   bool m_uses_hash_char;
 };
 
-class
-comment_list : public base_list<comment_elt>
+class comment_list
 {
 public:
 
   OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (comment_list)
 
+  typedef std::list<comment_elt>::reference reference;
+  typedef std::list<comment_elt>::const_reference const_reference;
+
+  typedef std::list<comment_elt>::iterator iterator;
+  typedef std::list<comment_elt>::const_iterator const_iterator;
+
   void append (const comment_elt& elt)
-  { base_list<comment_elt>::append (elt); }
+  {
+    m_list.push_back (elt);
+  }
 
   void append (const std::string& s,
                comment_elt::comment_type t = comment_elt::unknown,
                bool uses_hash_char = false)
-  { append (comment_elt (s, t, uses_hash_char)); }
+  {
+    m_list.push_back (comment_elt (s, t, uses_hash_char));
+  }
+
+  void clear () { m_list.clear (); }
+
+  bool empty () const { return m_list.empty (); }
+
+  reference front () { return m_list.front (); }
+  reference back () { return m_list.back (); }
+
+  const_reference front () const { return m_list.front (); }
+  const_reference back () const { return m_list.back (); }
+
+  iterator begin () { return m_list.begin (); }
+  iterator end () { return m_list.end (); }
+
+  const_iterator begin () const { return m_list.begin (); }
+  const_iterator end () const { return m_list.end (); }
 
   comment_list * dup () const;
 
@@ -128,7 +152,7 @@
   // comments that doesn't look like a copyright statement.
   comment_elt find_doc_comment () const
   {
-    for (const auto& elt : *this)
+    for (const auto& elt : m_list)
       {
         // FIXME: should we also omit end-of-line comments?
         if (! elt.is_copyright ())
@@ -142,6 +166,10 @@
   {
     return find_doc_comment().text ();
   }
+
+private:
+
+  std::list<comment_elt> m_list;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/lex.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/lex.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,8 +48,7 @@
 
 // For communication between the lexer and parser.
 
-class
-lexical_feedback
+class lexical_feedback
 {
 public:
 
@@ -326,9 +325,12 @@
 
   void reset ();
 
-  int previous_token_value () const;
+  int previous_token_id () const;
+  token * previous_token ();
+  const token * previous_token () const;
 
-  bool previous_token_value_is (int tok_val) const;
+  bool previous_token_is (int tok_id) const;
+  bool previous_token_is (const token *tok) const;
 
   void mark_previous_token_trailing_space ();
 
@@ -481,7 +483,7 @@
   std::string m_current_input_line;
 
   // The text of the current comment, used to gather comment lines
-  // before storing in m_comment_buf.
+  // before storing in m_comment_list.
   std::string m_comment_text;
 
   // The text of functions entered on the command line.
@@ -524,8 +526,7 @@
 // initialize if everything is grouped in a parent class rather than
 // listing all the members in the base_lexer class.
 
-class
-base_lexer : public lexical_feedback
+class base_lexer : public lexical_feedback
 {
 public:
 
@@ -558,53 +559,8 @@
     bool m_eof;
   };
 
-  // Collect comment text.
-
-  class
-  comment_buffer
-  {
-  public:
-
-    comment_buffer () : m_comment_list (nullptr) { }
-
-    OCTAVE_DISABLE_COPY_MOVE (comment_buffer)
-
-    ~comment_buffer () { delete m_comment_list; }
-
-    void append (const std::string& s, comment_elt::comment_type t, bool uses_hash_char)
-    {
-      if (! m_comment_list)
-        m_comment_list = new comment_list ();
-
-      m_comment_list->append (s, t, uses_hash_char);
-    }
-
-    // Caller is expected to delete the returned value.
-
-    comment_list * get_comment ()
-    {
-      comment_list *retval = m_comment_list;
-
-      m_comment_list = nullptr;
-
-      return retval;
-    }
-
-    void reset ()
-    {
-      delete m_comment_list;
-
-      m_comment_list = nullptr;
-    }
-
-  private:
-
-    comment_list *m_comment_list;
-  };
-
   base_lexer (interpreter& interp)
-    : lexical_feedback (interp), m_scanner (nullptr), m_input_buf (),
-      m_comment_buf ()
+    : lexical_feedback (interp), m_scanner (nullptr), m_input_buf ()
   {
     init ();
   }
@@ -647,7 +603,7 @@
 
   bool inside_any_object_index ();
 
-  int make_keyword_token (const std::string& s);
+  token * make_keyword_token (const std::string& s);
 
   bool fq_identifier_contains_keyword (const std::string& s);
 
@@ -661,7 +617,12 @@
 
   void finish_comment (comment_elt::comment_type typ);
 
-  comment_list * get_comment () { return m_comment_buf.get_comment (); }
+  comment_list get_comment_list ()
+  {
+    comment_list retval = m_comment_list;
+    m_comment_list.clear ();
+    return retval;
+  }
 
   int handle_close_bracket (int bracket_type);
 
@@ -669,9 +630,9 @@
 
   int handle_superclass_identifier ();
 
-  int handle_meta_identifier ();
+  token * make_meta_identifier_token (const std::string& cls);
 
-  int handle_fq_identifier ();
+  token * make_fq_identifier_token (const std::string& ident);
 
   int handle_identifier ();
 
@@ -689,13 +650,17 @@
 
   void warn_deprecated_syntax (const std::string& msg);
 
+  int syntax_error (const std::string& msg);
+  int syntax_error (const std::string& msg, const filepos& pos);
+  int syntax_error (const std::string& msg, const filepos& beg_pos, const filepos& end_pos);
+
   void push_token (token *);
 
   token * current_token ();
 
   std::size_t pending_token_count () const;
 
-  void display_token (int tok);
+  void display_token (int tok_id);
 
   void fatal_error (const char *msg);
 
@@ -713,8 +678,8 @@
   // Object that reads and buffers input.
   input_buffer m_input_buf;
 
-  // Object that collects comment text.
-  comment_buffer m_comment_buf;
+  // List of collected comments.
+  comment_list m_comment_list;
 
   virtual std::string input_source () const { return "unknown"; }
 
@@ -736,27 +701,25 @@
 
   void display_start_state () const;
 
-  bool maybe_unput_comma_before_unary_op (int tok);
+  bool maybe_unput_comma_before_unary_op (int tok_id);
 
-  int handle_op (int tok, bool bos = false, bool compat = true);
+  int handle_op (int tok_id, bool bos = false, bool compat = true);
 
   int finish_command_arg ();
 
-  int handle_token (int tok, token *tok_val = nullptr);
-
-  int count_token (int tok);
+  int handle_token (int tok_id);
+  int handle_token (token *tok);
 
-  int count_token_internal (int tok);
+  int count_token_internal (int tok_id);
 
-  int show_token (int tok);
+  int show_token (int tok_id);
 
 protected:
 
   std::stack<int> start_state_stack;
 };
 
-class
-lexer : public base_lexer
+class lexer : public base_lexer
 {
 public:
 
@@ -825,8 +788,7 @@
 template <> int base_lexer::handle_number<10> ();
 template <> int base_lexer::handle_number<16> ();
 
-class
-push_lexer : public base_lexer
+class push_lexer : public base_lexer
 {
 public:
 
--- a/libinterp/parse-tree/lex.ll	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/lex.ll	Fri Apr 12 15:10:26 2024 +0200
@@ -168,22 +168,22 @@
 #define YY_FATAL_ERROR(msg)                     \
    (yyget_extra (yyscanner))->fatal_error (msg)
 
-#define CMD_OR_OP(PATTERN, TOK, COMPAT)                                 \
-   do                                                                   \
-     {                                                                  \
-       curr_lexer->lexer_debug (PATTERN);                               \
-                                                                        \
-       if (curr_lexer->looks_like_command_arg ())                       \
-         {                                                              \
-           yyless (0);                                                  \
-           curr_lexer->push_start_state (COMMAND_START);                \
-         }                                                              \
-       else                                                             \
-         return curr_lexer->handle_op (TOK, false, COMPAT);             \
-     }                                                                  \
+#define CMD_OR_OP(PATTERN, TOK_ID, COMPAT)                      \
+   do                                                           \
+     {                                                          \
+       curr_lexer->lexer_debug (PATTERN);                       \
+                                                                \
+       if (curr_lexer->looks_like_command_arg ())               \
+         {                                                      \
+           yyless (0);                                          \
+           curr_lexer->push_start_state (COMMAND_START);        \
+         }                                                      \
+       else                                                     \
+         return curr_lexer->handle_op (TOK_ID, false, COMPAT);  \
+     }                                                          \
    while (0)
 
-#define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT)                           \
+#define CMD_OR_UNARY_OP(PATTERN, TOK_ID, COMPAT)                        \
    do                                                                   \
      {                                                                  \
        curr_lexer->lexer_debug (PATTERN);                               \
@@ -196,17 +196,17 @@
                curr_lexer->push_start_state (COMMAND_START);            \
              }                                                          \
            else                                                         \
-             return curr_lexer->handle_op (TOK, false, COMPAT);         \
+             return curr_lexer->handle_op (TOK_ID, false, COMPAT);      \
          }                                                              \
        else                                                             \
          {                                                              \
-           if (curr_lexer->maybe_unput_comma_before_unary_op (TOK))     \
+           if (curr_lexer->maybe_unput_comma_before_unary_op (TOK_ID))  \
              {                                                          \
                yyless (0);                                              \
                curr_lexer->xunput (',');                                \
              }                                                          \
            else                                                         \
-             return curr_lexer->handle_op (TOK, false, COMPAT);         \
+             return curr_lexer->handle_op (TOK_ID, false, COMPAT);      \
          }                                                              \
      }                                                                  \
    while (0)
@@ -225,57 +225,57 @@
      }                                                  \
    while (0)
 
-// If we are at the end of the buffer, ask for more input.
-// If we are at the end of the file, deal with it.
-// Otherwise, just keep going with the text from the current buffer.
-#define HANDLE_STRING_CONTINUATION                      \
-   do                                                   \
-     {                                                  \
-       curr_lexer->m_filepos.next_line ();              \
-                                                        \
-       HANDLE_EOB_OR_EOF (-1);                          \
-     }                                                  \
+   // If we are at the end of the buffer, ask for more input.
+   // If we are at the end of the file, deal with it.
+   // Otherwise, just keep going with the text from the current buffer.
+#define HANDLE_STRING_CONTINUATION              \
+   do                                           \
+     {                                          \
+       curr_lexer->m_filepos.next_line ();      \
+                                                \
+       HANDLE_EOB_OR_EOF (-1);                  \
+     }                                          \
    while (0)
 
-#define HANDLE_NUMBER(PATTERN, BASE)                            \
-  do                                                            \
-    {                                                           \
-     curr_lexer->lexer_debug (PATTERN);                         \
-                                                                \
-     if (curr_lexer->previous_token_may_be_command ()           \
-         &&  curr_lexer->space_follows_previous_token ())       \
-       {                                                        \
-         yyless (0);                                            \
-         curr_lexer->push_start_state (COMMAND_START);          \
-       }                                                        \
-     else                                                       \
-       {                                                        \
-         int tok = curr_lexer->previous_token_value ();         \
-                                                                \
-         if (curr_lexer->whitespace_is_significant ()           \
-             && curr_lexer->space_follows_previous_token ()     \
-             && ! (tok == '[' || tok == '{'                     \
-                   || curr_lexer->previous_token_is_binop ()))  \
-           {                                                    \
-             yyless (0);                                        \
-             curr_lexer->xunput (',');                          \
-           }                                                    \
-         else                                                   \
-           return curr_lexer->handle_number<BASE> ();           \
-       }                                                        \
-    }                                                           \
-  while (0)
+#define HANDLE_NUMBER(PATTERN, BASE)                                    \
+   do                                                                   \
+     {                                                                  \
+       curr_lexer->lexer_debug (PATTERN);                               \
+                                                                        \
+       if (curr_lexer->previous_token_may_be_command ()                 \
+           &&  curr_lexer->space_follows_previous_token ())             \
+         {                                                              \
+           yyless (0);                                                  \
+           curr_lexer->push_start_state (COMMAND_START);                \
+         }                                                              \
+       else                                                             \
+         {                                                              \
+           int tok_id = curr_lexer->previous_token_id ();               \
+                                                                        \
+           if (curr_lexer->whitespace_is_significant ()                 \
+               && curr_lexer->space_follows_previous_token ()           \
+               && ! (tok_id == '[' || tok_id == '{'                     \
+                     || curr_lexer->previous_token_is_binop ()))        \
+             {                                                          \
+               yyless (0);                                              \
+               curr_lexer->xunput (',');                                \
+             }                                                          \
+           else                                                         \
+             return curr_lexer->handle_number<BASE> ();                 \
+         }                                                              \
+     }                                                                  \
+   while (0)
 
 #define HANDLE_IDENTIFIER(pattern, get_set)                             \
    do                                                                   \
      {                                                                  \
        curr_lexer->lexer_debug (pattern);                               \
                                                                         \
-       int tok = curr_lexer->previous_token_value ();                   \
+       int tok_id = curr_lexer->previous_token_id ();                   \
                                                                         \
        if (curr_lexer->whitespace_is_significant ()                     \
            && curr_lexer->space_follows_previous_token ()               \
-           && ! (tok == '[' || tok == '{'                               \
+           && ! (tok_id == '[' || tok_id == '{'                         \
                  || curr_lexer->previous_token_is_binop ()))            \
          {                                                              \
            yyless (0);                                                  \
@@ -590,9 +590,9 @@
       curr_lexer->warn_language_extension ("bare newline inside parentheses");
     else
       {
-        int tok = curr_lexer->previous_token_value ();
-
-        if (! (tok == ';' || tok == '[' || tok == '{'))
+        int tok_id = curr_lexer->previous_token_id ();
+
+        if (! (tok_id == ';' || tok_id == '[' || tok_id == '{'))
           curr_lexer->xunput (';');
       }
   }
@@ -655,9 +655,9 @@
     if (curr_lexer->whitespace_is_significant ()
         && curr_lexer->space_follows_previous_token ())
       {
-        int tok = curr_lexer->previous_token_value ();
-
-        if (! (tok == '[' || tok == '{'
+        int tok_id = curr_lexer->previous_token_id ();
+
+        if (! (tok_id == '[' || tok_id == '{'
                || curr_lexer->previous_token_is_binop ()))
           unput_comma = true;
       }
@@ -688,7 +688,7 @@
 
         curr_lexer->push_start_state (MATRIX_START);
 
-        return curr_lexer->count_token ('[');
+        return curr_lexer->handle_token ('[');
       }
   }
 
@@ -991,14 +991,11 @@
         curr_lexer->m_looking_for_object_index = true;
         curr_lexer->m_at_beginning_of_statement = false;
 
-        curr_lexer->push_token (new octave::token (DQ_STRING,
-                                                   curr_lexer->m_string_text,
-                                                   curr_lexer->m_tok_beg,
-                                                   curr_lexer->m_tok_end));
+        octave::token *tok = new octave::token (DQ_STRING, curr_lexer->m_string_text, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());
 
         curr_lexer->m_string_text = "";
 
-        return curr_lexer->count_token_internal (DQ_STRING);
+        return curr_lexer->handle_token (tok);
       }
   }
 
@@ -1008,19 +1005,14 @@
     curr_lexer->update_token_positions (yyleng);
 
     unsigned int result;
-    sscanf (yytext+1, "%o", &result);
+    if (sscanf (yytext+1, "%o", &result) != 1)
+      curr_lexer->fatal_error ("scanf failed in lexer rule <DQ_STRING_START>\\\\[0-7]{1,3} - please report this bug");
 
     if (result > 0xff)
       {
         // Use location of octal digits for error token.
-        octave::token *tok
-          = new octave::token (LEXICAL_ERROR,
-                               "invalid octal escape sequence in character string",
-                               curr_lexer->m_tok_beg, curr_lexer->m_tok_end);
-
-        curr_lexer->push_token (tok);
-
-        return curr_lexer->count_token_internal (LEXICAL_ERROR);
+        std::string msg {"invalid octal escape sequence in character string"};
+        return curr_lexer->syntax_error (msg);
       }
     else
       curr_lexer->m_string_text += static_cast<unsigned char> (result);
@@ -1032,7 +1024,8 @@
     curr_lexer->m_filepos.increment_column (yyleng);
 
     unsigned int result;
-    sscanf (yytext+2, "%x", &result);
+    if (sscanf (yytext+2, "%x", &result) != 1)
+      curr_lexer->fatal_error ("scanf failed in lexer rule <DQ_STRING_START>\\\\x[0-9a-fA-F]+ - please report this bug");
 
     // Truncate the value silently instead of checking the range like
     // we do for octal above.  This is to match C/C++ where any number
@@ -1121,16 +1114,8 @@
     curr_lexer->lexer_debug ("<DQ_STRING_START>{NL}");
 
     // Use current file position for error token.
-    octave::token *tok
-      = new octave::token (LEXICAL_ERROR,
-                           "unterminated character string constant",
-                           curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-    curr_lexer->push_token (tok);
-
-    curr_lexer->m_filepos.next_line ();
-
-    return curr_lexer->count_token_internal (LEXICAL_ERROR);
+    std::string msg {"unterminated character string constant"};
+    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
   }
 
 %{
@@ -1158,14 +1143,11 @@
         curr_lexer->m_looking_for_object_index = true;
         curr_lexer->m_at_beginning_of_statement = false;
 
-        curr_lexer->push_token (new octave::token (SQ_STRING,
-                                                   curr_lexer->m_string_text,
-                                                   curr_lexer->m_tok_beg,
-                                                   curr_lexer->m_tok_end));
+        octave::token *tok = new octave::token (SQ_STRING, curr_lexer->m_string_text, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());
 
         curr_lexer->m_string_text = "";
 
-        return curr_lexer->count_token_internal (SQ_STRING);
+        return curr_lexer->handle_token (tok);
       }
   }
 
@@ -1180,16 +1162,8 @@
     curr_lexer->lexer_debug ("<SQ_STRING_START>{NL}");
 
     // Use current file position for error token.
-    octave::token *tok
-      = new octave::token (LEXICAL_ERROR,
-                           "unterminated character string constant",
-                           curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-    curr_lexer->push_token (tok);
-
-    curr_lexer->m_filepos.next_line ();
-
-    return curr_lexer->count_token_internal (LEXICAL_ERROR);
+    std::string msg {"unterminated character string constant"};
+    return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
   }
 
 %{
@@ -1203,14 +1177,16 @@
 
     curr_lexer->update_token_positions (yyleng);
 
-    int id_tok = curr_lexer->handle_fq_identifier ();
-
-    if (id_tok >= 0)
-      {
-        curr_lexer->m_looking_for_object_index = true;
-
-        return curr_lexer->count_token_internal (id_tok);
-      }
+    std::string ident = yytext;
+
+    ident.erase (std::remove_if (ident.begin (), ident.end (), is_space_or_tab), ident.end ());
+
+    if (curr_lexer->fq_identifier_contains_keyword (ident))
+      return curr_lexer->syntax_error ("function, method, class, and package names may not be keywords");
+
+    octave::token *tok = curr_lexer->make_fq_identifier_token (ident);
+
+    return curr_lexer->handle_token (tok);
   }
 
 <FQ_IDENT_START>{S}+ {
@@ -1364,14 +1340,19 @@
       {
         curr_lexer->update_token_positions (yyleng);
 
-        int id_tok = curr_lexer->handle_meta_identifier ();
-
-        if (id_tok >= 0)
-          {
-            curr_lexer->m_looking_for_object_index = true;
-
-            return curr_lexer->count_token_internal (id_tok);
-          }
+        std::string txt = yytext;
+
+        txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab), txt.end ());
+
+        // Eliminate leading '?'
+        std::string cls = txt.substr (1);
+
+        if (curr_lexer->fq_identifier_contains_keyword (cls))
+          return curr_lexer->syntax_error ("class and package names may not be keywords");
+
+        octave::token *tok = curr_lexer->make_meta_identifier_token (cls);
+
+        return curr_lexer->handle_token (tok);
       }
   }
 
@@ -1387,11 +1368,11 @@
       }
     else
       {
-        int tok_val = curr_lexer->previous_token_value ();
+        int tok_id = curr_lexer->previous_token_id ();
 
         if (curr_lexer->whitespace_is_significant ()
             && curr_lexer->space_follows_previous_token ()
-            && ! (tok_val == '[' || tok_val == '{'
+            && ! (tok_id == '[' || tok_id == '{'
                   || curr_lexer->previous_token_is_binop ()))
           {
             yyless (0);
@@ -1410,7 +1391,7 @@
                 curr_lexer->m_looking_at_function_handle++;
                 curr_lexer->m_looking_for_object_index = false;
 
-                return curr_lexer->count_token ('@');
+                return curr_lexer->handle_token ('@');
               }
             else
               {
@@ -1421,22 +1402,16 @@
                 octave::token *tok;
 
                 if (octave::iskeyword (ident))
-                  tok = new octave::token (LEXICAL_ERROR,
-                                           "function handles may not refer to keywords",
-                                           curr_lexer->m_tok_beg,
-                                           curr_lexer->m_tok_end);
-                else
                   {
-                    curr_lexer->m_looking_for_object_index = true;
-
-                    tok = new octave::token (FCN_HANDLE, ident,
-                                             curr_lexer->m_tok_beg,
-                                             curr_lexer->m_tok_end);
+                    std::string msg {"function handles may not refer to keywords"};
+                    return curr_lexer->syntax_error (msg);
                   }
 
-                curr_lexer->push_token (tok);
-
-                return curr_lexer->count_token_internal (tok->token_value ());
+                curr_lexer->m_looking_for_object_index = true;
+
+                tok = new octave::token (FCN_HANDLE, ident, curr_lexer->m_tok_beg, curr_lexer->m_tok_end, curr_lexer->get_comment_list ());
+
+                return curr_lexer->handle_token (tok);
               }
           }
       }
@@ -1467,7 +1442,7 @@
 
         curr_lexer->m_at_beginning_of_statement = true;
 
-        return curr_lexer->count_token ('\n');
+        return curr_lexer->handle_token ('\n');
       }
     else if (curr_lexer->m_nesting_level.is_bracket_or_brace ())
       {
@@ -1475,14 +1450,8 @@
         curr_lexer->m_filepos.next_line ();
 
         // Use current file position for error token.
-        octave::token *tok
-          = new octave::token (LEXICAL_ERROR,
-                               "unexpected internal lexer error",
-                               curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-        curr_lexer->push_token (tok);
-
-        return curr_lexer->count_token_internal (LEXICAL_ERROR);
+        std::string msg {"unexpected internal lexer error"};
+        return curr_lexer->syntax_error (msg, curr_lexer->m_filepos);
       }
   }
 
@@ -1508,13 +1477,13 @@
       }
     else
       {
-        int tok = curr_lexer->previous_token_value ();
+        int tok_id = curr_lexer->previous_token_id ();
 
         if (curr_lexer->whitespace_is_significant ())
           {
             if (curr_lexer->space_follows_previous_token ())
               {
-                if (tok == '[' || tok == '{'
+                if (tok_id == '[' || tok_id == '{'
                     || curr_lexer->previous_token_is_binop ())
                   {
                     curr_lexer->m_filepos.increment_column ();
@@ -1528,7 +1497,7 @@
               }
             else
               {
-                if (tok == '[' || tok == '{'
+                if (tok_id == '[' || tok_id == '{'
                     || curr_lexer->previous_token_is_binop ()
                     || curr_lexer->previous_token_is_keyword ())
                   {
@@ -1538,13 +1507,13 @@
                 else
                   {
                     curr_lexer->m_filepos.increment_column ();
-                    return curr_lexer->count_token (HERMITIAN);
+                    return curr_lexer->handle_token (HERMITIAN);
                   }
               }
           }
         else
           {
-            if (! tok || tok == '[' || tok == '{' || tok == '('
+            if (! tok_id || tok_id == '[' || tok_id == '{' || tok_id == '('
                 || curr_lexer->previous_token_is_binop ()
                 || curr_lexer->previous_token_is_keyword ())
               {
@@ -1554,7 +1523,7 @@
             else
               {
                 curr_lexer->m_filepos.increment_column ();
-                return curr_lexer->count_token (HERMITIAN);
+                return curr_lexer->handle_token (HERMITIAN);
               }
           }
       }
@@ -1576,13 +1545,13 @@
       }
     else
       {
-        int tok = curr_lexer->previous_token_value ();
+        int tok_id = curr_lexer->previous_token_id ();
 
         if (curr_lexer->whitespace_is_significant ())
           {
             if (curr_lexer->space_follows_previous_token ())
               {
-                if (tok == '[' || tok == '{'
+                if (tok_id == '[' || tok_id == '{'
                     || curr_lexer->previous_token_is_binop ())
                   {
                     curr_lexer->m_filepos.increment_column ();
@@ -1692,9 +1661,9 @@
     if (curr_lexer->whitespace_is_significant ()
         && curr_lexer->space_follows_previous_token ())
       {
-        int tok = curr_lexer->previous_token_value ();
-
-        if (! (tok == '[' || tok == '{'
+        int tok_id = curr_lexer->previous_token_id ();
+
+        if (! (tok_id == '[' || tok_id == '{'
                || curr_lexer->previous_token_is_binop ()))
           unput_comma = true;
       }
@@ -1744,7 +1713,7 @@
         curr_lexer->m_nesting_level.anon_fcn_body ();
       }
 
-    return curr_lexer->count_token (')');
+    return curr_lexer->handle_token (')');
   }
 
 "." {
@@ -1802,9 +1771,9 @@
     if (curr_lexer->whitespace_is_significant ()
         && curr_lexer->space_follows_previous_token ())
       {
-        int tok = curr_lexer->previous_token_value ();
-
-        if (! (tok == '[' || tok == '{'
+        int tok_id = curr_lexer->previous_token_id ();
+
+        if (! (tok_id == '[' || tok_id == '{'
                || curr_lexer->previous_token_is_binop ()))
           unput_comma = true;
       }
@@ -1829,7 +1798,7 @@
 
         curr_lexer->push_start_state (MATRIX_START);
 
-        return curr_lexer->count_token ('{');
+        return curr_lexer->handle_token ('{');
       }
   }
 
@@ -1880,16 +1849,9 @@
             << octave::undo_string_escape (static_cast<char> (c))
             << "' (ASCII " << c << ")";
 
-        // Use current file position for error token.
-        octave::token *tok
-          = new octave::token (LEXICAL_ERROR, buf.str (),
-                               curr_lexer->m_filepos, curr_lexer->m_filepos);
-
-        curr_lexer->push_token (tok);
-
-        curr_lexer->m_filepos.increment_column ();
-
-        return curr_lexer->count_token_internal (LEXICAL_ERROR);
+        curr_lexer->update_token_positions (yyleng);
+
+        return curr_lexer->syntax_error (buf.str ());
       }
   }
 
@@ -2148,7 +2110,7 @@
   lexical_feedback::symbol_table_context::pop ()
   {
     if (empty ())
-      panic_impossible ();
+      error ("unexpected: empty stack in lexical_feedback::symbol_table_context::pop - please report this bug");
 
     m_frame_stack.pop_front ();
   }
@@ -2245,60 +2207,79 @@
     m_tokens.clear ();
   }
 
-  int
-  lexical_feedback::previous_token_value () const
+  token *
+  lexical_feedback::previous_token ()
+  {
+    return m_tokens.front ();
+  }
+
+  const token *
+  lexical_feedback::previous_token () const
   {
-    const token *tok = m_tokens.front ();
-    return tok ? tok->token_value () : 0;
+    return m_tokens.front ();
+  }
+
+  int
+  lexical_feedback::previous_token_id () const
+  {
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->token_id () : 0;
   }
 
   bool
-  lexical_feedback::previous_token_value_is (int tok_val) const
+  lexical_feedback::previous_token_is (int tok_id) const
   {
-    const token *tok = m_tokens.front ();
-    return tok ? tok->token_value_is (tok_val) : false;
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->token_is (tok_id) : false;
+  }
+
+  bool
+  lexical_feedback::previous_token_is (const token *tok) const
+  {
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->token_is (tok) : false;
   }
 
   void
   lexical_feedback::mark_previous_token_trailing_space ()
   {
-    token *tok = m_tokens.front ();
-    if (tok && ! previous_token_value_is ('\n'))
-      tok->mark_trailing_space ();
+    token *prev_tok = previous_token ();
+    if (prev_tok && ! previous_token_is ('\n'))
+      prev_tok->mark_trailing_space ();
   }
 
   bool
   lexical_feedback::space_follows_previous_token () const
   {
-    const token *tok = m_tokens.front ();
-    return tok ? tok->space_follows_token () : false;
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->space_follows_token () : false;
   }
 
   bool
   lexical_feedback::previous_token_is_binop () const
   {
-    int tok = previous_token_value ();
-
-    return (tok == '+' || tok == '-' || tok == '@' || tok == '~' || tok == '!'
-            || tok == ',' || tok == ';' || tok == '*' || tok == '/'
-            || tok == ':' || tok == '=' || tok == ADD_EQ
-            || tok == AND_EQ || tok == DIV_EQ || tok == EDIV
-            || tok == EDIV_EQ || tok == ELEFTDIV || tok == ELEFTDIV_EQ
-            || tok == EMUL || tok == EMUL_EQ
-            || tok == EPOW || tok == EPOW_EQ || tok == EXPR_AND
-            || tok == EXPR_AND_AND || tok == EXPR_EQ || tok == EXPR_GE
-            || tok == EXPR_GT || tok == EXPR_LE || tok == EXPR_LT
-            || tok == EXPR_NE || tok == EXPR_OR
-            || tok == EXPR_OR_OR || tok == LEFTDIV || tok == LEFTDIV_EQ
-            || tok == MUL_EQ || tok == OR_EQ || tok == POW
-            || tok == POW_EQ || tok == SUB_EQ);
+    int tok_id = previous_token_id ();
+
+    return (tok_id == '+' || tok_id == '-' || tok_id == '@' || tok_id == '~' || tok_id == '!'
+            || tok_id == ',' || tok_id == ';' || tok_id == '*' || tok_id == '/'
+            || tok_id == ':' || tok_id == '=' || tok_id == ADD_EQ
+            || tok_id == AND_EQ || tok_id == DIV_EQ || tok_id == EDIV
+            || tok_id == EDIV_EQ || tok_id == ELEFTDIV || tok_id == ELEFTDIV_EQ
+            || tok_id == EMUL || tok_id == EMUL_EQ
+            || tok_id == EPOW || tok_id == EPOW_EQ || tok_id == EXPR_AND
+            || tok_id == EXPR_AND_AND || tok_id == EXPR_EQ || tok_id == EXPR_GE
+            || tok_id == EXPR_GT || tok_id == EXPR_LE || tok_id == EXPR_LT
+            || tok_id == EXPR_NE || tok_id == EXPR_OR
+            || tok_id == EXPR_OR_OR || tok_id == LEFTDIV || tok_id == LEFTDIV_EQ
+            || tok_id == MUL_EQ || tok_id == OR_EQ || tok_id == POW
+            || tok_id == POW_EQ || tok_id == SUB_EQ);
   }
 
   bool
   lexical_feedback::previous_token_is_keyword () const
   {
-    const token *tok = m_tokens.front ();
-    return tok ? tok->iskeyword () : false;
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->iskeyword () : false;
   }
 
   void
@@ -2325,8 +2306,8 @@
     if (! m_allow_command_syntax)
       return false;
 
-    const token *tok = m_tokens.front ();
-    return tok ? tok->may_be_command () : false;
+    const token *prev_tok = previous_token ();
+    return prev_tok ? prev_tok->may_be_command () : false;
   }
 
 static bool
@@ -2379,7 +2360,9 @@
     else
       len = max_size > m_chars_left ? m_chars_left : max_size;
 
-    assert (len > 0);
+    if (len <= 0)
+      error ("unexpected: buffer underflow in base_lexer::input_buffer::copy_chunk - please report this bug");
+
     memcpy (buf, m_buffer.c_str () + m_offset, len);
 
     m_chars_left -= len;
@@ -2462,7 +2445,7 @@
 
     lexical_feedback::reset ();
 
-    m_comment_buf.reset ();
+    m_comment_list.clear ();
   }
 
   void
@@ -2491,19 +2474,18 @@
 
     if (m_block_comment_nesting_level != 0)
       {
-        warning ("block comment unterminated at end of input");
+        std::string msg {"block comment unterminated at end of input"};
 
         if ((m_reading_fcn_file || m_reading_script_file || m_reading_classdef_file)
             && ! m_fcn_file_name.empty ())
-          warning ("near line %d of file '%s.m'",
-                   m_filepos.line (), m_fcn_file_name.c_str ());
+          msg += " near line " + std::to_string (m_filepos.line () - 1) + " of file '" + m_fcn_file_name + ".m'";
+
+        syntax_error (msg);
       }
 
-    token *tok_val = new token (END_OF_INPUT, m_tok_beg, m_tok_end);
-
-    push_token (tok_val);
-
-    return count_token_internal (END_OF_INPUT);
+    token *tok = new token (END_OF_INPUT, m_tok_beg, m_tok_end, get_comment_list ());
+
+    return handle_token (tok);
   }
 
   char *
@@ -2614,7 +2596,7 @@
     return retval;
   }
 
-  int
+  token *
   base_lexer::make_keyword_token (const std::string& s)
   {
     // Token positions should have already been updated before this
@@ -2625,14 +2607,14 @@
     const octave_kw *kw = octave_kw_hash::in_word_set (s.c_str (), slen);
 
     if (! kw)
-      return 0;
+      return nullptr;
 
     bool previous_at_bos = m_at_beginning_of_statement;
 
     // May be reset to true for some token types.
     m_at_beginning_of_statement = false;
 
-    token *tok_val = nullptr;
+    token *tok = nullptr;
 
     switch (kw->kw_id)
       {
@@ -2663,93 +2645,84 @@
                       || m_parsed_function_name.top ())))
           {
             m_at_beginning_of_statement = previous_at_bos;
-            return 0;
+            return nullptr;
           }
 
-        tok_val = new token (kw->tok, token::simple_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::simple_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case end_try_catch_kw:
-        tok_val = new token (kw->tok, token::try_catch_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::try_catch_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case end_unwind_protect_kw:
-        tok_val = new token (kw->tok, token::unwind_protect_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::unwind_protect_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endfor_kw:
-        tok_val = new token (kw->tok, token::for_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::for_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endfunction_kw:
-        tok_val = new token (kw->tok, token::function_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::function_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endif_kw:
-        tok_val = new token (kw->tok, token::if_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::if_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endparfor_kw:
-        tok_val = new token (kw->tok, token::parfor_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::parfor_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endswitch_kw:
-        tok_val = new token (kw->tok, token::switch_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::switch_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endwhile_kw:
-        tok_val = new token (kw->tok, token::while_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::while_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endarguments_kw:
 #if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK)
-        return 0;
+        return nullptr;
 #else
-        tok_val = new token (kw->tok, token::arguments_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::arguments_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 #endif
 
       case endclassdef_kw:
-        tok_val = new token (kw->tok, token::classdef_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::classdef_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endenumeration_kw:
-        tok_val = new token (kw->tok, token::enumeration_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::enumeration_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endevents_kw:
-        tok_val = new token (kw->tok, token::events_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::events_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endmethods_kw:
-        tok_val = new token (kw->tok, token::methods_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::methods_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
       case endproperties_kw:
-        tok_val = new token (kw->tok, token::properties_end, m_tok_beg,
-                             m_tok_end);
+        tok = new token (kw->tok_id, token::properties_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
@@ -2780,7 +2753,7 @@
         if (! m_maybe_classdef_get_set_method)
           {
             m_at_beginning_of_statement = previous_at_bos;
-            return 0;
+            return nullptr;
           }
         break;
 
@@ -2793,7 +2766,7 @@
         if (! m_classdef_element_names_are_keywords)
           {
             m_at_beginning_of_statement = previous_at_bos;
-            return 0;
+            return nullptr;
           }
         // fall through ...
 
@@ -2840,10 +2813,10 @@
 
       case arguments_kw:
 #if defined (DISABLE_ARGUMENTS_VALIDATION_BLOCK)
-        return 0;
+        return nullptr;
 #else
         if (! m_arguments_is_keyword)
-          return 0;
+          return nullptr;
         break;
 #endif
 
@@ -2852,7 +2825,7 @@
         break;
 
       case endspmd_kw:
-        tok_val = new token (kw->tok, token::spmd_end, m_tok_beg, m_tok_end);
+        tok = new token (kw->tok_id, token::spmd_end, m_tok_beg, m_tok_end, get_comment_list ());
         m_at_beginning_of_statement = true;
         break;
 
@@ -2861,10 +2834,9 @@
           if ((m_reading_fcn_file || m_reading_script_file
                || m_reading_classdef_file)
               && ! m_fcn_file_full_name.empty ())
-            tok_val = new token (kw->tok, m_fcn_file_full_name,
-                                 m_tok_beg, m_tok_end);
+            tok = new token (kw->tok_id, m_fcn_file_full_name, m_tok_beg, m_tok_end, get_comment_list ());
           else
-            tok_val = new token (kw->tok, "stdin", m_tok_beg, m_tok_end);
+            tok = new token (kw->tok_id, "stdin", m_tok_beg, m_tok_end, get_comment_list ());
         }
         break;
 
@@ -2872,20 +2844,20 @@
         {
           int l = m_tok_beg.line ();
           octave_value ov_value (static_cast<double> (l));
-          tok_val = new token (kw->tok, ov_value, "", m_tok_beg, m_tok_end);
+          tok = new token (kw->tok_id, ov_value, "", m_tok_beg, m_tok_end, get_comment_list ());
         }
         break;
 
-      default:
-        panic_impossible ();
+        // We should have handled all possible enum values above.  Rely
+        // on compiler diagnostics to warn if we haven't.  For example,
+        // GCC's -Wswitch option, enabled by -Wall, will provide a
+        // warning.
       }
 
-    if (! tok_val)
-      tok_val = new token (kw->tok, true, m_tok_beg, m_tok_end);
-
-    push_token (tok_val);
-
-    return kw->tok;
+    if (! tok)
+      tok = new token (kw->tok_id, true, m_tok_beg, m_tok_end, get_comment_list ());
+
+    return tok;
   }
 
 /*
@@ -2944,6 +2916,12 @@
   return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
 }
 
+OCTAVE_NORETURN static void
+error_unexpected_bytes (int bytes)
+{
+  error ("unexpected: bytes (= %d) not 1, 2, 4, or 8 in make_integer_value - please report this bug", bytes);
+}
+
 static inline octave_value
 make_integer_value (uintmax_t long_int_val, bool unsigned_val, int bytes)
 {
@@ -2964,7 +2942,7 @@
          return octave_value (octave_uint64 (long_int_val));
 
        default:
-         panic_impossible ();
+         error_unexpected_bytes (bytes);
        };
     }
   else
@@ -2987,7 +2965,7 @@
         return octave_value (octave_int64 (int64_t (long_int_val)));
 
         default:
-          panic_impossible ();
+          error_unexpected_bytes (bytes);
         };
     }
 
@@ -3041,14 +3019,8 @@
 
     if (bytes < 0)
       {
-        token *tok
-          = new token (LEXICAL_ERROR,
-                       "too many digits for binary constant",
-                       m_tok_beg, m_tok_end);
-
-        push_token (tok);
-
-        return count_token_internal (LEXICAL_ERROR);
+        std::string msg {"too many digits for binary constant"};
+        return syntax_error (msg);
       }
 
     // FIXME: is there a better way?  Can uintmax_t be anything other
@@ -3063,10 +3035,10 @@
     else if (sizeof (uintmax_t) == sizeof (unsigned long))
       long_int_val = strtoul (yytxt.c_str (), &end, 2);
     else
-      panic_impossible ();
+      error ("unexpected: size mismatch: uintmax_t vs unsigned long or unsigned long long in base_lexer::handle_number<2> - please report this bug");
 
     if (errno == ERANGE)
-      panic_impossible ();
+      error ("unexpected: ERANGE error in base_lexer::handle_number<2> - please report this bug");
 
     octave_value ov_value
       = make_integer_value (long_int_val, unsigned_val, bytes);
@@ -3076,9 +3048,9 @@
 
     update_token_positions (flex_yyleng ());
 
-    push_token (new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end));
-
-    return count_token_internal (NUMBER);
+    token *tok = new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end, get_comment_list ());
+
+    return handle_token (tok);
   }
 
   static uint64_t
@@ -3142,13 +3114,8 @@
     *p = '\0';
 
     double value = 0.0;
-    int nread = 0;
-
-    nread = sscanf (tmptxt, "%lf", &value);
-
-    // If yytext doesn't contain a valid number, we are in deep doo doo.
-
-    assert (nread == 1);
+    if (sscanf (tmptxt, "%lf", &value) != 1)
+      fatal_error ("scanf failed in base_lexer::handle_number<10> - please report this bug");
 
     octave_value ov_value;
 
@@ -3171,7 +3138,7 @@
         else if (sizeof (uintmax_t) == sizeof (unsigned long))
           long_int_val = strtoul (tmptxt, &end, 10);
         else
-          panic_impossible ();
+          error ("unexpected: size mismatch: uintmax_t vs unsigned long or unsigned long long in base_lexer::handle_number<10> - please report this bug");
 
         if (errno != ERANGE)
           {
@@ -3197,9 +3164,9 @@
                   ? octave_value (Complex (0.0, value))
                   : octave_value (value));
 
-    push_token (new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end));
-
-    return count_token_internal (NUMBER);
+    token *tok = new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end, get_comment_list ());
+
+    return handle_token (tok);
   }
 
   template <>
@@ -3249,34 +3216,24 @@
 
     if (bytes < 0)
       {
-        token *tok
-          = new token (LEXICAL_ERROR,
-                       "too many digits for hexadecimal constant",
-                       m_tok_beg, m_tok_end);
-
-        push_token (tok);
-
-        return count_token_internal (LEXICAL_ERROR);
+        std::string msg {"too many digits for hexadecimal constant"};
+        return syntax_error (msg);
       }
 
-    // Assert here because if yytext doesn't contain a valid number, we
-    // are in deep doo doo.
-
     uintmax_t long_int_val;
-    int status = sscanf (yytxt.c_str (), "%jx", &long_int_val);
-    assert (status);
-
-    octave_value ov_value
-      = make_integer_value (long_int_val, unsigned_val, bytes);
+    if (sscanf (yytxt.c_str (), "%jx", &long_int_val) != 1)
+      fatal_error ("sscanf failed in base_lexer::handle_number<16> - please report this bug");
+
+    octave_value ov_value = make_integer_value (long_int_val, unsigned_val, bytes);
 
     m_looking_for_object_index = false;
     m_at_beginning_of_statement = false;
 
     update_token_positions (flex_yyleng ());
 
-    push_token (new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end));
-
-    return count_token_internal (NUMBER);
+    token *tok = new token (NUMBER, ov_value, yytxt, m_tok_beg, m_tok_end, get_comment_list ());
+
+    return handle_token (tok);
   }
 
   void
@@ -3352,7 +3309,7 @@
     if (looks_like_copyright (m_comment_text))
       typ = comment_elt::copyright;
 
-    m_comment_buf.append (m_comment_text, typ, m_comment_uses_hash_char);
+    m_comment_list.append (m_comment_text, typ, m_comment_uses_hash_char);
 
     m_comment_text = "";
     m_comment_uses_hash_char = false;
@@ -3376,12 +3333,12 @@
         else if (bracket_type == '}')
           m_braceflag--;
         else
-          panic_impossible ();
+          error ("unexpected: bracket_type not ']' or '}' in base_lexer::handle_close_bracket - please report this bug");
       }
 
     pop_start_state ();
 
-    return count_token (bracket_type);
+    return handle_token (bracket_type);
   }
 
   bool
@@ -3414,82 +3371,45 @@
 
     if (iskeyword (meth) || fq_identifier_contains_keyword (cls))
       {
-        token *tok
-          = new token (LEXICAL_ERROR,
-                       "method, class, and package names may not be keywords",
-                       m_tok_beg, m_tok_end);
-
-        push_token (tok);
-
-        return count_token_internal (LEXICAL_ERROR);
+        std::string msg {"method, class, and package names may not be keywords"};
+        return syntax_error (msg);
       }
 
-    push_token (new token (SUPERCLASSREF, meth, cls, m_tok_beg, m_tok_end));
+    token *tok = new token (SUPERCLASSREF, meth, cls, m_tok_beg, m_tok_end, get_comment_list ());
 
     m_filepos.increment_column (flex_yyleng ());
 
-    return count_token_internal (SUPERCLASSREF);
+    return handle_token (tok);
   }
 
-  int
-  base_lexer::handle_meta_identifier ()
+  token *
+  base_lexer::make_meta_identifier_token (const std::string& cls)
   {
-    std::string txt = flex_yytext ();
-
-    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
-               txt.end ());
-
-    // Eliminate leading '?'
-    std::string cls = txt.substr (1);
-
     // Token positions should have already been updated before this
     // function is called.
 
-    if (fq_identifier_contains_keyword (cls))
-      {
-        token *tok = new token (LEXICAL_ERROR,
-                                "class and package names may not be keywords",
-                                m_tok_beg, m_tok_end);
-        push_token (tok);
-
-        return count_token_internal (LEXICAL_ERROR);
-      }
-
-    push_token (new token (METAQUERY, cls, m_tok_beg, m_tok_end));
+    m_looking_for_object_index = true;
+
+    token *tok = new token (METAQUERY, cls, m_tok_beg, m_tok_end, get_comment_list ());
 
     m_filepos.increment_column (flex_yyleng ());
 
-    return METAQUERY;
+    return tok;
   }
 
-  int
-  base_lexer::handle_fq_identifier ()
+  token *
+  base_lexer::make_fq_identifier_token (const std::string& ident)
   {
-    std::string txt = flex_yytext ();
-
-    txt.erase (std::remove_if (txt.begin (), txt.end (), is_space_or_tab),
-               txt.end ());
-
     // Token positions should have already been updated before this
     // function is called.
 
-    if (fq_identifier_contains_keyword (txt))
-      {
-        token *tok
-          = new token (LEXICAL_ERROR,
-                       "function, method, class, and package names may not be keywords",
-                       m_tok_beg, m_tok_end);
-
-        push_token (tok);
-
-        return count_token_internal (LEXICAL_ERROR);
-      }
-
-    push_token (new token (FQ_IDENT, txt, m_tok_beg, m_tok_end));
+    m_looking_for_object_index = true;
+
+    token *tok = new token (FQ_IDENT, ident, m_tok_beg, m_tok_end, get_comment_list ());
 
     m_filepos.increment_column (flex_yyleng ());
 
-    return FQ_IDENT;
+    return tok;
   }
 
   // Figure out exactly what kind of token to return when we have seen
@@ -3509,32 +3429,32 @@
 
     if (m_looking_at_indirect_ref)
       {
-        push_token (new token (STRUCT_ELT, ident, m_tok_beg, m_tok_end));
+        token *tok = new token (STRUCT_ELT, ident, m_tok_beg, m_tok_end, get_comment_list ());
 
         m_looking_for_object_index = true;
 
-        return STRUCT_ELT;
+        return handle_token (tok);
       }
 
     // If ident is a keyword token, then make_keyword_token will set
     // m_at_beginning_of_statement.  For example, if tok is an IF
     // token, then m_at_beginning_of_statement will be false.
 
-    int kw_token = make_keyword_token (ident);
+    token *tok = make_keyword_token (ident);
 
     // If we have a regular keyword, return it.
     // Keywords can be followed by identifiers.
 
-    if (kw_token)
+    if (tok)
       {
         m_looking_for_object_index = false;
 
         // The call to make_keyword_token set m_at_beginning_of_statement.
 
-        return count_token_internal (kw_token);
+        return handle_token (tok);
       }
 
-    token *tok = new token (NAME, ident, m_tok_beg, m_tok_end);
+    tok = new token (NAME, ident, m_tok_beg, m_tok_end, get_comment_list ());
 
     // For compatibility with Matlab, the following symbols are
     // handled specially so that things like
@@ -3553,8 +3473,6 @@
               || ident == "NaN" || ident == "nan"))
       tok->mark_may_be_command ();
 
-    push_token (tok);
-
     // The magic end index can't be indexed.
 
     if (ident != "end")
@@ -3562,7 +3480,7 @@
 
     m_at_beginning_of_statement = false;
 
-    return count_token_internal (NAME);
+    return handle_token (tok);
   }
 
   void
@@ -3642,11 +3560,33 @@
                        m_filepos.line (), m_fcn_file_full_name.c_str ());
   }
 
+  int
+  base_lexer::syntax_error (const std::string& msg)
+  {
+    return syntax_error (msg, m_tok_beg, m_tok_end);
+  }
+
+  int
+  base_lexer::syntax_error (const std::string& msg, const filepos& pos)
+  {
+    return syntax_error (msg, pos, pos);
+  }
+
+  int
+  base_lexer::syntax_error (const std::string& msg, const filepos& beg_pos, const filepos& end_pos)
+  {
+    token *tok = new token (LEXICAL_ERROR, msg, beg_pos, end_pos);
+
+    push_token (tok);
+
+    return count_token_internal (tok->token_id ());
+  }
+
   void
   base_lexer::push_token (token *tok)
   {
     YYSTYPE *lval = yyget_lval (m_scanner);
-    lval->tok_val = tok;
+    lval->tok = tok;
     m_tokens.push (tok);
   }
 
@@ -3654,7 +3594,7 @@
   base_lexer::current_token ()
   {
     YYSTYPE *lval = yyget_lval (m_scanner);
-    return lval->tok_val;
+    return lval->tok;
   }
 
   std::size_t
@@ -3664,9 +3604,9 @@
   }
 
   void
-  base_lexer::display_token (int tok)
+  base_lexer::display_token (int tok_id)
   {
-    switch (tok)
+    switch (tok_id)
       {
       case '=': std::cerr << "'='\n"; break;
       case ':': std::cerr << "':'\n"; break;
@@ -3711,9 +3651,9 @@
 
       case NUMBER:
         {
-          token *tok_val = current_token ();
+          token *tok = current_token ();
           std::cerr << "NUMBER [";
-          octave_value num = tok_val->number ();
+          octave_value num = tok->number ();
           num.print_raw (std::cerr);
           std::cerr << "]\n";
         }
@@ -3721,15 +3661,15 @@
 
       case STRUCT_ELT:
         {
-          token *tok_val = current_token ();
-          std::cerr << "STRUCT_ELT [" << tok_val->text () << "]\n";
+          token *tok = current_token ();
+          std::cerr << "STRUCT_ELT [" << tok->text () << "]\n";
         }
         break;
 
       case NAME:
         {
-          token *tok_val = current_token ();
-          std::cerr << "NAME [" << tok_val->text () << "]\n";
+          token *tok = current_token ();
+          std::cerr << "NAME [" << tok->text () << "]\n";
         }
         break;
 
@@ -3738,10 +3678,10 @@
       case DQ_STRING:
       case SQ_STRING:
         {
-          token *tok_val = current_token ();
-
-          std::cerr << (tok == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
-                    << " [" << tok_val->text () << "]\n";
+          token *tok = current_token ();
+
+          std::cerr << (tok_id == DQ_STRING ? "DQ_STRING" : "SQ_STRING")
+                    << " [" << tok->text () << "]\n";
         }
         break;
 
@@ -3757,7 +3697,7 @@
       case OTHERWISE: std::cerr << "OTHERWISE\n"; break;
       case BREAK: std::cerr << "BREAK\n"; break;
       case CONTINUE: std::cerr << "CONTINUE\n"; break;
-      case FUNC_RET: std::cerr << "FUNC_RET\n"; break;
+      case RETURN: std::cerr << "RETURN\n"; break;
       case UNWIND: std::cerr << "UNWIND\n"; break;
       case CLEANUP: std::cerr << "CLEANUP\n"; break;
       case TRY: std::cerr << "TRY\n"; break;
@@ -3767,7 +3707,7 @@
       case FCN_HANDLE: std::cerr << "FCN_HANDLE\n"; break;
       case END_OF_INPUT: std::cerr << "END_OF_INPUT\n\n"; break;
       case LEXICAL_ERROR: std::cerr << "LEXICAL_ERROR\n\n"; break;
-      case FCN: std::cerr << "FCN\n"; break;
+      case FUNCTION: std::cerr << "FUNCTION\n"; break;
       case INPUT_FILE: std::cerr << "INPUT_FILE\n"; break;
       case SUPERCLASSREF: std::cerr << "SUPERCLASSREF\n"; break;
       case METAQUERY: std::cerr << "METAQUERY\n"; break;
@@ -3782,10 +3722,10 @@
       case '\t': std::cerr << "TAB\n"; break;
       default:
         {
-          if (tok < 256 && tok > 31)
-            std::cerr << static_cast<char> (tok) << "\n";
+          if (tok_id < 256 && tok_id > 31)
+            std::cerr << static_cast<char> (tok_id) << "\n";
           else
-            std::cerr << "UNKNOWN(" << tok << ")\n";
+            std::cerr << "UNKNOWN(" << tok_id << ")\n";
         }
         break;
       }
@@ -3794,7 +3734,7 @@
   void
   base_lexer::fatal_error (const char *msg)
   {
-    error ("fatal lexer error: %s", msg);
+    ::error ("fatal lexer error: %s", msg);
   }
 
   bool
@@ -3921,9 +3861,9 @@
   }
 
   bool
-  base_lexer::maybe_unput_comma_before_unary_op (int tok)
+  base_lexer::maybe_unput_comma_before_unary_op (int tok_id)
   {
-    int prev_tok = previous_token_value ();
+    int prev_tok_id = previous_token_id ();
 
     bool unput_comma = false;
 
@@ -3934,9 +3874,9 @@
 
         bool space_after = is_space_or_tab (c);
 
-        if (! (prev_tok == '[' || prev_tok == '{'
+        if (! (prev_tok_id == '[' || prev_tok_id == '{'
                || previous_token_is_binop ()
-               || ((tok == '+' || tok == '-') && space_after)))
+               || ((tok_id == '+' || tok_id == '-') && space_after)))
           unput_comma = true;
       }
 
@@ -3944,19 +3884,19 @@
   }
 
   int
-  base_lexer::handle_op (int tok, bool bos, bool compat)
+  base_lexer::handle_op (int tok_id, bool bos, bool compat)
   {
     if (! compat)
       warn_language_extension_operator (flex_yytext ());
 
     update_token_positions (flex_yyleng ());
 
-    push_token (new token (tok, m_tok_beg, m_tok_end));
+    token *tok = new token (tok_id, m_tok_beg, m_tok_end, get_comment_list ());
 
     m_looking_for_object_index = false;
     m_at_beginning_of_statement = bos;
 
-    switch (tok)
+    switch (tok_id)
       {
       case EXPR_LT:
         if (m_parsing_classdef_decl)
@@ -3975,7 +3915,7 @@
         break;
       }
 
-    return count_token_internal (tok);
+    return handle_token (tok);
   }
 
   // When a command argument boundary is detected, push out the current
@@ -3985,61 +3925,52 @@
   int
   base_lexer::finish_command_arg ()
   {
-    int tok = SQ_STRING;
-
-    token *tok_val = new token (tok, m_string_text, m_tok_beg, m_tok_end);
+    token *tok = new token (SQ_STRING, m_string_text, m_tok_beg, m_tok_end, get_comment_list ());
 
     m_string_text = "";
     m_command_arg_paren_count = 0;
 
-    return handle_token (tok, tok_val);
+    return handle_token (tok);
   }
 
   int
-  base_lexer::handle_token (int tok, token *tok_val)
+  base_lexer::handle_token (int tok_id)
   {
-    if (! tok_val)
-      tok_val = new token (tok, m_tok_beg, m_tok_end);
-
-    push_token (tok_val);
-
-    return count_token_internal (tok);
+    return handle_token (new token (tok_id, m_tok_beg, m_tok_end));
   }
 
   int
-  base_lexer::count_token (int tok)
+  base_lexer::handle_token (token *tok)
   {
-    token *tok_val = new token (tok, m_tok_beg, m_tok_end);
-
-    push_token (tok_val);
-
-    return count_token_internal (tok);
+    push_token (tok);
+
+    return count_token_internal (tok->token_id ());
   }
 
   int
-  base_lexer::count_token_internal (int tok)
+  base_lexer::count_token_internal (int tok_id)
   {
-    if (tok != '\n')
+    if (tok_id != '\n')
       increment_token_count ();
 
-    return show_token (tok);
+    return show_token (tok_id);
   }
 
   int
-  base_lexer::show_token (int tok)
+  base_lexer::show_token (int tok_id)
   {
 
     if (display_tokens ())
-      display_token (tok);
+      display_token (tok_id);
 
     if (debug_flag ())
       {
         std::cerr << "R: ";
-        display_token (tok);
+        display_token (tok_id);
         std::cerr << std::endl;
       }
 
-    return tok;
+    return tok_id;
   }
 
   int
@@ -4124,7 +4055,8 @@
         // input_buffer::copy_chunk, simply insert the marker directly
         // in BUF.
 
-        assert (max_size > 0);
+        if (max_size <= 0)
+          error ("unexpected: max_size <= 0 in push_lexer::fill_flex_buffer - please report this bug");
 
         buf[0] = static_cast<char> (1);
         status = 1;
--- a/libinterp/parse-tree/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -23,6 +23,7 @@
   %reldir%/pt-colon.h \
   %reldir%/pt-const.h \
   %reldir%/pt-decl.h \
+  %reldir%/pt-delimiter-list.h \
   %reldir%/pt-eval.h \
   %reldir%/pt-except.h \
   %reldir%/pt-exp.h \
@@ -87,8 +88,7 @@
   %reldir%/pt-tm-const.cc \
   %reldir%/pt-unop.cc \
   %reldir%/pt-walk.cc \
-  %reldir%/pt.cc \
-  %reldir%/token.cc
+  %reldir%/pt.cc
 
 ## Special rules for sources which must be built before rest of compilation.
 
--- a/libinterp/parse-tree/oct-lvalue.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/oct-lvalue.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -168,7 +168,7 @@
       break;
 
     default:
-      panic_impossible ();
+      error ("unexpected: index not '(', '{', or '.' in octave_lvalue::numel - please report this bug");
     }
 }
 
--- a/libinterp/parse-tree/oct-parse.yy	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/oct-parse.yy	Fri Apr 12 15:10:26 2024 +0200
@@ -35,7 +35,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
 #include <cstdio>
 #include <cstdlib>
 
@@ -140,10 +139,7 @@
   int dummy_type;
 
   // The type of the basic tokens returned by the lexer.
-  octave::token *tok_val;
-
-  // Comment strings that we need to deal with mid-rule.
-  octave::comment_list *comment_type;
+  octave::token *tok;
 
   // Types for the nonterminals we generate.
   char punct_type;
@@ -191,65 +187,66 @@
   octave::tree_classdef_property* tree_classdef_property_type;
   octave::tree_classdef_property_list* tree_classdef_property_list_type;
   octave::tree_classdef_properties_block* tree_classdef_properties_block_type;
-  octave::tree_classdef_methods_list* tree_classdef_methods_list_type;
+  octave::tree_classdef_method_list* tree_classdef_method_list_type;
   octave::tree_classdef_methods_block* tree_classdef_methods_block_type;
   octave::tree_classdef_event* tree_classdef_event_type;
-  octave::tree_classdef_events_list* tree_classdef_events_list_type;
+  octave::tree_classdef_event_list* tree_classdef_event_list_type;
   octave::tree_classdef_events_block* tree_classdef_events_block_type;
   octave::tree_classdef_enum* tree_classdef_enum_type;
   octave::tree_classdef_enum_list* tree_classdef_enum_list_type;
   octave::tree_classdef_enum_block* tree_classdef_enum_block_type;
 }
 
-// Tokens with line and column information.
-%token <tok_val> '=' ':' '-' '+' '*' '/' '~' '!'
-%token <tok_val> '(' ')' '[' ']' '{' '}' '.' '@'
-%token <tok_val> ',' ';' '\n'
-%token <tok_val> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
-%token <tok_val> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
-%token <tok_val> EXPR_AND_AND EXPR_OR_OR
-%token <tok_val> EXPR_AND EXPR_OR
-%token <tok_val> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
-%token <tok_val> LEFTDIV EMUL EDIV ELEFTDIV
-%token <tok_val> HERMITIAN TRANSPOSE
-%token <tok_val> PLUS_PLUS MINUS_MINUS POW EPOW
-%token <tok_val> NUMBER
-%token <tok_val> STRUCT_ELT
-%token <tok_val> NAME
-%token <tok_val> END
-%token <tok_val> DQ_STRING SQ_STRING
-%token <tok_val> FOR PARFOR WHILE DO UNTIL
-%token <tok_val> SPMD
-%token <tok_val> IF ELSEIF ELSE
-%token <tok_val> SWITCH CASE OTHERWISE
-%token <tok_val> BREAK CONTINUE FUNC_RET
-%token <tok_val> UNWIND CLEANUP
-%token <tok_val> TRY CATCH
-%token <tok_val> GLOBAL PERSISTENT
-%token <tok_val> FCN_HANDLE
-%token <tok_val> CLASSDEF
-%token <tok_val> PROPERTIES METHODS EVENTS ENUMERATION
-%token <tok_val> METAQUERY
-%token <tok_val> SUPERCLASSREF
-%token <tok_val> FQ_IDENT
-%token <tok_val> GET SET
-%token <tok_val> FCN
-%token <tok_val> ARGUMENTS
-%token <tok_val> LEXICAL_ERROR
-%token <tok_val> END_OF_INPUT
+// Tokens with position information.
+%token <tok> '=' ':' '-' '+' '*' '/' '~' '!'
+%token <tok> '(' ')' '[' ']' '{' '}' '.' '@'
+%token <tok> ',' ';' '\n'
+%token <tok> ADD_EQ SUB_EQ MUL_EQ DIV_EQ LEFTDIV_EQ POW_EQ
+%token <tok> EMUL_EQ EDIV_EQ ELEFTDIV_EQ EPOW_EQ AND_EQ OR_EQ
+%token <tok> EXPR_AND_AND EXPR_OR_OR
+%token <tok> EXPR_AND EXPR_OR
+%token <tok> EXPR_LT EXPR_LE EXPR_EQ EXPR_NE EXPR_GE EXPR_GT
+%token <tok> LEFTDIV EMUL EDIV ELEFTDIV
+%token <tok> HERMITIAN TRANSPOSE
+%token <tok> PLUS_PLUS MINUS_MINUS POW EPOW
+%token <tok> NUMBER
+// The result of a constant folding operation.
+%token <tok> CONSTANT
+%token <tok> STRUCT_ELT
+%token <tok> NAME
+%token <tok> END
+%token <tok> DQ_STRING SQ_STRING
+%token <tok> FOR PARFOR WHILE DO UNTIL
+%token <tok> SPMD
+%token <tok> IF ELSEIF ELSE
+%token <tok> SWITCH CASE OTHERWISE
+%token <tok> BREAK CONTINUE RETURN
+%token <tok> UNWIND CLEANUP
+%token <tok> TRY CATCH
+%token <tok> GLOBAL PERSISTENT
+%token <tok> FCN_HANDLE
+%token <tok> CLASSDEF
+%token <tok> PROPERTIES METHODS EVENTS ENUMERATION
+%token <tok> METAQUERY
+%token <tok> SUPERCLASSREF
+%token <tok> FQ_IDENT
+%token <tok> GET SET
+%token <tok> FUNCTION
+%token <tok> ARGUMENTS
+%token <tok> LEXICAL_ERROR
+%token <tok> END_OF_INPUT
 
 // Other tokens.
 %token <dummy_type> INPUT_FILE
 // %token VARARGIN VARARGOUT
 
 // Nonterminals we construct.
-%type <dummy_type> indirect_ref_op
 %type <dummy_type> push_fcn_symtab push_script_symtab begin_file
-%type <dummy_type> param_list_beg param_list_end stmt_begin anon_fcn_begin
+%type <dummy_type> stmt_begin anon_fcn_begin
 %type <dummy_type> parsing_local_fcns parse_error at_first_executable_stmt
-%type <comment_type> stash_comment
-%type <tok_val> function_beg classdef_beg arguments_beg
-%type <tok_val> properties_beg methods_beg events_beg enumeration_beg
+%type <tok> param_list_beg param_list_end
+%type <tok> function_beg classdef_beg arguments_beg indirect_ref_op
+%type <tok> properties_beg methods_beg events_beg enumeration_beg
 %type <punct_type> sep_no_nl opt_sep_no_nl nl opt_nl sep opt_sep
 %type <tree_type> input
 %type <tree_constant_type> string constant magic_colon
@@ -276,8 +273,8 @@
 %type <tree_classdef_type> classdef
 %type <tree_command_type> file
 %type <tree_if_command_type> if_command
-%type <tree_if_clause_type> elseif_clause else_clause
-%type <tree_if_command_list_type> if_cmd_list1 if_cmd_list
+%type <tree_if_command_list_type> if_clause_list
+%type <tree_if_clause_type> if_clause elseif_clause else_clause
 %type <tree_switch_command_type> switch_command
 %type <tree_switch_case_type> switch_case default_case
 %type <tree_switch_case_list_type> case_list1 case_list
@@ -296,10 +293,10 @@
 %type <tree_classdef_property_type> class_property
 %type <tree_classdef_property_list_type> property_list property_list1
 %type <tree_classdef_properties_block_type> properties_block
-%type <tree_classdef_methods_list_type> methods_list methods_list1
+%type <tree_classdef_method_list_type> method_list method_list1
 %type <tree_classdef_methods_block_type> methods_block
 %type <tree_classdef_event_type> class_event
-%type <tree_classdef_events_list_type> events_list events_list1
+%type <tree_classdef_event_list_type> event_list event_list1
 %type <tree_classdef_events_block_type> events_block
 %type <tree_classdef_enum_type> class_enum
 %type <tree_classdef_enum_list_type> enum_list enum_list1
@@ -312,7 +309,6 @@
 %type <tree_arg_size_spec_type> size_spec
 %type <tree_identifier_type> class_name
 %type <tree_arg_validation_fcns_type> validation_fcns
-%type <tree_expression_type> default_value
 %type <octave_user_function_type> method_decl1
 
 // Precedence and associativity.
@@ -337,9 +333,8 @@
 // cases (for example, a new semantic type is added but not handled
 // here).
 
-%destructor { } <tok_val>
+%destructor { } <tok>
 %destructor { } <punct_type>
-%destructor { } <comment_type>
 %destructor { } <>
 
 %destructor { delete $$; } <tree_type>
@@ -385,10 +380,10 @@
 %destructor { delete $$; } <tree_classdef_property_type>
 %destructor { delete $$; } <tree_classdef_property_list_type>
 %destructor { delete $$; } <tree_classdef_properties_block_type>
-%destructor { delete $$; } <tree_classdef_methods_list_type>
+%destructor { delete $$; } <tree_classdef_method_list_type>
 %destructor { delete $$; } <tree_classdef_methods_block_type>
 %destructor { delete $$; } <tree_classdef_event_type>
-%destructor { delete $$; } <tree_classdef_events_list_type>
+%destructor { delete $$; } <tree_classdef_event_list_type>
 %destructor { delete $$; } <tree_classdef_events_block_type>
 %destructor { delete $$; } <tree_classdef_enum_type>
 %destructor { delete $$; } <tree_classdef_enum_list_type>
@@ -398,9 +393,7 @@
 // already explicitly declared for all types.
 //
 // %destructor {
-//    warning_with_id
-//      ("Octave:parser-destructor",
-//       "possible memory leak in cleanup following parse error");
+//    warning_with_id ("Octave:parser-destructor", "possible memory leak in cleanup following parse error");
 // } <*>
 
 // Where to start.
@@ -434,6 +427,13 @@
                     else
                       YYACCEPT;
                   }
+                | file
+                  {
+                    lexer.m_end_of_input = true;
+
+                    $$ = $1;
+                    YYACCEPT;
+                  }
                 | parse_error
                   {
                     $$ = nullptr;
@@ -488,15 +488,9 @@
                 ;
 
 fcn_list1       : function
-                  {
-                    octave::tree_statement *stmt = parser.make_statement ($1);
-                    $$ = parser.make_statement_list (stmt);
-                  }
+                  { $$ = parser.make_function_def_list ($1); }
                 | fcn_list1 opt_sep function
-                  {
-                    octave::tree_statement *stmt = parser.make_statement ($3);
-                    $$ = parser.append_statement_list ($1, $2, stmt, false);
-                  }
+                  { $$ = parser.append_function_def_list ($1, $2, $3); }
                 ;
 
 statement       : expression
@@ -517,20 +511,18 @@
 
 word_list_cmd   : identifier word_list
                   {
-                    $$ = parser.make_index_expression ($1, $2, '(');
-                    if (! $$)
+                    if (! ($$ = parser.make_word_list_command ($1, $2)))
                       {
                         // make_index_expression deleted $1 and $2.
                         YYABORT;
                       }
-                    $$->mark_word_list_cmd ();
                   }
                 ;
 
 word_list       : string
                   { $$ = parser.make_argument_list ($1); }
                 | word_list string
-                  { $$ = parser.append_argument_list ($1, $2); }
+                  { $$ = parser.append_argument_list ($1, nullptr, $2); }
                 ;
 
 // ===========
@@ -563,31 +555,23 @@
                 ;
 
 matrix          : '[' matrix_rows ']'
-                  { $$ = parser.finish_matrix ($2, $1, $3); }
+                  { $$ = parser.finish_matrix ($1, $2, $3); }
                 ;
 
 matrix_rows     : cell_or_matrix_row
                   { $$ = parser.make_matrix ($1); }
                 | matrix_rows ';' cell_or_matrix_row
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_matrix_row ($1, $3);
-                  }
+                  { $$ = parser.append_matrix_row ($1, $2, $3); }
                 ;
 
 cell            : '{' cell_rows '}'
-                  { $$ = parser.finish_cell ($2, $1, $3); }
+                  { $$ = parser.finish_cell ($1, $2, $3); }
                 ;
 
 cell_rows       : cell_or_matrix_row
                   { $$ = parser.make_cell ($1); }
                 | cell_rows ';' cell_or_matrix_row
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_cell_row ($1, $3);
-                  }
+                  { $$ = parser.append_cell_row ($1, $2, $3); }
                 ;
 
 // tree_argument_list objects can't be empty or have leading or trailing
@@ -638,8 +622,7 @@
 
 anon_fcn_handle : '@' param_list anon_fcn_begin expression
                   {
-                    $$ = parser.make_anon_fcn_handle ($2, $4, $1->beg_pos ());
-                    if (! $$)
+                    if (! ($$ = parser.make_anon_fcn_handle ($1, $2, $4)))
                       {
                         // make_anon_fcn_handle deleted $2 and $4.
                         YYABORT;
@@ -655,6 +638,7 @@
                     lexer.m_parsing_anon_fcn_body = false;
 
                     $$ = nullptr;
+
                     parser.bison_error ("anonymous function bodies must be single expressions");
                     YYABORT;
                   }
@@ -678,11 +662,7 @@
                 | superclass_identifier
                   { $$ = $1; }
                 | '(' expression ')'
-                  {
-                    OCTAVE_YYUSE ($1, $3);
-
-                    $$ = $2->mark_in_parens ();
-                  }
+                  { $$ = $2->mark_in_delims (*($1), *($3)); }
                 ;
 
 magic_colon     : ':'
@@ -690,11 +670,7 @@
                 ;
 
 magic_tilde     : '~'
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = parser.make_black_hole ();
-                  }
+                  { $$ = parser.make_black_hole ($1); }
                 ;
 
 arg_list        : expression
@@ -704,46 +680,29 @@
                 | magic_tilde
                   { $$ = parser.make_argument_list ($1); }
                 | arg_list ',' magic_colon
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_argument_list ($1, $3);
-                  }
+                  { $$ = parser.append_argument_list ($1, $2, $3); }
                 | arg_list ',' magic_tilde
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_argument_list ($1, $3);
-                  }
+                  { $$ = parser.append_argument_list ($1, $2, $3); }
                 | arg_list ',' expression
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_argument_list ($1, $3);
-                  }
+                  { $$ = parser.append_argument_list ($1, $2, $3); }
                 ;
 
 indirect_ref_op : '.'
                   {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = 0;
                     lexer.m_looking_at_indirect_ref = true;
+                    $$ = $1;
                   }
                 ;
 
 oper_expr       : primary_expr
                   { $$ = $1; }
                 | oper_expr PLUS_PLUS
-                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | oper_expr MINUS_MINUS
-                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | oper_expr '(' ')'
                   {
-                    OCTAVE_YYUSE ($2, $3);
-
-                    $$ = parser.make_index_expression ($1, nullptr, '(');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '(')))
                       {
                         // make_index_expression deleted $1.
                         YYABORT;
@@ -751,10 +710,7 @@
                   }
                 | oper_expr '(' arg_list ')'
                   {
-                    OCTAVE_YYUSE ($2, $4);
-
-                    $$ = parser.make_index_expression ($1, $3, '(');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '(')))
                       {
                         // make_index_expression deleted $1 and $3.
                         YYABORT;
@@ -762,10 +718,7 @@
                   }
                 | oper_expr '{' '}'
                   {
-                    OCTAVE_YYUSE ($2, $3);
-
-                    $$ = parser.make_index_expression ($1, nullptr, '{');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '{')))
                       {
                         // make_index_expression deleted $1.
                         YYABORT;
@@ -773,73 +726,63 @@
                   }
                 | oper_expr '{' arg_list '}'
                   {
-                    OCTAVE_YYUSE ($2, $4);
-
-                    $$ = parser.make_index_expression ($1, $3, '{');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '{')))
                       {
                         // make_index_expression deleted $1 and $3.
                         YYABORT;
                       }
                   }
                 | oper_expr HERMITIAN
-                  { $$ = parser.make_postfix_op (HERMITIAN, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | oper_expr TRANSPOSE
-                  { $$ = parser.make_postfix_op (TRANSPOSE, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | oper_expr indirect_ref_op STRUCT_ELT
-                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
+                  { $$ = parser.make_indirect_ref ($1, $2, $3); }
                 | oper_expr indirect_ref_op '(' expression ')'
-                  {
-                    OCTAVE_YYUSE ($3, $5);
-
-                    $$ = parser.make_indirect_ref ($1, $4);
-                  }
+                  { $$ = parser.make_indirect_ref ($1, $2, $3, $4, $5); }
                 | PLUS_PLUS oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | MINUS_MINUS oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '~' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('~', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '!' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('!', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '+' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('+', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '-' oper_expr %prec UNARY
-                  { $$ = parser.make_prefix_op ('-', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | oper_expr POW power_expr
-                  { $$ = parser.make_binary_op (POW, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr EPOW power_expr
-                  { $$ = parser.make_binary_op (EPOW, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr '+' oper_expr
-                  { $$ = parser.make_binary_op ('+', $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr '-' oper_expr
-                  { $$ = parser.make_binary_op ('-', $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr '*' oper_expr
-                  { $$ = parser.make_binary_op ('*', $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr '/' oper_expr
-                  { $$ = parser.make_binary_op ('/', $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr EMUL oper_expr
-                  { $$ = parser.make_binary_op (EMUL, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr EDIV oper_expr
-                  { $$ = parser.make_binary_op (EDIV, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr LEFTDIV oper_expr
-                  { $$ = parser.make_binary_op (LEFTDIV, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | oper_expr ELEFTDIV oper_expr
-                  { $$ = parser.make_binary_op (ELEFTDIV, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 ;
 
 power_expr      : primary_expr
                   { $$ = $1; }
                 | power_expr PLUS_PLUS
-                  { $$ = parser.make_postfix_op (PLUS_PLUS, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | power_expr MINUS_MINUS
-                  { $$ = parser.make_postfix_op (MINUS_MINUS, $1, $2); }
+                  { $$ = parser.make_postfix_op ($1, $2); }
                 | power_expr '(' ')'
                   {
-                    OCTAVE_YYUSE ($2, $3);
-
-                    $$ = parser.make_index_expression ($1, nullptr, '(');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '(')))
                       {
                         // make_index_expression deleted $1.
                         YYABORT;
@@ -847,10 +790,7 @@
                   }
                 | power_expr '(' arg_list ')'
                   {
-                    OCTAVE_YYUSE ($2, $4);
-
-                    $$ = parser.make_index_expression ($1, $3, '(');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '(')))
                       {
                         // make_index_expression deleted $1 and $3.
                         YYABORT;
@@ -858,10 +798,7 @@
                   }
                 | power_expr '{' '}'
                   {
-                    OCTAVE_YYUSE ($2, $3);
-
-                    $$ = parser.make_index_expression ($1, nullptr, '{');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, nullptr, $3, '{')))
                       {
                         // make_index_expression deleted $1.
                         YYABORT;
@@ -869,44 +806,33 @@
                   }
                 | power_expr '{' arg_list '}'
                   {
-                    OCTAVE_YYUSE ($2, $4);
-
-                    $$ = parser.make_index_expression ($1, $3, '{');
-                    if (! $$)
+                    if (! ($$ = parser.make_index_expression ($1, $2, $3, $4, '{')))
                       {
                         // make_index_expression deleted $1 and $3.
                         YYABORT;
                       }
                   }
                 | power_expr indirect_ref_op STRUCT_ELT
-                  { $$ = parser.make_indirect_ref ($1, $3->text ()); }
+                  { $$ = parser.make_indirect_ref ($1, $2, $3); }
                 | power_expr indirect_ref_op '(' expression ')'
-                  {
-                    OCTAVE_YYUSE ($3, $5);
-
-                    $$ = parser.make_indirect_ref ($1, $4);
-                  }
+                  { $$ = parser.make_indirect_ref ($1, $2, $3, $4, $5); }
                 | PLUS_PLUS power_expr %prec POW
-                  { $$ = parser.make_prefix_op (PLUS_PLUS, $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | MINUS_MINUS power_expr %prec POW
-                  { $$ = parser.make_prefix_op (MINUS_MINUS, $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '~' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('~', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '!' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('!', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '+' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('+', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 | '-' power_expr %prec POW
-                  { $$ = parser.make_prefix_op ('-', $2, $1); }
+                  { $$ = parser.make_prefix_op ($1, $2); }
                 ;
 
 colon_expr      : oper_expr ':' oper_expr
                   {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.make_colon_expression ($1, $3);
-
-                    if (! $$)
+                    if (! ($$ = parser.make_colon_expression ($1, $2, $3)))
                       {
                         // make_colon_expression deleted $1 and $3.
                         YYABORT;
@@ -914,11 +840,7 @@
                   }
                 | oper_expr ':' oper_expr ':' oper_expr
                   {
-                    OCTAVE_YYUSE ($2, $4);
-
-                    $$ = parser.make_colon_expression ($1, $5, $3);
-
-                    if (! $$)
+                    if (! ($$ = parser.make_colon_expression ($1, $2, $3, $4, $5)))
                       {
                         // make_colon_expression deleted $1, $3, and $5.
                         YYABORT;
@@ -931,67 +853,65 @@
                 | colon_expr
                   { $$ = $1; }
                 | simple_expr EXPR_LT simple_expr
-                  { $$ = parser.make_binary_op (EXPR_LT, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_LE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_LE, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_EQ simple_expr
-                  { $$ = parser.make_binary_op (EXPR_EQ, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_GE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_GE, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_GT simple_expr
-                  { $$ = parser.make_binary_op (EXPR_GT, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_NE simple_expr
-                  { $$ = parser.make_binary_op (EXPR_NE, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_AND simple_expr
-                  { $$ = parser.make_binary_op (EXPR_AND, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_OR simple_expr
-                  { $$ = parser.make_binary_op (EXPR_OR, $1, $2, $3); }
+                  { $$ = parser.make_binary_op ($1, $2, $3); }
                 | simple_expr EXPR_AND_AND simple_expr
-                  { $$ = parser.make_boolean_op (EXPR_AND_AND, $1, $2, $3); }
+                  { $$ = parser.make_boolean_op ($1, $2, $3); }
                 | simple_expr EXPR_OR_OR simple_expr
-                  { $$ = parser.make_boolean_op (EXPR_OR_OR, $1, $2, $3); }
+                  { $$ = parser.make_boolean_op ($1, $2, $3); }
                 ;
 
 assign_lhs      : simple_expr
                   {
-                    $$ = parser.validate_matrix_for_assignment ($1);
-
-                    if ($$)
-                      { lexer.m_looking_at_matrix_or_assign_lhs = false; }
-                    else
+                    if (! ($$ = parser.validate_matrix_for_assignment ($1)))
                       {
                         // validate_matrix_for_assignment deleted $1.
                         YYABORT;
                       }
+
+                    lexer.m_looking_at_matrix_or_assign_lhs = false;
                   }
                 ;
 
 assign_expr     : assign_lhs '=' expression
-                  { $$ = parser.make_assign_op ('=', $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs ADD_EQ expression
-                  { $$ = parser.make_assign_op (ADD_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs SUB_EQ expression
-                  { $$ = parser.make_assign_op (SUB_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs MUL_EQ expression
-                  { $$ = parser.make_assign_op (MUL_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs DIV_EQ expression
-                  { $$ = parser.make_assign_op (DIV_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs LEFTDIV_EQ expression
-                  { $$ = parser.make_assign_op (LEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs POW_EQ expression
-                  { $$ = parser.make_assign_op (POW_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs EMUL_EQ expression
-                  { $$ = parser.make_assign_op (EMUL_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs EDIV_EQ expression
-                  { $$ = parser.make_assign_op (EDIV_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs ELEFTDIV_EQ expression
-                  { $$ = parser.make_assign_op (ELEFTDIV_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs EPOW_EQ expression
-                  { $$ = parser.make_assign_op (EPOW_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs AND_EQ expression
-                  { $$ = parser.make_assign_op (AND_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 | assign_lhs OR_EQ expression
-                  { $$ = parser.make_assign_op (OR_EQ, $1, $2, $3); }
+                  { $$ = parser.make_assign_op ($1, $2, $3); }
                 ;
 
 expression      : simple_expr
@@ -1038,8 +958,6 @@
                   { $$ = $1; }
                 | function
                   { $$ = $1; }
-                | file
-                  { $$ = $1; }
                 ;
 
 // ======================
@@ -1048,12 +966,12 @@
 
 declaration     : GLOBAL decl_init_list
                   {
-                    $$ = parser.make_decl_command (GLOBAL, $1, $2);
+                    $$ = parser.make_decl_command ($1, $2);
                     lexer.m_looking_at_decl_list = false;
                   }
                 | PERSISTENT decl_init_list
                   {
-                    $$ = parser.make_decl_command (PERSISTENT, $1, $2);
+                    $$ = parser.make_decl_command ($1, $2);
                     lexer.m_looking_at_decl_list = false;
                   }
                 ;
@@ -1084,49 +1002,45 @@
 // If statement
 // ============
 
-if_command      : IF stash_comment if_cmd_list END
+if_command      : if_clause_list else_clause END
                   {
-                    if (! ($$ = parser.finish_if_command ($1, $3, $4, $2)))
+                    if (! ($$ = parser.finish_if_command ($1, $2, $3)))
                       {
-                        // finish_if_command deleted $3.
+                        // finish_if_command deleted $1 and $2.
                         YYABORT;
                       }
                   }
                 ;
 
-if_cmd_list     : if_cmd_list1
-                  { $$ = $1; }
-                | if_cmd_list1 else_clause
-                  { $$ = parser.append_if_clause ($1, $2); }
-                ;
-
-if_cmd_list1    : expression stmt_begin opt_sep opt_list
-                  {
-                    OCTAVE_YYUSE ($3);
-
-                    parser.maybe_convert_to_braindead_shortcircuit ($1);
-
-                    $$ = parser.start_if_command ($1, $4);
-                  }
-                | if_cmd_list1 elseif_clause
+if_clause_list  : if_clause
+                  { $$ = parser.start_if_command ($1); }
+                | if_clause_list elseif_clause
                   { $$ = parser.append_if_clause ($1, $2); }
                 ;
 
-elseif_clause   : ELSEIF stash_comment opt_sep expression stmt_begin opt_sep opt_list
+if_clause       : IF opt_sep expression stmt_begin opt_sep opt_list
                   {
-                    OCTAVE_YYUSE ($3, $6);
-
-                    parser.maybe_convert_to_braindead_shortcircuit ($4);
-
-                    $$ = parser.make_elseif_clause ($1, $4, $7, $2);
+                    OCTAVE_YYUSE ($2, $5);
+
+                    $$ = parser.make_if_clause ($1, $3, $6);
                   }
                 ;
 
-else_clause     : ELSE stash_comment opt_sep opt_list
+elseif_clause   : ELSEIF opt_sep expression stmt_begin opt_sep opt_list
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    $$ = parser.make_else_clause ($1, $2, $4);
+                    OCTAVE_YYUSE ($2, $5);
+
+                    $$ = parser.make_if_clause ($1, $3, $6);
+                  }
+                ;
+
+else_clause     : // empty
+                  { $$ = nullptr; }
+                | ELSE opt_sep opt_list
+                  {
+                    OCTAVE_YYUSE ($2);
+
+                    $$ = parser.make_if_clause ($1, nullptr, $3);
                   }
                 ;
 
@@ -1134,13 +1048,13 @@
 // Switch statement
 // ================
 
-switch_command  : SWITCH stash_comment expression opt_sep case_list END
+switch_command  : SWITCH expression opt_sep case_list END
                   {
-                    OCTAVE_YYUSE ($4);
-
-                    if (! ($$ = parser.finish_switch_command ($1, $3, $5, $6, $2)))
+                    OCTAVE_YYUSE ($3);
+
+                    if (! ($$ = parser.finish_switch_command ($1, $2, $4, $5)))
                       {
-                        // finish_switch_command deleted $3 adn $5.
+                        // finish_switch_command deleted $2 and $4.
                         YYABORT;
                       }
                   }
@@ -1162,19 +1076,19 @@
                   { $$ = parser.append_switch_case ($1, $2); }
                 ;
 
-switch_case     : CASE stash_comment opt_sep expression stmt_begin opt_sep opt_list
+switch_case     : CASE opt_sep expression stmt_begin opt_sep opt_list
                   {
-                    OCTAVE_YYUSE ($3, $6);
-
-                    $$ = parser.make_switch_case ($1, $4, $7, $2);
+                    OCTAVE_YYUSE ($2, $5);
+
+                    $$ = parser.make_switch_case ($1, $3, $6);
                   }
                 ;
 
-default_case    : OTHERWISE stash_comment opt_sep opt_list
+default_case    : OTHERWISE opt_sep opt_list
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    $$ = parser.make_default_switch_case ($1, $2, $4);
+                    OCTAVE_YYUSE ($2);
+
+                    $$ = parser.make_default_switch_case ($1, $3);
                   }
                 ;
 
@@ -1182,65 +1096,61 @@
 // Looping
 // =======
 
-loop_command    : WHILE stash_comment expression stmt_begin opt_sep opt_list END
+loop_command    : WHILE expression stmt_begin opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($5);
-
-                    parser.maybe_convert_to_braindead_shortcircuit ($3);
-
-                    if (! ($$ = parser.make_while_command ($1, $3, $6, $7, $2)))
+                    OCTAVE_YYUSE ($4);
+
+                    parser.maybe_convert_to_braindead_shortcircuit ($2);
+
+                    if (! ($$ = parser.make_while_command ($1, $2, $5, $6)))
                       {
-                        // make_while_command deleted $3 and $6.
+                        // make_while_command deleted $2 and $5.
                         YYABORT;
                       }
                   }
-                | DO stash_comment opt_sep opt_list UNTIL expression
+                | DO opt_sep opt_list UNTIL expression
                   {
-                    OCTAVE_YYUSE ($1, $3);
-
-                    $$ = parser.make_do_until_command ($5, $4, $6, $2);
+                    OCTAVE_YYUSE ($2);
+
+                    $$ = parser.make_do_until_command ($1, $3, $4, $5);
                   }
-                | FOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
+                | FOR assign_lhs '=' expression stmt_begin opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($4, $7);
-
-                    if (! ($$ = parser.make_for_command (FOR, $1, $3, $5,
-                                                         nullptr, $8, $9, $2)))
+                    OCTAVE_YYUSE ($6);
+
+                    if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $7, $8)))
+                      {
+                        // make_for_command deleted $2, $4, and $7.
+                        YYABORT;
+                      }
+                  }
+                | FOR '(' assign_lhs '=' expression ')' opt_sep opt_list END
+                  {
+                    OCTAVE_YYUSE ($2, $4, $6, $7);
+
+                    if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, nullptr, nullptr, $6, $8, $9)))
                       {
                         // make_for_command deleted $3, $5, and $8.
                         YYABORT;
                       }
                   }
-                | FOR stash_comment '(' assign_lhs '=' expression ')' opt_sep opt_list END
+                | PARFOR assign_lhs '=' expression stmt_begin opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($3, $5, $7, $8);
-
-                    if (! ($$ = parser.make_for_command (FOR, $1, $4, $6,
-                                                         nullptr, $9, $10, $2)))
+                    OCTAVE_YYUSE ($3, $6);
+
+                    if (! ($$ = parser.make_for_command ($1, nullptr, $2, $3, $4, nullptr, nullptr, nullptr, $7, $8)))
                       {
-                        // make_for_command deleted $4, $6, and $9.
+                        // make_for_command deleted $2, $4, and $7.
                         YYABORT;
                       }
                   }
-                | PARFOR stash_comment assign_lhs '=' expression stmt_begin opt_sep opt_list END
+                | PARFOR '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($4, $7);
-
-                    if (! ($$ = parser.make_for_command (PARFOR, $1, $3, $5,
-                                                         nullptr, $8, $9, $2)))
+                    OCTAVE_YYUSE ($2, $4, $6, $8, $9);
+
+                    if (! ($$ = parser.make_for_command ($1, $2, $3, $4, $5, $6, $7, $8, $10, $11)))
                       {
-                        // make_for_command deleted $3, $5, and $8.
-                        YYABORT;
-                      }
-                  }
-                | PARFOR stash_comment '(' assign_lhs '=' expression ',' expression ')' opt_sep opt_list END
-                  {
-                    OCTAVE_YYUSE ($3, $5, $7, $9, $10);
-
-                    if (! ($$ = parser.make_for_command (PARFOR, $1, $4, $6,
-                                                         $8, $11, $12, $2)))
-                      {
-                        // make_for_command deleted $4, $6, $8, and $11.
+                        // make_for_command deleted $3, $5, $7, and $10.
                         YYABORT;
                       }
                   }
@@ -1260,7 +1170,7 @@
                     if (! ($$ = parser.make_continue_command ($1)))
                       YYABORT;
                   }
-                | FUNC_RET
+                | RETURN
                   { $$ = parser.make_return_command ($1); }
                 ;
 
@@ -1268,16 +1178,13 @@
 // Parallel execution pool
 // =======================
 
-spmd_command    : SPMD stash_comment opt_sep opt_list END
+spmd_command    : SPMD opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_spmd_command ($1, $4, $5, lc, tc)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_spmd_command ($1, $3, $4)))
                       {
-                        // make_spmd_command deleted $4, LC, and TC.
+                        // make_spmd_command deleted $3.
                         YYABORT;
                       }
                   }
@@ -1287,36 +1194,33 @@
 // Exceptions
 // ==========
 
-except_command  : UNWIND stash_comment opt_sep opt_list CLEANUP
-                  stash_comment opt_sep opt_list END
+except_command  : UNWIND opt_sep opt_list CLEANUP opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($3, $5, $7);
-
-                    if (! ($$ = parser.make_unwind_command ($1, $4, $8, $9, $2, $6)))
+                    OCTAVE_YYUSE ($2, $5);
+
+                    if (! ($$ = parser.make_unwind_command ($1, $3, $4, $6, $7)))
                       {
-                        // make_unwind_command deleted $4 and $8.
+                        // make_unwind_command deleted $3 and $6.
                         YYABORT;
                       }
                   }
-                | TRY stash_comment opt_sep opt_list CATCH stash_comment
-                  opt_sep opt_list END
+                | TRY opt_sep opt_list CATCH opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($3, $5, $7);
-
-                    if (! ($$ = parser.make_try_command ($1, $4, $7, $8, $9, $2, $6)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_try_command ($1, $3, $4, $5, $6, $7)))
                       {
-                        // make_try_command deleted $4 and $8.
+                        // make_try_command deleted $3 and $6.
                         YYABORT;
                       }
                   }
-                | TRY stash_comment opt_sep opt_list END
+                | TRY opt_sep opt_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    if (! ($$ = parser.make_try_command ($1, $4, 0, nullptr,
-                                                         $5, $2, nullptr)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_try_command ($1, $3, nullptr, 0, nullptr, $4)))
                       {
-                        // make_try_command deleted $4.
+                        // make_try_command deleted $3.
                         YYABORT;
                       }
                   }
@@ -1341,9 +1245,6 @@
 
 param_list_beg  : '('
                   {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = 0;
                     lexer.m_looking_at_parameter_list = true;
                     lexer.m_arguments_is_keyword = false;
 
@@ -1354,17 +1255,17 @@
                         lexer.m_looking_at_function_handle--;
                         lexer.m_looking_at_anon_fcn_args = true;
                       }
+
+                    $$ = $1;
                   }
                 ;
 
 param_list_end  : ')'
                   {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = 0;
                     lexer.m_looking_at_parameter_list = false;
                     lexer.m_arguments_is_keyword = true;
                     lexer.m_looking_for_object_index = false;
+                    $$ = $1;
                   }
                 ;
 
@@ -1379,11 +1280,14 @@
                     if ($2)
                       lexer.mark_as_variables ($2->variable_names ());
 
-                    $$ = $2;
+                    $$ = $2->mark_in_delims (*($1), *($3));
                   }
                 | param_list_beg error
                   {
+                    OCTAVE_YYUSE ($1);
+
                     $$ = nullptr;
+
                     parser.bison_error ("invalid parameter list");
                     YYABORT;
                   }
@@ -1411,11 +1315,7 @@
 param_list2     : param_list_elt
                   { $$ = parser.make_parameter_list (octave::tree_parameter_list::in, $1); }
                 | param_list2 ',' param_list_elt
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_parameter_list ($1, $3);
-                  }
+                  { $$ = parser.append_parameter_list ($1, $2, $3); }
                 ;
 
 param_list_elt  : decl_elt
@@ -1430,18 +1330,17 @@
 
 return_list     : '[' ']'
                   {
-                    OCTAVE_YYUSE ($1, $2);
-
                     lexer.m_looking_at_return_list = false;
 
-                    $$ = parser.make_parameter_list (octave::tree_parameter_list::out);
+                    octave::tree_parameter_list *tmp = parser.make_parameter_list (octave::tree_parameter_list::out);
+
+                    $$ = tmp->mark_in_delims (*($1), *($2));
                   }
                 | identifier
                   {
                     lexer.m_looking_at_return_list = false;
 
-                    octave::tree_parameter_list *tmp
-                      = parser.make_parameter_list (octave::tree_parameter_list::out, $1);
+                    octave::tree_parameter_list *tmp = parser.make_parameter_list (octave::tree_parameter_list::out, $1);
 
                     // Even though this parameter list can contain only
                     // a single identifier, we still need to validate it
@@ -1457,15 +1356,13 @@
                   }
                 | '[' return_list1 ']'
                   {
-                    OCTAVE_YYUSE ($1, $3);
-
                     lexer.m_looking_at_return_list = false;
 
                     // Check for duplicate parameter names, varargin,
                     // or varargout.
 
                     if (parser.validate_param_list ($2, octave::tree_parameter_list::out))
-                      $$ = $2;
+                      $$ = $2->mark_in_delims (*($1), *($3));
                     else
                       {
                         delete $2;
@@ -1475,15 +1372,9 @@
                 ;
 
 return_list1    : identifier
-                  {
-                    $$ = parser.make_parameter_list (octave::tree_parameter_list::out, $1);
-                  }
+                  { $$ = parser.make_parameter_list (octave::tree_parameter_list::out, $1); }
                 | return_list1 ',' identifier
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_parameter_list ($1, $3);
-                  }
+                  { $$ = parser.append_parameter_list ($1, $2, $3); }
                 ;
 
 // =======================
@@ -1525,32 +1416,27 @@
                         lexer.m_symtab_context.pop ();
 
                         delete $3;
-
-                        if (! parser.validate_primary_fcn ())
-                          YYABORT;
                       }
                     else
                       {
-                        octave::tree_statement *end_of_script
-                          = parser.make_end ("endscript", true,
-                                             $4->beg_pos (), $4->end_pos ());
+                        octave::tree_statement *end_of_script = parser.make_end ("endscript", true, $4);
 
                         parser.make_script ($3, end_of_script);
-
-                        if (! parser.validate_primary_fcn ())
-                          YYABORT;
                       }
 
+                    if (! parser.validate_primary_fcn ())
+                      YYABORT;
+
                     $$ = nullptr;
                   }
                 | begin_file opt_nl classdef parsing_local_fcns opt_sep opt_fcn_list END_OF_INPUT
                   {
-                    OCTAVE_YYUSE ($2, $5, $7);
+                    OCTAVE_YYUSE ($2, $5);
 
                     // Unused symbol table context.
                     lexer.m_symtab_context.pop ();
 
-                    if (! parser.finish_classdef_file ($3, $6))
+                    if (! parser.finish_classdef_file ($3, $6, $7))
                       YYABORT;
 
                     $$ = nullptr;
@@ -1561,12 +1447,12 @@
 // Function definition
 // ===================
 
-function_beg    : push_fcn_symtab FCN
+function_beg    : push_fcn_symtab FUNCTION
                   {
+                    if (lexer.m_reading_classdef_file || lexer.m_parsing_classdef)
+                      lexer.m_maybe_classdef_get_set_method = true;
+
                     $$ = $2;
-                    if (lexer.m_reading_classdef_file
-                        || lexer.m_parsing_classdef)
-                      lexer.m_maybe_classdef_get_set_method = true;
                   }
                 ;
 
@@ -1582,9 +1468,7 @@
                   }
                 | GET '.' identifier
                   {
-                    OCTAVE_YYUSE ($1, $2);
-
-                    $$ = $3;
+                    $$ = $3->mark_get_set (*($1), *($2));
 
                     lexer.m_parsed_function_name.top () = true;
                     lexer.m_maybe_classdef_get_set_method = false;
@@ -1593,9 +1477,7 @@
                   }
                 | SET '.' identifier
                   {
-                    OCTAVE_YYUSE ($1, $2);
-
-                    $$ = $3;
+                    $$ = $3->mark_get_set (*($1), *($2));
 
                     lexer.m_parsed_function_name.top () = true;
                     lexer.m_maybe_classdef_get_set_method = false;
@@ -1609,8 +1491,7 @@
                     parser.endfunction_found (true);
 
                     if (parser.end_token_ok ($1, octave::token::function_end))
-                      $$ = parser.make_end ("endfunction", false,
-                                            $1->beg_pos (), $1->end_pos ());
+                      $$ = parser.make_end ("endfunction", false, $1);
                     else
                       {
                         parser.end_token_error ($1, octave::token::function_end);
@@ -1647,31 +1528,26 @@
                         YYABORT;
                       }
 
-                    $$ = parser.make_end ("endfunction", true,
-                                          $1->beg_pos (), $1->end_pos ());
+                    $$ = parser.make_end ("endfunction", true, $1);
                   }
                 ;
 
-function        : function_beg stash_comment fcn_name opt_param_list opt_sep stash_comment function_body function_end
+function        : function_beg fcn_name opt_param_list opt_sep function_body function_end
                   {
-                    OCTAVE_YYUSE ($5);
-
-                    $$ = parser.make_function ($1, nullptr, $3, $4, $7, $8, $2, $6);
+                    OCTAVE_YYUSE ($4);
+
+                    $$ = parser.make_function ($1, nullptr, nullptr, $2, $3, $5, $6);
                   }
-                | function_beg stash_comment return_list '=' fcn_name opt_param_list opt_sep stash_comment function_body function_end
+                | function_beg return_list '=' fcn_name opt_param_list opt_sep function_body function_end
                   {
-                    OCTAVE_YYUSE ($4, $7);
-
-                    $$ = parser.make_function ($1, $3, $5, $6, $9, $10, $2, $8);
+                    OCTAVE_YYUSE ($6);
+
+                    $$ = parser.make_function ($1, $2, $3, $4, $5, $7, $8);
                   }
                 ;
 
 function_body   : at_first_executable_stmt opt_list
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = $2;
-                  }
+                  { $$ = $2; }
                 | function_body1 opt_sep at_first_executable_stmt opt_list
                   {
                     OCTAVE_YYUSE ($2);
@@ -1682,10 +1558,7 @@
 
 at_first_executable_stmt
                 : // empty
-                  {
-                    $$ = 0;
-                    lexer.m_arguments_is_keyword = false;
-                  }
+                  { lexer.m_arguments_is_keyword = false; }
                 ;
 
 function_body1  : arguments_block
@@ -1702,17 +1575,13 @@
                   }
                 ;
 
-arguments_block : arguments_beg stash_comment opt_sep args_attr_list
-                  args_validation_list opt_sep END
+arguments_block : arguments_beg opt_sep args_attr_list args_validation_list opt_sep END
                   {
-                    OCTAVE_YYUSE ($3, $6);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_arguments_block ($1, $4, $5, $7, lc, tc)))
+                    OCTAVE_YYUSE ($2, $5);
+
+                    if (! ($$ = parser.make_arguments_block ($1, $3, $4, $6)))
                       {
-                        // make_arguments_block deleted $4, $5, LC, and TC.
+                        // make_arguments_block deleted $3, and $4.
                         YYABORT;
                       }
 
@@ -1731,7 +1600,7 @@
                   { $$ = nullptr; }
                 | '(' identifier ')'
                   {
-                    OCTAVE_YYUSE ($1, $3);
+                    $2->mark_in_delims (*($1), *($3));
 
                     // Error if $$ is nullptr.
                     if  (! ($$ = parser.make_args_attribute_list ($2)))
@@ -1765,21 +1634,29 @@
                     { $$ = $1; }
                   ;
 
-arg_validation    : size_spec class_name validation_fcns default_value
-                  {
-                    if (! ($$ = parser.make_arg_validation ($1, $2, $3, $4)))
-                      {
-                        // make_arg_validation deleted ...
-                        YYABORT;
-                      }
-                  }
+arg_validation    : size_spec class_name validation_fcns
+                    {
+                      if (! ($$ = parser.make_arg_validation ($1, $2, $3)))
+                        {
+                          // make_arg_validation deleted ...
+                          YYABORT;
+                        }
+                    }
+                  | size_spec class_name validation_fcns '=' expression
+                    {
+                      if (! ($$ = parser.make_arg_validation ($1, $2, $3, $4, $5)))
+                        {
+                          // make_arg_validation deleted ...
+                          YYABORT;
+                        }
+                    }
                 ;
 
 size_spec       : // empty
                   { $$ = nullptr; }
                 | '(' arg_list ')'
                   {
-                    OCTAVE_YYUSE ($1, $3);
+                    $2->mark_in_delims (*($1), *($3));
 
                     if (! ($$ = parser.make_arg_size_spec ($2)))
                       {
@@ -1800,7 +1677,7 @@
                   { $$ = nullptr; }
                 | '{' arg_list '}'
                   {
-                    OCTAVE_YYUSE ($1, $3);
+                    $2->mark_in_delims (*($1), *($3));
 
                     if (! ($$ = parser.make_arg_validation_fcns ($2)))
                       {
@@ -1810,16 +1687,6 @@
                   }
                 ;
 
-default_value   : // empty
-                  { $$ = nullptr; }
-                | '=' expression
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = $2;
-                  }
-                ;
-
 // ========
 // Classdef
 // ========
@@ -1842,15 +1709,15 @@
                   }
                 ;
 
-classdef        : classdef_beg stash_comment attr_list identifier opt_sep superclass_list stash_comment class_body stash_comment END
+classdef        : classdef_beg attr_list identifier opt_sep superclass_list class_body END
                   {
-                    OCTAVE_YYUSE ($5);
+                    OCTAVE_YYUSE ($4);
 
                     lexer.m_parsing_classdef = false;
 
-                    if (! ($$ = parser.make_classdef ($1, $3, $4, $6, $8, $10, $2, $7, $9)))
+                    if (! ($$ = parser.make_classdef ($1, $2, $3, $5, $6, $7)))
                       {
-                        // make_classdef deleted $2, $3, $4, $6, $7, $8, $9
+                        // make_classdef deleted $2, $3, $5, $6
                         YYABORT;
                       }
                   }
@@ -1860,49 +1727,32 @@
                   { $$ = nullptr; }
                 | '(' attr_list1 ')' opt_sep
                   {
-                    OCTAVE_YYUSE ($1, $3, $4);
-
-                    $$ = $2;
+                    OCTAVE_YYUSE ($4);
+
+                    $$ = $2->mark_in_delims (*($1), *($3));
                   }
                 ;
 
 attr_list1      : attr
                   { $$ = parser.make_classdef_attribute_list ($1); }
                 | attr_list1 ',' attr
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_classdef_attribute ($1, $3);
-                  }
+                  { $$ = parser.append_classdef_attribute ($1, $2, $3); }
                 ;
 
 attr            : identifier
                   { $$ = parser.make_classdef_attribute ($1); }
                 | identifier '=' expression
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.make_classdef_attribute ($1, $3);
-                  }
+                  { $$ = parser.make_classdef_attribute ($1, $2, $3); }
                 | '~' identifier
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = parser.make_not_classdef_attribute ($2);
-                  }
+                  { $$ = parser.make_not_classdef_attribute ($1, $2); }
                 | '!' identifier
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = parser.make_not_classdef_attribute ($2);
-                  }
+                  { $$ = parser.make_not_classdef_attribute ($1, $2); }
                 ;
 
 superclass_list : // empty
                   {
                     lexer.m_parsing_classdef_decl = false;
                     lexer.m_parsing_classdef_superclass = false;
-
                     $$ = nullptr;
                   }
                 | superclass_list1 opt_sep
@@ -1911,24 +1761,15 @@
 
                     lexer.m_parsing_classdef_decl = false;
                     lexer.m_parsing_classdef_superclass = false;
-
                     $$ = $1;
                   }
                 ;
 
 superclass_list1
                 : EXPR_LT superclass
-                  {
-                    OCTAVE_YYUSE ($1);
-
-                    $$ = parser.make_classdef_superclass_list ($2);
-                  }
+                  { $$ = parser.make_classdef_superclass_list ($1, $2); }
                 | superclass_list1 EXPR_AND superclass
-                  {
-                    OCTAVE_YYUSE ($2);
-
-                    $$ = parser.append_classdef_superclass ($1, $3);
-                  }
+                  { $$ = parser.append_classdef_superclass ($1, $2, $3); }
                 ;
 
 superclass      : FQ_IDENT
@@ -1984,18 +1825,13 @@
                 ;
 
 properties_block
-                : properties_beg stash_comment opt_sep attr_list property_list END
+                : properties_beg opt_sep attr_list property_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_classdef_properties_block
-                           ($1, $4, $5, $6, lc, tc)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_classdef_properties_block ($1, $3, $4, $5)))
                       {
-                        // make_classdef_properties_block deleted $4,
-                        // $5, LC, and TC.
+                        // make_classdef_properties_block deleted $3 and $4.
                         YYABORT;
                       }
                   }
@@ -2034,18 +1870,18 @@
                     // identifier that becomes the next element in the
                     // list.  If the element at the end of the list
                     // doesn't have a doc string, see whether the
-                    // element we are adding is stroing an end-of-line
+                    // element we are adding is storing an end-of-line
                     // comment for us to use.
 
                     octave::tree_classdef_property *last_elt = $1->back ();
 
                     if (! last_elt->have_doc_string ())
                       {
-                        octave::comment_list *cl = $3->comments ();
-
-                        if (cl)
+                        octave::comment_list comments = $3->leading_comments ();
+
+                        if (! comments.empty ())
                           {
-                            octave::comment_elt elt = cl->front ();
+                            octave::comment_elt elt = comments.front ();
 
                             if (elt.is_end_of_line ())
                               last_elt->doc_string (elt.text ());
@@ -2056,22 +1892,17 @@
                   }
                 ;
 
-class_property  : stash_comment identifier arg_validation
-                  { $$ = parser.make_classdef_property ($1, $2, $3); }
+class_property  : identifier arg_validation
+                  { $$ = parser.make_classdef_property ($1, $2); }
                 ;
 
-methods_block   : methods_beg stash_comment opt_sep attr_list methods_list END
+methods_block   : methods_beg opt_sep attr_list method_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_classdef_methods_block
-                           ($1, $4, $5, $6, lc, tc)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_classdef_methods_block ($1, $3, $4, $5)))
                       {
-                        // make_classdef_methods_block deleted $4, $5,
-                        // LC, and TC.
+                        // make_classdef_methods_block deleted $3 and $4.
                         YYABORT;
                       }
                   }
@@ -2086,7 +1917,7 @@
 
 method_decl1    : identifier
                   {
-                    if (! ($$ = parser.start_classdef_external_method ($1, nullptr)))
+                    if (! ($$ = parser.start_classdef_external_method ($1)))
                       YYABORT;
                   }
                 | identifier param_list
@@ -2096,12 +1927,10 @@
                   }
                 ;
 
-method_decl     : stash_comment method_decl1
-                  { $$ = parser.finish_classdef_external_method ($2, nullptr, $1); }
-                | stash_comment return_list '='
+method_decl     : method_decl1
+                  { $$ = parser.finish_classdef_external_method ($1); }
+                | return_list '='
                   {
-                    OCTAVE_YYUSE ($3);
-
                     lexer.m_defining_fcn++;
                     lexer.m_parsed_function_name.push (false);
                   }
@@ -2110,7 +1939,7 @@
                     lexer.m_defining_fcn--;
                     lexer.m_parsed_function_name.pop ();
 
-                    $$ = parser.finish_classdef_external_method ($5, $2, $1);
+                    $$ = parser.finish_classdef_external_method ($4, $1, $2);
                   }
                 ;
 
@@ -2120,12 +1949,12 @@
                   { $$ = $1; }
                 ;
 
-methods_list    : // empty
+method_list     : // empty
                   {
                     lexer.m_classdef_element_names_are_keywords = true;
                     $$ = nullptr;
                   }
-                | methods_list1 opt_sep
+                | method_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
@@ -2134,9 +1963,9 @@
                   }
                 ;
 
-methods_list1   : method
-                  { $$ = parser.make_classdef_methods_list ($1); }
-                | methods_list1 opt_sep method
+method_list1    : method
+                  { $$ = parser.make_classdef_method_list ($1); }
+                | method_list1 opt_sep method
                   {
                     OCTAVE_YYUSE ($2);
 
@@ -2144,18 +1973,13 @@
                   }
                 ;
 
-events_block    : events_beg stash_comment opt_sep attr_list events_list END
+events_block    : events_beg opt_sep attr_list event_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_classdef_events_block
-                           ($1, $4, $5, $6, lc, tc)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_classdef_events_block ($1, $3, $4, $5)))
                       {
-                        // make_classdef_events_block deleted $4, $5,
-                        // LC, and TC.
+                        // make_classdef_events_block deleted $4 and $5.
                         YYABORT;
                       }
                   }
@@ -2168,12 +1992,12 @@
                   }
                 ;
 
-events_list     : // empty
+event_list      : // empty
                   {
                     lexer.m_classdef_element_names_are_keywords = true;
                     $$ = nullptr;
                   }
-                | events_list1 opt_sep
+                | event_list1 opt_sep
                   {
                     OCTAVE_YYUSE ($2);
 
@@ -2182,9 +2006,9 @@
                   }
                 ;
 
-events_list1    : class_event
-                  { $$ = parser.make_classdef_events_list ($1); }
-                | events_list1 opt_sep class_event
+event_list1     : class_event
+                  { $$ = parser.make_classdef_event_list ($1); }
+                | event_list1 opt_sep class_event
                   {
                     OCTAVE_YYUSE ($2);
 
@@ -2192,22 +2016,17 @@
                   }
                 ;
 
-class_event     : stash_comment identifier
-                  { $$ = parser.make_classdef_event ($1, $2); }
+class_event     : identifier
+                  { $$ = parser.make_classdef_event ($1); }
                 ;
 
-enum_block      : enumeration_beg stash_comment opt_sep attr_list enum_list END
+enum_block      : enumeration_beg opt_sep attr_list enum_list END
                   {
-                    OCTAVE_YYUSE ($3);
-
-                    octave::comment_list *lc = $2;
-                    octave::comment_list *tc = lexer.get_comment ();
-
-                    if (! ($$ = parser.make_classdef_enum_block
-                           ($1, $4, $5, $6, lc, tc)))
+                    OCTAVE_YYUSE ($2);
+
+                    if (! ($$ = parser.make_classdef_enum_block ($1, $3, $4, $5)))
                       {
-                        // make_classdef_enum_block deleted $4, $5, LC,
-                        // and TC.
+                        // make_classdef_enum_block deleted $3 and $4.
                         YYABORT;
                       }
                   }
@@ -2244,12 +2063,8 @@
                   }
                 ;
 
-class_enum      : stash_comment identifier '(' expression ')'
-                  {
-                    OCTAVE_YYUSE ($3, $5);
-
-                    $$ = parser.make_classdef_enum ($2, $4, $1);
-                  }
+class_enum      : identifier '(' expression ')'
+                  { $$ = parser.make_classdef_enum ($1, $2, $3, $4); }
                 ;
 
 // =============
@@ -2271,12 +2086,6 @@
                   }
                 ;
 
-stash_comment   : // empty
-                  {
-                    $$ = lexer.get_comment ();
-                  }
-                ;
-
 parse_error     : LEXICAL_ERROR
                   {
                     $$ = 0;
@@ -2403,3445 +2212,3042 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-  class parse_exception : public std::runtime_error
-  {
-  public:
-
-    parse_exception () = delete;
-
-    parse_exception (const std::string& message,
-                     const std::string& fcn_name = "",
-                     const std::string& file_name = "",
-                     int line = -1, int column = -1)
-      : runtime_error (message), m_message (message),
-        m_fcn_name (fcn_name), m_file_name (file_name),
-        m_line (line), m_column (column)
-    { }
-
-    OCTAVE_DEFAULT_COPY_MOVE_DELETE (parse_exception)
-
-    std::string message () const { return m_message; }
-
-    // Provided for std::exception interface.
-    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;
-
-  private:
-
-    std::string m_message;
-
-    std::string m_fcn_name;
-    std::string m_file_name;
-    int m_line;
-    int m_column;
-  };
-
-  class parse_tree_validator : public tree_walker
+class parse_exception : public std::runtime_error
+{
+public:
+
+  parse_exception () = delete;
+
+  parse_exception (const std::string& message, const std::string& fcn_name = "", const std::string& file_name = "", const filepos& pos = filepos ())
+    : runtime_error (message), m_message (message), m_fcn_name (fcn_name), m_file_name (file_name), m_pos (pos)
+  { }
+
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (parse_exception)
+
+  std::string message () const { return m_message; }
+
+  // Provided for std::exception interface.
+  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; }
+
+  filepos pos () const { return m_pos; }
+
+  // virtual void display (std::ostream& os) const;
+
+private:
+
+  std::string m_message;
+
+  std::string m_fcn_name;
+  std::string m_file_name;
+  filepos m_pos;
+};
+
+class parse_tree_validator : public tree_walker
+{
+public:
+
+  parse_tree_validator ()
+    : m_scope (symbol_scope::anonymous ()), m_error_list ()
+  { }
+
+  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
   {
-  public:
-
-    parse_tree_validator ()
-      : m_scope (symbol_scope::anonymous ()), m_error_list ()
-    { }
-
-    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;
-    }
-
-    void visit_octave_user_script (octave_user_script& script)
-    {
-      unwind_protect_var<symbol_scope> restore_var (m_scope, script.scope ());
-
-      tree_statement_list *stmt_list = script.body ();
-
-      if (stmt_list)
-        stmt_list->accept (*this);
-    }
-
-    void visit_octave_user_function (octave_user_function& fcn)
-    {
-      unwind_protect_var<symbol_scope> restore_var (m_scope, fcn.scope ());
-
-      tree_statement_list *stmt_list = fcn.body ();
-
-      if (stmt_list)
-        stmt_list->accept (*this);
-
-      std::map<std::string, octave_value> subfcns = fcn.subfunctions ();
-
-      if (! subfcns.empty ())
-        {
-          for (auto& nm_val : subfcns)
-            {
-              octave_user_function *subfcn
-                = nm_val.second.user_function_value ();
-
-              if (subfcn)
-                subfcn->accept (*this);
-            }
-        }
-    }
-
-    void visit_index_expression (tree_index_expression& idx_expr)
-    {
-      if (idx_expr.is_word_list_cmd ())
-        {
-          std::string sym_nm = idx_expr.name ();
-
-          if (m_scope.is_variable (sym_nm))
-            {
-              std::string message
-                = sym_nm + ": invalid use of symbol as both variable and command";
-              parse_exception pe (message, m_scope.fcn_name (),
-                                  m_scope.fcn_file_name (),
-                                  idx_expr.line (), idx_expr.column ());
-
-              m_error_list.push_back (pe);
-            }
-        }
-    }
-
-  private:
-
-    symbol_scope m_scope;
-
-    std::list<parse_exception> m_error_list;
-  };
-
-  template <typename LIST_T, typename ELT_T>
-  static LIST_T *
-  list_append (LIST_T *list, ELT_T elt)
+    return m_error_list;
+  }
+
+  void visit_octave_user_script (octave_user_script& script)
   {
-    list->append (elt);
-    return list;
-  }
-
-  std::size_t
-  base_parser::parent_scope_info::size () const
-  {
-    return m_info.size ();
+    unwind_protect_var<symbol_scope> restore_var (m_scope, script.scope ());
+
+    tree_statement_list *stmt_list = script.body ();
+
+    if (stmt_list)
+      stmt_list->accept (*this);
   }
 
-  void
-  base_parser::parent_scope_info::push (const value_type& elt)
-  {
-    m_info.push_back (elt);
-  }
-
-  void
-  base_parser::parent_scope_info::push (const symbol_scope& scope)
-  {
-    push (value_type (scope, ""));
-  }
-
-  void
-  base_parser::parent_scope_info::pop ()
+  void visit_octave_user_function (octave_user_function& fcn)
   {
-    m_info.pop_back ();
-  }
-
-  bool
-  base_parser::parent_scope_info::name_ok (const std::string& name)
-  {
-    // Name can't be the same as any parent function or any other
-    // function we've already seen.  We could maintain a complex
-    // tree structure of names, or we can just store the set of
-    // full names of all the functions, which must be unique.
-
-    std::string full_name;
-
-    for (std::size_t i = 0; i < size()-1; i++)
-      {
-        const value_type& elt = m_info[i];
-
-        if (name == elt.second)
-          return false;
-
-        full_name += elt.second + ">";
-      }
-
-    full_name += name;
-
-    if (m_all_names.find (full_name) != m_all_names.end ())
+    unwind_protect_var<symbol_scope> restore_var (m_scope, fcn.scope ());
+
+    tree_statement_list *stmt_list = fcn.body ();
+
+    if (stmt_list)
+      stmt_list->accept (*this);
+
+    std::map<std::string, octave_value> subfcns = fcn.subfunctions ();
+
+    if (! subfcns.empty ())
       {
-        // Return false (failure) if we are parsing a subfunction, local
-        // function, or nested function.  Otherwise, it is OK to have a
-        // duplicate name.
-
-        return ! (m_parser.parsing_subfunctions ()
-                  || m_parser.parsing_local_functions ()
-                  || m_parser.curr_fcn_depth () > 0);
-      }
-
-    m_all_names.insert (full_name);
-
-    return true;
-  }
-
-  bool
-  base_parser::parent_scope_info::name_current_scope (const std::string& name)
-  {
-    if (! name_ok (name))
-      return false;
-
-    if (size () > 0)
-      m_info.back().second = name;
-
-    return true;
-  }
-
-  symbol_scope
-  base_parser::parent_scope_info::parent_scope () const
-  {
-    return size () > 1 ? m_info[size()-2].first : symbol_scope::invalid ();
-  }
-
-  std::string
-  base_parser::parent_scope_info::parent_name () const
-  {
-    return m_info[size()-2].second;
-  }
-
-  void base_parser::parent_scope_info::clear ()
-  {
-    m_info.clear ();
-    m_all_names.clear ();
-  }
-
-  base_parser::base_parser (base_lexer& lxr)
-    : m_endfunction_found (false), m_autoloading (false),
-      m_fcn_file_from_relative_lookup (false),
-      m_parsing_subfunctions (false), m_parsing_local_functions (false),
-      m_max_fcn_depth (-1), m_curr_fcn_depth (-1),
-      m_primary_fcn_scope (symbol_scope::invalid ()),
-      m_curr_class_name (), m_curr_package_name (), m_function_scopes (*this),
-      m_primary_fcn (), m_subfunction_names (), m_classdef_object (),
-      m_stmt_list (), m_lexer (lxr), m_parser_state (yypstate_new ())
-  { }
-
-  base_parser::~base_parser ()
-  {
-    delete &m_lexer;
-
-    // FIXME: Deleting the internal Bison parser state structure does
-    // not clean up any partial parse trees in the event of an interrupt or
-    // error.  It's not clear how to safely do that with the C language
-    // parser that Bison generates.  The C++ language parser that Bison
-    // generates would do it for us automatically whenever an exception
-    // is thrown while parsing input, but there is currently no C++
-    // interface for a push parser.
-
-    yypstate_delete (static_cast<yypstate *> (m_parser_state));
-  }
-
-  void
-  base_parser::reset ()
-  {
-    m_endfunction_found = false;
-    m_autoloading = false;
-    m_fcn_file_from_relative_lookup = false;
-    m_parsing_subfunctions = false;
-    m_parsing_local_functions = false;
-    m_max_fcn_depth = -1;
-    m_curr_fcn_depth = -1;
-    m_primary_fcn_scope = symbol_scope::invalid ();
-    m_curr_class_name = "";
-    m_curr_package_name = "";
-    m_function_scopes.clear ();
-    m_primary_fcn = octave_value ();
-    m_subfunction_names.clear ();
-    m_classdef_object.reset ();
-    m_stmt_list.reset ();
-
-    m_lexer.reset ();
-
-    yypstate_delete (static_cast<yypstate *> (m_parser_state));
-    m_parser_state = yypstate_new ();
-  }
-
-  // Error messages for mismatched end tokens.
-
-  static std::string
-  end_token_as_string (token::end_tok_type ettype)
-  {
-    std::string retval = "<unknown>";
-
-    switch (ettype)
-      {
-      case token::simple_end:
-        retval = "end";
-        break;
-
-      case token::classdef_end:
-        retval = "endclassdef";
-        break;
-
-      case token::enumeration_end:
-        retval = "endenumeration";
-        break;
-
-      case token::events_end:
-        retval = "endevents";
-        break;
-
-      case token::for_end:
-        retval = "endfor";
-        break;
-
-      case token::function_end:
-        retval = "endfunction";
-        break;
-
-      case token::if_end:
-        retval = "endif";
-        break;
-
-      case token::methods_end:
-        retval = "endmethods";
-        break;
-
-      case token::parfor_end:
-        retval = "endparfor";
-        break;
-
-      case token::properties_end:
-        retval = "endproperties";
-        break;
-
-      case token::spmd_end:
-        retval = "endspmd";
-        break;
-
-      case token::switch_end:
-        retval = "endswitch";
-        break;
-
-      case token::try_catch_end:
-        retval = "end_try_catch";
-        break;
-
-      case token::unwind_protect_end:
-        retval = "end_unwind_protect";
-        break;
-
-      case token::while_end:
-        retval = "endwhile";
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    return retval;
-  }
-
-  void
-  base_parser::statement_list (std::shared_ptr<tree_statement_list>& lst)
-  {
-    if (! lst)
-      return;
-
-    if (m_stmt_list)
-      {
-        // Append additional code to existing statement list.
-
-        while (! lst->empty ())
+        for (auto& nm_val : subfcns)
           {
-            m_stmt_list->push_back (lst->front ());
-            lst->pop_front ();
+            octave_user_function *subfcn = nm_val.second.user_function_value ();
+
+            if (subfcn)
+              subfcn->accept (*this);
           }
       }
-    else
-      m_stmt_list = lst;
   }
 
-  void
-  base_parser::end_token_error (token *tok, token::end_tok_type expected)
-  {
-    std::string msg = ("'" + end_token_as_string (expected)
-                       + "' command matched by '"
-                       + end_token_as_string (tok->ettype ()) + "'");
-
-    bison_error (msg, tok->beg_pos ());
-  }
-
-  // Check to see that end tokens are properly matched.
-
-  bool
-  base_parser::end_token_ok (token *tok, token::end_tok_type expected)
-  {
-    token::end_tok_type ettype = tok->ettype ();
-
-    return ettype == expected || ettype == token::simple_end;
-  }
-
-  bool
-  base_parser::push_fcn_symtab ()
-  {
-    m_curr_fcn_depth++;
-
-    if (m_max_fcn_depth < m_curr_fcn_depth)
-      m_max_fcn_depth = m_curr_fcn_depth;
-
-    // Will get a real name later.
-    m_lexer.m_symtab_context.push (symbol_scope ("parser:push_fcn_symtab"));
-    m_function_scopes.push (m_lexer.m_symtab_context.curr_scope ());
-
-    if (! m_lexer.m_reading_script_file && m_curr_fcn_depth == 0
-        && ! m_parsing_subfunctions)
-        {
-          m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope ();
-          m_primary_fcn_scope.mark_primary_fcn_scope ();
-        }
-
-    if (m_lexer.m_reading_script_file && m_curr_fcn_depth > 0)
-      {
-        bison_error ("nested functions not implemented in this context");
-
-        return false;
-      }
-
-    return true;
-  }
-
-  // Make a constant.
-
-  tree_constant *
-  base_parser::make_constant (token *tok_val)
+  void visit_index_expression (tree_index_expression& idx_expr)
   {
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    int op = tok_val->token_value ();
-
-    tree_constant *retval = nullptr;
-
-    switch (op)
-      {
-      case ':':
-        {
-          octave_value tmp (octave_value::magic_colon_t);
-          retval = new tree_constant (tmp);
-        }
-        break;
-
-      case NUMBER:
-        {
-          retval = new tree_constant (tok_val->number (), l, c);
-          retval->stash_original_text (tok_val->text_rep ());
-        }
-        break;
-
-      case DQ_STRING:
-      case SQ_STRING:
-        {
-          std::string txt = tok_val->text ();
-
-          char delim = op == DQ_STRING ? '"' : '\'';
-          octave_value tmp (txt, delim);
-
-          if (txt.empty ())
-            {
-              if (op == DQ_STRING)
-                tmp = octave_null_str::instance;
-              else
-                tmp = octave_null_sq_str::instance;
-            }
-
-          retval = new tree_constant (tmp, l, c);
-
-          if (op == DQ_STRING)
-            txt = undo_string_escapes (txt);
-
-          // FIXME: maybe this should also be handled by
-          // tok_val->text_rep () for character strings?
-          retval->stash_original_text (delim + txt + delim);
-        }
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    return retval;
-  }
-
-  tree_black_hole *
-  base_parser::make_black_hole ()
-  {
-    return new tree_black_hole ();
-  }
-
-  // Make a function handle.
-
-  tree_fcn_handle *
-  base_parser::make_fcn_handle (token *tok_val)
-  {
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    tree_fcn_handle *retval = new tree_fcn_handle (tok_val->text (), l, c);
-
-    return retval;
-  }
-
-  // Make an anonymous function handle.
-
-  tree_anon_fcn_handle *
-  base_parser::make_anon_fcn_handle (tree_parameter_list *param_list,
-                                     tree_expression *expr,
-                                     const filepos& at_pos)
-  {
-    // FIXME: We need to examine EXPR and issue an error if any
-    // sub-expression contains an assignment, compound assignment,
-    // increment, or decrement operator.
-
-    anon_fcn_validator validator (param_list, expr);
-
-    if (! validator.ok ())
+    if (idx_expr.is_word_list_cmd ())
       {
-        delete param_list;
-        delete expr;
-
-        bison_error (validator.message (), validator.line (),
-                     validator.column ());
-
-        return nullptr;
-      }
-
-    symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();
-    symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();
-
-    m_lexer.m_symtab_context.pop ();
-
-    expr->set_print_flag (false);
-
-    fcn_scope.mark_static ();
-
-    int at_line = at_pos.line ();
-    int at_column = at_pos.column ();
-
-    tree_anon_fcn_handle *retval
-      = new tree_anon_fcn_handle (param_list, expr, fcn_scope,
-                                  parent_scope, at_line, at_column);
-
-    std::ostringstream buf;
-
-    tree_print_code tpc (buf);
-
-    retval->accept (tpc);
-
-    std::string file = m_lexer.m_fcn_file_full_name;
-    if (! file.empty ())
-      buf << ": file: " << file;
-    else if (m_lexer.input_from_terminal ())
-      buf << ": *terminal input*";
-    else if (m_lexer.input_from_eval_string ())
-      buf << ": *eval string*";
-    buf << ": line: " << at_line << " column: " << at_column;
-
-    std::string scope_name = buf.str ();
-
-    fcn_scope.cache_name (scope_name);
-
-    // FIXME: Stash the filename.  This does not work and produces
-    // errors when executed.
-    //retval->stash_file_name (m_lexer.m_fcn_file_name);
-
-    return retval;
-  }
-
-  // Build a colon expression.
-
-  tree_expression *
-  base_parser::make_colon_expression (tree_expression *base,
-                                      tree_expression *limit,
-                                      tree_expression *incr)
-  {
-    tree_expression *retval = nullptr;
-
-    if (! base || ! limit)
-      {
-        delete base;
-        delete limit;
-        delete incr;
-
-        return retval;
-      }
-
-    int l = base->line ();
-    int c = base->column ();
-
-    tree_colon_expression *expr
-      = new tree_colon_expression (base, limit, incr, l, c);
-
-    retval = expr;
-
-    if (base->is_constant () && limit->is_constant ()
-        && (! incr || incr->is_constant ()))
-      {
-        interpreter& interp = m_lexer.m_interpreter;
-
-        try
-          {
-            // If the evaluation generates a warning message, restore
-            // the previous value of last_warning_message and skip the
-            // conversion to a constant value.
-
-            error_system& es = interp.get_error_system ();
-
-            unwind_action restore_last_warning_message
-              (&error_system::set_last_warning_message, &es,
-               es.last_warning_message (""));
-
-            unwind_action restore_discard_warning_messages
-              (&error_system::set_discard_warning_messages, &es,
-               es.discard_warning_messages (true));
-
-            tree_evaluator& tw = interp.get_evaluator ();
-
-            octave_value tmp = expr->evaluate (tw);
-
-            std::string msg = es.last_warning_message ();
-
-            if (msg.empty ())
-              {
-                tree_constant *tc_retval
-                  = new tree_constant (tmp, expr->line (), expr->column ());
-
-                std::ostringstream buf;
-
-                tree_print_code tpc (buf);
-
-                expr->accept (tpc);
-
-                tc_retval->stash_original_text (buf.str ());
-
-                delete expr;
-
-                retval = tc_retval;
-              }
-          }
-        catch (const execution_exception&)
+        std::string sym_nm = idx_expr.name ();
+
+        if (m_scope.is_variable (sym_nm))
           {
-            interp.recover_from_exception ();
-          }
-      }
-
-    return retval;
-  }
-
-  // Build a binary expression.
-
-  tree_expression *
-  base_parser::make_binary_op (int op, tree_expression *op1,
-                               token *tok_val, tree_expression *op2)
-  {
-    octave_value::binary_op t = octave_value::unknown_binary_op;
-
-    switch (op)
-      {
-      case POW:
-        t = octave_value::op_pow;
-        break;
-
-      case EPOW:
-        t = octave_value::op_el_pow;
-        break;
-
-      case '+':
-        t = octave_value::op_add;
-        break;
-
-      case '-':
-        t = octave_value::op_sub;
-        break;
-
-      case '*':
-        t = octave_value::op_mul;
-        break;
-
-      case '/':
-        t = octave_value::op_div;
-        break;
-
-      case EMUL:
-        t = octave_value::op_el_mul;
-        break;
-
-      case EDIV:
-        t = octave_value::op_el_div;
-        break;
-
-      case LEFTDIV:
-        t = octave_value::op_ldiv;
-        break;
-
-      case ELEFTDIV:
-        t = octave_value::op_el_ldiv;
-        break;
-
-      case EXPR_LT:
-        t = octave_value::op_lt;
-        break;
-
-      case EXPR_LE:
-        t = octave_value::op_le;
-        break;
-
-      case EXPR_EQ:
-        t = octave_value::op_eq;
-        break;
-
-      case EXPR_GE:
-        t = octave_value::op_ge;
-        break;
-
-      case EXPR_GT:
-        t = octave_value::op_gt;
-        break;
-
-      case EXPR_NE:
-        t = octave_value::op_ne;
-        break;
-
-      case EXPR_AND:
-        t = octave_value::op_el_and;
-        break;
-
-      case EXPR_OR:
-        t = octave_value::op_el_or;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return maybe_compound_binary_expression (op1, op2, l, c, t);
-  }
-
-  void
-  base_parser::maybe_convert_to_braindead_shortcircuit (tree_expression*& expr)
-  {
-    if (expr->is_binary_expression ())
-      {
-        tree_binary_expression *binexp
-          = dynamic_cast<tree_binary_expression *> (expr);
-
-        tree_expression *lhs = binexp->lhs ();
-        tree_expression *rhs = binexp->rhs ();
-
-        maybe_convert_to_braindead_shortcircuit (lhs);
-        maybe_convert_to_braindead_shortcircuit (rhs);
-
-        // Operands may have changed.
-        binexp->lhs (lhs);
-        binexp->rhs (rhs);
-
-        octave_value::binary_op op_type = binexp->op_type ();
-        if (op_type == octave_value::op_el_and
-            || op_type == octave_value::op_el_or)
-          {
-            binexp->preserve_operands ();
-
-            int line = expr->line ();
-            int column = expr->column ();
-
-            delete expr;
-
-            expr = new tree_braindead_shortcircuit_binary_expression
-              (lhs, rhs, line, column, op_type);
+            std::string message = sym_nm + ": invalid use of symbol as both variable and command";
+            parse_exception pe (message, m_scope.fcn_name (), m_scope.fcn_file_name (), idx_expr.beg_pos ());
+
+            m_error_list.push_back (pe);
           }
       }
   }
 
-  // Build a boolean expression.
-
-  tree_expression *
-  base_parser::make_boolean_op (int op, tree_expression *op1,
-                                token *tok_val, tree_expression *op2)
-  {
-    tree_boolean_expression::type t;
-
-    switch (op)
-      {
-      case EXPR_AND_AND:
-        t = tree_boolean_expression::bool_and;
-        break;
-
-      case EXPR_OR_OR:
-        t = tree_boolean_expression::bool_or;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_boolean_expression (op1, op2, l, c, t);
-  }
-
-  // Build a prefix expression.
-
-  tree_expression *
-  base_parser::make_prefix_op (int op, tree_expression *op1, token *tok_val)
-  {
-    octave_value::unary_op t = octave_value::unknown_unary_op;
-
-    switch (op)
-      {
-      case '~':
-      case '!':
-        t = octave_value::op_not;
-        break;
-
-      case '+':
-        t = octave_value::op_uplus;
-        break;
-
-      case '-':
-        t = octave_value::op_uminus;
-        break;
-
-      case PLUS_PLUS:
-        t = octave_value::op_incr;
-        break;
-
-      case MINUS_MINUS:
-        t = octave_value::op_decr;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_prefix_expression (op1, l, c, t);
-  }
-
-  // Build a postfix expression.
-
-  tree_expression *
-  base_parser::make_postfix_op (int op, tree_expression *op1, token *tok_val)
-  {
-    octave_value::unary_op t = octave_value::unknown_unary_op;
-
-    switch (op)
-      {
-      case HERMITIAN:
-        t = octave_value::op_hermitian;
-        break;
-
-      case TRANSPOSE:
-        t = octave_value::op_transpose;
-        break;
-
-      case PLUS_PLUS:
-        t = octave_value::op_incr;
-        break;
-
-      case MINUS_MINUS:
-        t = octave_value::op_decr;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    return new tree_postfix_expression (op1, l, c, t);
-  }
-
-  // Build an unwind-protect command.
-
-  tree_command *
-  base_parser::make_unwind_command (token *unwind_tok,
-                                    tree_statement_list *body,
-                                    tree_statement_list *cleanup_stmts,
-                                    token *end_tok,
-                                    comment_list *lc,
-                                    comment_list *mc)
-  {
-    tree_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::unwind_protect_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = unwind_tok->line ();
-        int c = unwind_tok->column ();
-
-        retval = new tree_unwind_protect_command (body, cleanup_stmts,
-                                                  lc, mc, tc, l, c);
-      }
-    else
-      {
-        delete body;
-        delete cleanup_stmts;
-
-        end_token_error (end_tok, token::unwind_protect_end);
-      }
-
-    return retval;
-  }
-
-  // Build a try-catch command.
-
-  tree_command *
-  base_parser::make_try_command (token *try_tok,
-                                 tree_statement_list *body,
-                                 char catch_sep,
-                                 tree_statement_list *cleanup_stmts,
-                                 token *end_tok,
-                                 comment_list *lc,
-                                 comment_list *mc)
-  {
-    tree_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::try_catch_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = try_tok->line ();
-        int c = try_tok->column ();
-
-        tree_identifier *id = nullptr;
-
-        if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
-          {
-            tree_statement *stmt = cleanup_stmts->front ();
-
-            if (stmt)
-              {
-                tree_expression *expr = stmt->expression ();
-
-                if (expr && expr->is_identifier ())
-                  {
-                    id = dynamic_cast<tree_identifier *> (expr);
-
-                    cleanup_stmts->pop_front ();
-
-                    stmt->set_expression (nullptr);
-                    delete stmt;
-                  }
-              }
-          }
-
-        retval = new tree_try_catch_command (body, cleanup_stmts, id,
-                                             lc, mc, tc, l, c);
-      }
-    else
-      {
-        delete body;
-        delete cleanup_stmts;
-
-        end_token_error (end_tok, token::try_catch_end);
-      }
-
-    return retval;
-  }
-
-  // Build a while command.
-
-  tree_command *
-  base_parser::make_while_command (token *while_tok,
-                                   tree_expression *expr,
-                                   tree_statement_list *body,
-                                   token *end_tok,
-                                   comment_list *lc)
-  {
-    tree_command *retval = nullptr;
-
-    maybe_warn_assign_as_truth_value (expr);
-
-    if (end_token_ok (end_tok, token::while_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        m_lexer.m_looping--;
-
-        int l = while_tok->line ();
-        int c = while_tok->column ();
-
-        retval = new tree_while_command (expr, body, lc, tc, l, c);
-      }
-    else
-      {
-        delete expr;
-        delete body;
-
-        end_token_error (end_tok, token::while_end);
-      }
-
-    return retval;
-  }
-
-  // Build a do-until command.
-
-  tree_command *
-  base_parser::make_do_until_command (token *until_tok,
-                                      tree_statement_list *body,
-                                      tree_expression *expr,
-                                      comment_list *lc)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-    m_lexer.m_looping--;
-
-    int l = until_tok->line ();
-    int c = until_tok->column ();
-
-    return new tree_do_until_command (expr, body, lc, tc, l, c);
-  }
-
-  // Build a for command.
-
-  tree_command *
-  base_parser::make_for_command (int tok_id, token *for_tok,
-                                 tree_argument_list *lhs,
-                                 tree_expression *expr,
-                                 tree_expression *maxproc,
-                                 tree_statement_list *body,
-                                 token *end_tok,
-                                 comment_list *lc)
-  {
-    tree_command *retval = nullptr;
-
-    bool parfor = tok_id == PARFOR;
-
-    if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
-      {
-        expr->mark_as_for_cmd_expr ();
-
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        m_lexer.m_looping--;
-
-        int l = for_tok->line ();
-        int c = for_tok->column ();
-
-        if (lhs->length () == 1)
-          {
-            tree_expression *tmp = lhs->remove_front ();
-
-            m_lexer.mark_as_variable (tmp->name ());
-
-            retval = new tree_simple_for_command (parfor, tmp, expr, maxproc,
-                                                  body, lc, tc, l, c);
-
-            delete lhs;
-          }
-        else if (parfor)
-          {
-            delete lhs;
-            delete expr;
-            delete maxproc;
-            delete body;
-
-            bison_error ("invalid syntax for parfor statement");
-          }
-        else
-          {
-            m_lexer.mark_as_variables (lhs->variable_names ());
-
-            retval = new tree_complex_for_command (lhs, expr, body,
-                                                   lc, tc, l, c);
-          }
-      }
-    else
-      {
-        delete lhs;
-        delete expr;
-        delete maxproc;
-        delete body;
-
-        end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
-      }
-
-    return retval;
-  }
-
-  // Build a break command.
-
-  tree_command *
-  base_parser::make_break_command (token *break_tok)
-  {
-    int l = break_tok->line ();
-    int c = break_tok->column ();
-
-    if (! m_lexer.m_looping)
+private:
+
+  symbol_scope m_scope;
+
+  std::list<parse_exception> m_error_list;
+};
+
+template <typename LIST_T, typename ELT_T>
+static LIST_T *
+list_append (LIST_T *list, ELT_T elt)
+{
+  list->push_back (elt);
+  return list;
+}
+
+template <typename LIST_T, typename ELT_T>
+static LIST_T *
+list_append (LIST_T *list, const token& /*sep_tok*/, ELT_T elt)
+{
+  // FIXME XXX! need to capture SEP_TOK here
+  list->push_back (elt);
+  return list;
+}
+
+std::size_t
+base_parser::parent_scope_info::size () const
+{
+  return m_info.size ();
+}
+
+void
+base_parser::parent_scope_info::push (const value_type& elt)
+{
+  m_info.push_back (elt);
+}
+
+void
+base_parser::parent_scope_info::push (const symbol_scope& scope)
+{
+  push (value_type (scope, ""));
+}
+
+void
+base_parser::parent_scope_info::pop ()
+{
+  m_info.pop_back ();
+}
+
+bool
+base_parser::parent_scope_info::name_ok (const std::string& name)
+{
+  // Name can't be the same as any parent function or any other
+  // function we've already seen.  We could maintain a complex
+  // tree structure of names, or we can just store the set of
+  // full names of all the functions, which must be unique.
+
+  std::string full_name;
+
+  for (std::size_t i = 0; i < size()-1; i++)
+    {
+      const value_type& elt = m_info[i];
+
+      if (name == elt.second)
+        return false;
+
+      full_name += elt.second + ">";
+    }
+
+  full_name += name;
+
+  if (m_all_names.find (full_name) != m_all_names.end ())
+    {
+      // Return false (failure) if we are parsing a subfunction, local
+      // function, or nested function.  Otherwise, it is OK to have a
+      // duplicate name.
+
+      return ! (m_parser.parsing_subfunctions () || m_parser.parsing_local_functions () || m_parser.curr_fcn_depth () > 0);
+    }
+
+  m_all_names.insert (full_name);
+
+  return true;
+}
+
+bool
+base_parser::parent_scope_info::name_current_scope (const std::string& name)
+{
+  if (! name_ok (name))
+    return false;
+
+  if (size () > 0)
+    m_info.back().second = name;
+
+  return true;
+}
+
+symbol_scope
+base_parser::parent_scope_info::parent_scope () const
+{
+  return size () > 1 ? m_info[size()-2].first : symbol_scope::invalid ();
+}
+
+std::string
+base_parser::parent_scope_info::parent_name () const
+{
+  return m_info[size()-2].second;
+}
+
+void base_parser::parent_scope_info::clear ()
+{
+  m_info.clear ();
+  m_all_names.clear ();
+}
+
+base_parser::base_parser (base_lexer& lxr)
+  : m_endfunction_found (false), m_autoloading (false),
+    m_fcn_file_from_relative_lookup (false),
+    m_parsing_subfunctions (false), m_parsing_local_functions (false),
+    m_max_fcn_depth (-1), m_curr_fcn_depth (-1),
+    m_primary_fcn_scope (symbol_scope::invalid ()),
+    m_curr_class_name (), m_curr_package_name (), m_function_scopes (*this),
+    m_primary_fcn (), m_subfunction_names (), m_classdef_object (),
+    m_stmt_list (), m_lexer (lxr), m_parser_state (yypstate_new ())
+{ }
+
+base_parser::~base_parser ()
+{
+  delete &m_lexer;
+
+  // FIXME: Deleting the internal Bison parser state structure does
+  // not clean up any partial parse trees in the event of an interrupt or
+  // error.  It's not clear how to safely do that with the C language
+  // parser that Bison generates.  The C++ language parser that Bison
+  // generates would do it for us automatically whenever an exception
+  // is thrown while parsing input, but there is currently no C++
+  // interface for a push parser.
+
+  yypstate_delete (static_cast<yypstate *> (m_parser_state));
+}
+
+void
+base_parser::reset ()
+{
+  m_endfunction_found = false;
+  m_autoloading = false;
+  m_fcn_file_from_relative_lookup = false;
+  m_parsing_subfunctions = false;
+  m_parsing_local_functions = false;
+  m_max_fcn_depth = -1;
+  m_curr_fcn_depth = -1;
+  m_primary_fcn_scope = symbol_scope::invalid ();
+  m_curr_class_name = "";
+  m_curr_package_name = "";
+  m_function_scopes.clear ();
+  m_primary_fcn = octave_value ();
+  m_subfunction_names.clear ();
+  m_classdef_object.reset ();
+  m_stmt_list.reset ();
+
+  m_lexer.reset ();
+
+  yypstate_delete (static_cast<yypstate *> (m_parser_state));
+  m_parser_state = yypstate_new ();
+}
+
+OCTAVE_NORETURN static void
+unexpected_token (int tok_id, const char *where)
+{
+  error ("unexpected token (= %d) in %s - please report this bug", tok_id, where);
+}
+
+// Error messages for mismatched end tokens.
+
+static std::string
+end_token_as_string (token::end_tok_type ettype)
+{
+  std::string retval = "<unknown>";
+
+  switch (ettype)
+    {
+    case token::simple_end:
+      retval = "end";
+      break;
+
+    case token::arguments_end:
+      retval = "endarguments";
+      break;
+
+    case token::classdef_end:
+      retval = "endclassdef";
+      break;
+
+    case token::enumeration_end:
+      retval = "endenumeration";
+      break;
+
+    case token::events_end:
+      retval = "endevents";
+      break;
+
+    case token::for_end:
+      retval = "endfor";
+      break;
+
+    case token::function_end:
+      retval = "endfunction";
+      break;
+
+    case token::if_end:
+      retval = "endif";
+      break;
+
+    case token::methods_end:
+      retval = "endmethods";
+      break;
+
+    case token::parfor_end:
+      retval = "endparfor";
+      break;
+
+    case token::properties_end:
+      retval = "endproperties";
+      break;
+
+    case token::spmd_end:
+      retval = "endspmd";
+      break;
+
+    case token::switch_end:
+      retval = "endswitch";
+      break;
+
+    case token::try_catch_end:
+      retval = "end_try_catch";
+      break;
+
+    case token::unwind_protect_end:
+      retval = "end_unwind_protect";
+      break;
+
+    case token::while_end:
+      retval = "endwhile";
+      break;
+
+      // We should have handled all possible enum values above.  Rely on
+      // compiler diagnostics to warn if we haven't.  For example, GCC's
+      // -Wswitch option, enabled by -Wall, will provide a warning.
+    }
+
+  return retval;
+}
+
+void
+base_parser::statement_list (std::shared_ptr<tree_statement_list>& lst)
+{
+  if (! lst)
+    return;
+
+  if (m_stmt_list)
+    {
+      // Append additional code to existing statement list.
+
+      while (! lst->empty ())
+        {
+          m_stmt_list->push_back (lst->front ());
+          lst->pop_front ();
+        }
+    }
+  else
+    m_stmt_list = lst;
+}
+
+void
+base_parser::end_token_error (token *tok, token::end_tok_type expected)
+{
+  std::string msg = ("'" + end_token_as_string (expected) + "' command matched by '" + end_token_as_string (tok->ettype ()) + "'");
+
+  bison_error (msg, tok->beg_pos ());
+}
+
+// Check to see that end tokens are properly matched.
+
+bool
+base_parser::end_token_ok (token *tok, token::end_tok_type expected)
+{
+  token::end_tok_type ettype = tok->ettype ();
+
+  return ettype == expected || ettype == token::simple_end;
+}
+
+bool
+base_parser::push_fcn_symtab ()
+{
+  m_curr_fcn_depth++;
+
+  if (m_max_fcn_depth < m_curr_fcn_depth)
+    m_max_fcn_depth = m_curr_fcn_depth;
+
+  // Will get a real name later.
+  m_lexer.m_symtab_context.push (symbol_scope ("parser:push_fcn_symtab"));
+  m_function_scopes.push (m_lexer.m_symtab_context.curr_scope ());
+
+  if (! m_lexer.m_reading_script_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
+    {
+      m_primary_fcn_scope = m_lexer.m_symtab_context.curr_scope ();
+      m_primary_fcn_scope.mark_primary_fcn_scope ();
+    }
+
+  if (m_lexer.m_reading_script_file && m_curr_fcn_depth > 0)
+    {
+      bison_error ("nested functions not implemented in this context");
+
+      return false;
+    }
+
+  return true;
+}
+
+// Make a constant.
+
+tree_constant *
+base_parser::make_constant (token *tok)
+{
+  int tok_id = tok->token_id ();
+
+  tree_constant *retval = nullptr;
+
+  switch (tok_id)
+    {
+    case ':':
+      retval = new tree_constant (octave_value (octave_value::magic_colon_t), *tok);
+      break;
+
+    case NUMBER:
+      retval = new tree_constant (tok->number (), tok->text_rep (), *tok);
+      break;
+
+    case DQ_STRING:
+    case SQ_STRING:
       {
-        bison_error ("break must appear within a loop");
-        return nullptr;
-      }
-    else
-      return new tree_break_command (l, c);
-  }
-
-  // Build a continue command.
-
-  tree_command *
-  base_parser::make_continue_command (token *continue_tok)
-  {
-    int l = continue_tok->line ();
-    int c = continue_tok->column ();
-
-    if (! m_lexer.m_looping)
-      {
-        bison_error ("continue must appear within a loop");
-        return nullptr;
-      }
-    else
-      return new tree_continue_command (l, c);
-  }
-
-  // Build a return command.
-
-  tree_command *
-  base_parser::make_return_command (token *return_tok)
-  {
-    int l = return_tok->line ();
-    int c = return_tok->column ();
-
-    return new tree_return_command (l, c);
-  }
-
-  // Build an spmd command.
-
-  tree_spmd_command *
-  base_parser::make_spmd_command (token *spmd_tok, tree_statement_list *body,
-                                  token *end_tok, comment_list *lc,
-                                  comment_list *tc)
-  {
-    tree_spmd_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::spmd_end))
-      {
-        int l = spmd_tok->line ();
-        int c = spmd_tok->column ();
-
-        retval = new tree_spmd_command (body, lc, tc, l, c);
-      }
-    else
-      {
-        delete body;
-        delete lc;
-        delete tc;
-
-        end_token_error (end_tok, token::spmd_end);
-      }
-
-    return retval;
-  }
-
-  // Start an if command.
-
-  tree_if_command_list *
-  base_parser::start_if_command (tree_expression *expr,
-                                 tree_statement_list *list)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    // Line and column will be set in finish_if_command.
-
-    tree_if_clause *t = new tree_if_clause (expr, list);
-
-    return new tree_if_command_list (t);
-  }
-
-  // Finish an if command.
-
-  tree_if_command *
-  base_parser::finish_if_command (token *if_tok,
-                                  tree_if_command_list *list,
-                                  token *end_tok,
-                                  comment_list *lc)
-  {
-    tree_if_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::if_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = if_tok->line ();
-        int c = if_tok->column ();
-
-        if (list && ! list->empty ())
+        std::string txt = tok->text ();
+
+        char delim = tok_id == DQ_STRING ? '"' : '\'';
+        octave_value tmp (txt, delim);
+
+        if (txt.empty ())
           {
-            tree_if_clause *elt = list->front ();
-
-            if (elt)
-              {
-                elt->line (l);
-                elt->column (c);
-              }
-          }
-
-        retval = new tree_if_command (list, lc, tc, l, c);
-      }
-    else
-      {
-        delete list;
-
-        end_token_error (end_tok, token::if_end);
-      }
-
-    return retval;
-  }
-
-  // Build an elseif clause.
-
-  tree_if_clause *
-  base_parser::make_elseif_clause (token *elseif_tok,
-                                   tree_expression *expr,
-                                   tree_statement_list *list,
-                                   comment_list *lc)
-  {
-    maybe_warn_assign_as_truth_value (expr);
-
-    int l = elseif_tok->line ();
-    int c = elseif_tok->column ();
-
-    return new tree_if_clause (expr, list, lc, l, c);
-  }
-
-  tree_if_clause *
-  base_parser::make_else_clause (token *else_tok, comment_list *lc,
-                                 tree_statement_list *list)
-  {
-    int l = else_tok->line ();
-    int c = else_tok->column ();
-
-    return new tree_if_clause (list, lc, l, c);
-  }
-
-  tree_if_command_list *
-  base_parser::append_if_clause (tree_if_command_list *list,
-                                 tree_if_clause *clause)
-  {
-    return list_append (list, clause);
-  }
-
-  // Finish a switch command.
-
-  tree_switch_command *
-  base_parser::finish_switch_command (token *switch_tok,
-                                      tree_expression *expr,
-                                      tree_switch_case_list *list,
-                                      token *end_tok,
-                                      comment_list *lc)
-  {
-    tree_switch_command *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::switch_end))
-      {
-        comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-        int l = switch_tok->line ();
-        int c = switch_tok->column ();
-
-        if (list && ! list->empty ())
-          {
-            tree_switch_case *elt = list->front ();
-
-            if (elt)
-              {
-                elt->line (l);
-                elt->column (c);
-              }
-          }
-
-        retval = new tree_switch_command (expr, list, lc, tc, l, c);
-      }
-    else
-      {
-        delete expr;
-        delete list;
-
-        end_token_error (end_tok, token::switch_end);
-      }
-
-    return retval;
-  }
-
-  tree_switch_case_list *
-  base_parser::make_switch_case_list (tree_switch_case *switch_case)
-  {
-    return new tree_switch_case_list (switch_case);
-  }
-
-  // Build a switch case.
-
-  tree_switch_case *
-  base_parser::make_switch_case (token *case_tok,
-                                 tree_expression *expr,
-                                 tree_statement_list *list,
-                                 comment_list *lc)
-  {
-    maybe_warn_variable_switch_label (expr);
-
-    int l = case_tok->line ();
-    int c = case_tok->column ();
-
-    return new tree_switch_case (expr, list, lc, l, c);
-  }
-
-  tree_switch_case *
-  base_parser::make_default_switch_case (token *default_tok, comment_list *lc,
-                                         tree_statement_list *list)
-  {
-    int l = default_tok->line ();
-    int c = default_tok->column ();
-
-    return new tree_switch_case (list, lc, l, c);
-  }
-
-  tree_switch_case_list *
-  base_parser::append_switch_case (tree_switch_case_list *list,
-                                   tree_switch_case *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  // Build an assignment to a variable.
-
-  tree_expression *
-  base_parser::make_assign_op (int op, tree_argument_list *lhs,
-                               token *eq_tok, tree_expression *rhs)
-  {
-    octave_value::assign_op t = octave_value::unknown_assign_op;
-
-    switch (op)
-      {
-      case '=':
-        t = octave_value::op_asn_eq;
-        break;
-
-      case ADD_EQ:
-        t = octave_value::op_add_eq;
-        break;
-
-      case SUB_EQ:
-        t = octave_value::op_sub_eq;
-        break;
-
-      case MUL_EQ:
-        t = octave_value::op_mul_eq;
-        break;
-
-      case DIV_EQ:
-        t = octave_value::op_div_eq;
-        break;
-
-      case LEFTDIV_EQ:
-        t = octave_value::op_ldiv_eq;
-        break;
-
-      case POW_EQ:
-        t = octave_value::op_pow_eq;
-        break;
-
-      case EMUL_EQ:
-        t = octave_value::op_el_mul_eq;
-        break;
-
-      case EDIV_EQ:
-        t = octave_value::op_el_div_eq;
-        break;
-
-      case ELEFTDIV_EQ:
-        t = octave_value::op_el_ldiv_eq;
-        break;
-
-      case EPOW_EQ:
-        t = octave_value::op_el_pow_eq;
-        break;
-
-      case AND_EQ:
-        t = octave_value::op_el_and_eq;
-        break;
-
-      case OR_EQ:
-        t = octave_value::op_el_or_eq;
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    int l = eq_tok->line ();
-    int c = eq_tok->column ();
-
-    if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
-      {
-        // Multiple assignments like [x,y] OP= rhs are only valid for
-        // '=', not '+=', etc.
-
-        delete lhs;
-        delete rhs;
-
-        bison_error ("computed multiple assignment not allowed",
-                     eq_tok->beg_pos ());
-
-        return nullptr;
-      }
-
-    if (lhs->is_simple_assign_lhs ())
-      {
-        // We are looking at a simple assignment statement like x = rhs;
-
-        tree_expression *tmp = lhs->remove_front ();
-
-        if ((tmp->is_identifier () || tmp->is_index_expression ())
-            && iskeyword (tmp->name ()))
-          {
-            std::string kw = tmp->name ();
-
-            delete tmp;
-            delete lhs;
-            delete rhs;
-
-            bison_error ("invalid assignment to keyword \"" + kw + "\"",
-                         eq_tok->beg_pos ());
-
-            return nullptr;
+            if (tok_id == DQ_STRING)
+              tmp = octave_null_str::instance;
+            else
+              tmp = octave_null_sq_str::instance;
           }
 
-        delete lhs;
-
-        m_lexer.mark_as_variable (tmp->name ());
-
-        return new tree_simple_assignment (tmp, rhs, false, l, c, t);
-      }
-    else
-      {
-        std::list<std::string> names = lhs->variable_names ();
-
-        for (const auto& kw : names)
-          {
-            if (iskeyword (kw))
-              {
-                delete lhs;
-                delete rhs;
-
-                bison_error ("invalid assignment to keyword \"" + kw + "\"",
-                             eq_tok->beg_pos ());
-
-                return nullptr;
-              }
-          }
-
-        m_lexer.mark_as_variables (names);
-
-        return new tree_multi_assignment (lhs, rhs, false, l, c);
-      }
-  }
-
-  void
-  base_parser::make_script (tree_statement_list *cmds,
-                            tree_statement *end_script)
-  {
-    // Any comments at the beginning of a script file should be
-    // attached to the first statement in the file or the END_SCRIPT
-    // statement created by the parser.
-
-    if (! cmds)
-      cmds = new tree_statement_list ();
-
-    cmds->append (end_script);
-
-    symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();
-
-    script_scope.cache_name (m_lexer.m_fcn_file_full_name);
-    script_scope.cache_fcn_file_name (m_lexer.m_fcn_file_full_name);
-    script_scope.cache_dir_name (m_lexer.m_dir_name);
-
-    // First non-copyright comment in classdef body, before first
-    // properties, methods, etc. block.
-
-    tree_statement *first_stmt = cmds->front ();
-    comment_list *leading_comments = first_stmt->comment_text ();
-
-    std::string doc_string;
-    if (leading_comments)
-      doc_string = leading_comments->find_doc_string ();
-
-    octave_user_script *script
-      = new octave_user_script (m_lexer.m_fcn_file_full_name,
-                                m_lexer.m_fcn_file_name, script_scope,
-                                cmds, doc_string);
-
-    m_lexer.m_symtab_context.pop ();
-
-    sys::time now;
-
-    script->stash_fcn_file_time (now);
-    script->stash_dir_name (m_lexer.m_dir_name);
-
-    m_primary_fcn = octave_value (script);
-  }
-
-  tree_identifier *
-  base_parser::make_fcn_name (tree_identifier *id)
-  {
-    std::string id_name = id->name ();
-
-    // Make classdef local functions unique from classdef methods.
-
-    if (m_parsing_local_functions && m_curr_fcn_depth == 0)
-      id_name = m_lexer.m_fcn_file_name + ">" + id_name;
-
-    if (! m_function_scopes.name_current_scope (id_name))
-      {
-        bison_error ("duplicate subfunction or nested function name",
-                     id->line (), id->column ());
-
-        delete id;
-        return nullptr;
-      }
-
-    symbol_scope curr_scope = m_lexer.m_symtab_context.curr_scope ();
-    curr_scope.cache_name (id_name);
-
-    m_lexer.m_parsed_function_name.top () = true;
-    m_lexer.m_maybe_classdef_get_set_method = false;
-
-    return id;
-  }
-
-  // Define a function.
-
-  // FIXME: combining start_function, finish_function, and
-  // recover_from_parsing_function should be possible, but it makes
-  // for a large mess.  Maybe this could be a bit better organized?
-
-  tree_function_def *
-  base_parser::make_function (token *fcn_tok,
-                              tree_parameter_list *ret_list,
-                              tree_identifier *id,
-                              tree_parameter_list *param_list,
-                              tree_statement_list *body,
-                              tree_statement *end_fcn_stmt,
-                              comment_list *lc, comment_list *bc)
-  {
-    // First non-copyright comments found above and below function keyword.
-    comment_elt leading_doc_comment;
-    comment_elt body_doc_comment;
-
-    if (lc)
-      leading_doc_comment = lc->find_doc_comment ();
-
-    if (bc)
-      body_doc_comment = bc->find_doc_comment ();
-
-    // Choose which comment to use for doc string.
-
-    // For ordinary functions, use the first comment that isn't empty.
-
-    // If we are looking at a classdef method and there is a comment
-    // prior to the function keyword and another after, then
-    //
-    //   * Choose the one outside the function definition if either of
-    //     the comments use hash '#' characters.  This is the preferred
-    //     Octave style.
-    //
-    //   * Choose the one inside the function definition if both
-    //     comments use percent '%' characters.  This is
-    //     Matlab-compatible behavior.
-
-    // FIXME: maybe choose which comment to used by checking whether
-    // any language extensions are noticed in the entire source file,
-    // not just in the comments that are candidates to become the
-    // function doc string.
-
-    std::string doc_string;
-
-    if (leading_doc_comment.empty ()
-        || (m_lexer.m_parsing_classdef && ! body_doc_comment.empty ()
-            && (! (leading_doc_comment.uses_hash_char () || body_doc_comment.uses_hash_char ()))))
-      doc_string = body_doc_comment.text ();
-    else
-      doc_string = leading_doc_comment.text ();
-
-    int l = fcn_tok->line ();
-    int c = fcn_tok->column ();
-
-    octave_user_function *tmp_fcn
-      = start_function (id, param_list, body, end_fcn_stmt, doc_string);
-
-    tree_function_def *retval = finish_function (ret_list, tmp_fcn, lc, l, c);
-
-    recover_from_parsing_function ();
-
-    return retval;
-  }
-
-  // Begin defining a function.
-
-  octave_user_function *
-  base_parser::start_function (tree_identifier *id,
-                               tree_parameter_list *param_list,
-                               tree_statement_list *body,
-                               tree_statement *end_fcn_stmt,
-                               const std::string& doc_string)
-  {
-    // We'll fill in the return list later.
-
-    std::string id_name = id->name ();
-
-    delete id;
-
-    if (m_lexer.m_parsing_classdef_get_method)
-      id_name.insert (0, "get.");
-    else if (m_lexer.m_parsing_classdef_set_method)
-      id_name.insert (0, "set.");
-
-    m_lexer.m_parsing_classdef_get_method = false;
-    m_lexer.m_parsing_classdef_set_method = false;
-
-    if (! body)
-      body = new tree_statement_list ();
-
-    body->append (end_fcn_stmt);
-
-    octave_user_function *fcn
-      = new octave_user_function (m_lexer.m_symtab_context.curr_scope (),
-                                  param_list, nullptr, body);
-
-    comment_list *tc = m_lexer.m_comment_buf.get_comment ();
-
-    fcn->stash_trailing_comment (tc);
-    fcn->stash_fcn_end_location (end_fcn_stmt->line (),
-                                 end_fcn_stmt->column ());
-
-    // If input is coming from a file, issue a warning if the name of
-    // the file does not match the name of the function stated in the
-    // file.  Matlab doesn't provide a diagnostic (it ignores the stated
-    // name).
-    if (! m_autoloading && m_lexer.m_reading_fcn_file
-        && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
-      {
-        // FIXME: should m_lexer.m_fcn_file_name already be
-        // preprocessed when we get here?  It seems to only be a
-        // problem with relative filenames.
-
-        std::string nm = m_lexer.m_fcn_file_name;
-
-        std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
-
-        if (pos != std::string::npos)
-          nm = m_lexer.m_fcn_file_name.substr (pos+1);
-
-        if (nm != id_name)
-          {
-            warning_with_id
-              ("Octave:function-name-clash",
-               "function name '%s' does not agree with function filename '%s'",
-               id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
-
-            id_name = nm;
-          }
-      }
-
-    sys::time now;
-
-    fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);
-    fcn->stash_fcn_file_time (now);
-    fcn->stash_dir_name (m_lexer.m_dir_name);
-    fcn->stash_package_name (m_lexer.m_package_name);
-    fcn->mark_as_system_fcn_file ();
-    fcn->stash_function_name (id_name);
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)
-      {
-        if (m_fcn_file_from_relative_lookup)
-          fcn->mark_relative ();
-
-        if (m_lexer.m_parsing_class_method)
-          {
-            if (m_lexer.m_parsing_classdef)
-              {
-                if (m_curr_class_name == id_name)
-                  fcn->mark_as_classdef_constructor ();
-                else
-                  fcn->mark_as_classdef_method ();
-              }
-            else
-              {
-                if (m_curr_class_name == id_name)
-                  fcn->mark_as_legacy_constructor ();
-                else
-                  fcn->mark_as_legacy_method ();
-              }
-
-            fcn->stash_dispatch_class (m_curr_class_name);
-          }
-
-        std::string nm = fcn->fcn_file_name ();
-
-        sys::file_stat fs (nm);
-
-        if (fs && fs.is_newer (now))
-          warning_with_id ("Octave:future-time-stamp",
-                           "time stamp for '%s' is in the future", nm.c_str ());
-      }
-    else if (! m_lexer.input_from_tmp_history_file ()
-             && ! m_lexer.m_force_script
-             && m_lexer.m_reading_script_file
-             && m_lexer.m_fcn_file_name == id_name)
-      {
-        warning ("function '%s' defined within script file '%s'",
-                 id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-
-    // Record doc string for functions other than nested functions.
-    // We cannot currently record help for nested functions (bug #46008)
-    // because the doc_string of the outermost function is read first,
-    // whereas this function is called for the innermost function first.
-    // We could have a stack of doc_string objects in lexer.
-    if (! doc_string.empty () && m_curr_fcn_depth == 0)
-      fcn->document (doc_string);
-
-
-    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0
-        && ! m_parsing_subfunctions)
-      m_primary_fcn = octave_value (fcn);
-
-    return fcn;
-  }
-
-  tree_statement *
-  base_parser::make_end (const std::string& type, bool eof,
-                         const filepos& beg_pos, const filepos& /*end_pos*/)
-  {
-    int l = beg_pos.line ();
-    int c = beg_pos.column ();
-
-    return make_statement (new tree_no_op_command (type, eof, l, c));
-  }
-
-  tree_function_def *
-  base_parser::finish_function (tree_parameter_list *ret_list,
-                                octave_user_function *fcn,
-                                comment_list *lc,
-                                int l, int c)
-  {
-    tree_function_def *retval = nullptr;
-
-    if (! ret_list)
-      ret_list = new tree_parameter_list (tree_parameter_list::out);
-
-    ret_list->mark_as_formal_parameters ();
-
-    if (fcn)
-      {
-        std::string fcn_nm = fcn->name ();
-        std::string file = fcn->fcn_file_name ();
-
-        std::string tmp = fcn_nm;
-        if (! file.empty ())
-          tmp += ": " + file;
-
-        symbol_scope fcn_scope = fcn->scope ();
-        fcn_scope.cache_name (tmp);
-        fcn_scope.cache_fcn_name (fcn_nm);
-        fcn_scope.cache_fcn_file_name (file);
-        fcn_scope.cache_dir_name (m_lexer.m_dir_name);
-
-        if (lc)
-          fcn->stash_leading_comment (lc);
-
-        fcn->define_ret_list (ret_list);
-
-        if (m_curr_fcn_depth > 0 || m_parsing_subfunctions)
-          {
-            fcn->stash_fcn_location (l, c);
-
-            octave_value ov_fcn (fcn);
-
-            if (m_endfunction_found && m_function_scopes.size () > 1)
-              {
-                fcn->mark_as_nested_function ();
-                fcn_scope.set_nesting_depth (m_curr_fcn_depth);
-
-                symbol_scope pscope = m_function_scopes.parent_scope ();
-                fcn_scope.set_parent (pscope);
-                fcn_scope.set_primary_parent (m_primary_fcn_scope);
-
-                pscope.install_nestfunction (fcn_nm, ov_fcn, fcn_scope);
-
-                // For nested functions, the list of parent functions is
-                // set in symbol_scope::update_nest.
-              }
-            else
-              {
-                fcn->mark_as_subfunction ();
-                m_subfunction_names.push_back (fcn_nm);
-
-                fcn_scope.set_parent (m_primary_fcn_scope);
-                if (m_parsing_subfunctions)
-                  fcn_scope.set_primary_parent (m_primary_fcn_scope);
-
-                m_primary_fcn_scope.install_subfunction (fcn_nm, ov_fcn);
-              }
-          }
-
-        if (m_curr_fcn_depth == 0)
-          fcn_scope.update_nest ();
-
-        if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0)
-          {
-            // We are either reading a script file or defining a function
-            // at the command line, so this definition creates a
-            // tree_function object that is placed in the parse tree.
-            // Otherwise, it is just inserted in the symbol table,
-            // either as a subfunction or nested function (see above),
-            // or as the primary function for the file, via
-            // m_primary_fcn (see also load_fcn_from_file,,
-            // parse_fcn_file, and
-            // fcn_info::fcn_info_rep::find_user_function).
-
-            if (m_lexer.m_buffer_function_text)
-              {
-                fcn->cache_function_text (m_lexer.m_function_text,
-                                          fcn->time_parsed ());
-                m_lexer.m_buffer_function_text = false;
-              }
-
-            retval = new tree_function_def (fcn, l, c);
-          }
-      }
-
-    return retval;
-  }
-
-  tree_statement_list *
-  base_parser::append_function_body (tree_statement_list *body,
-                                     tree_statement_list *list)
-  {
-    if (list)
-      {
-        for (const auto& elt : *list)
-          list_append (body, elt);
-
-        list->clear ();
-        delete (list);
-      }
-
-    return body;
-  }
-
-  tree_arguments_block *
-  base_parser::make_arguments_block (token *arguments_tok,
-                                     tree_args_block_attribute_list *attr_list,
-                                     tree_args_block_validation_list *validation_list,
-                                     token *end_tok,
-                                     comment_list *lc, comment_list *tc)
-  {
-    tree_arguments_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::arguments_end))
-      {
-        filepos beg_pos = arguments_tok->beg_pos ();
-
-        int l = beg_pos.line ();
-        int c = beg_pos.column ();
-
-        retval = new tree_arguments_block (attr_list, validation_list, l, c);
-      }
-    else
-      {
-        delete attr_list;
-        delete validation_list;
-
-        delete lc;
-        delete tc;
-      }
-
-    return retval;
-  }
-
-  tree_arg_validation *
-  base_parser::make_arg_validation (tree_arg_size_spec *size_spec,
-                                    tree_identifier *class_name,
-                                    tree_arg_validation_fcns *validation_fcns,
-                                    tree_expression *default_value)
-  {
-    // FIXME: Validate arguments and convert to more specific types
-    // (std::string for arg_name and class_name, etc).
-
-    return new tree_arg_validation (size_spec, class_name,
-                                    validation_fcns, default_value);
-  }
-
-  tree_args_block_attribute_list *
-  base_parser::make_args_attribute_list (tree_identifier *attribute_name)
-  {
-    // FIXME: Validate argument and convert to more specific type
-    // (std::string for attribute_name).
-
-    return new tree_args_block_attribute_list (attribute_name);
-  }
-
-  tree_args_block_validation_list *
-  base_parser::make_args_validation_list (tree_arg_validation *arg_validation)
-  {
-    return new tree_args_block_validation_list (arg_validation);
-  }
-
-  tree_args_block_validation_list *
-  base_parser::append_args_validation_list (tree_args_block_validation_list *list,
-                                            tree_arg_validation *arg_validation)
-  {
-    return list_append (list, arg_validation);
-  }
-
-  tree_arg_size_spec *
-  base_parser::make_arg_size_spec (tree_argument_list *size_args)
-  {
-    // FIXME: Validate argument.
-
-    return new tree_arg_size_spec (size_args);
-  }
-
-  tree_arg_validation_fcns *
-  base_parser::make_arg_validation_fcns (tree_argument_list *fcn_args)
-  {
-    // FIXME: Validate argument.
-
-    return new tree_arg_validation_fcns (fcn_args);
-  }
-
-  void
-  base_parser::recover_from_parsing_function ()
-  {
-    m_lexer.m_symtab_context.pop ();
-
-    if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0
-        && ! m_parsing_subfunctions)
-      m_parsing_subfunctions = true;
-
-    m_curr_fcn_depth--;
-    m_function_scopes.pop ();
-
-    m_lexer.m_defining_fcn--;
-    m_lexer.m_parsed_function_name.pop ();
-    m_lexer.m_looking_at_return_list = false;
-    m_lexer.m_looking_at_parameter_list = false;
-  }
-
-  // A CLASSDEF block defines a class that has a constructor and other
-  // methods, but it is not an executable command.  Parsing the block
-  // makes some changes in the symbol table (inserting the constructor
-  // and methods, and adding to the list of known objects) and creates
-  // a parse tree containing meta information about the class.
-
-  // LC contains comments appearing before the classdef keyword.
-  // TC contains comments appearing between the classdef elements
-  // and the final end token for the classdef block.
-
-  tree_classdef *
-  base_parser::make_classdef (token *tok_val,
-                              tree_classdef_attribute_list *a,
-                              tree_identifier *id,
-                              tree_classdef_superclass_list *sc,
-                              tree_classdef_body *body, token *end_tok,
-                              comment_list *lc, comment_list *bc, comment_list *tc)
-  {
-    tree_classdef *retval = nullptr;
-
-    m_lexer.m_symtab_context.pop ();
-
-    std::string cls_name = id->name ();
-
-    std::string full_name = m_lexer.m_fcn_file_full_name;
-    std::string short_name = m_lexer.m_fcn_file_name;
-
-    std::size_t pos
-      = short_name.find_last_of (sys::file_ops::dir_sep_chars ());
-
-    if (pos != std::string::npos)
-      short_name = short_name.substr (pos+1);
-
-    if (short_name != cls_name)
-      {
-        int l = id->line ();
-        int c = id->column ();
-
-        delete a;
-        delete id;
-        delete sc;
-        delete body;
-        delete lc;
-        delete bc;
-        delete tc;
-
-        bison_error ("invalid classdef definition, the class name must match the filename", l, c);
-
-      }
-    else
-      {
-        if (end_token_ok (end_tok, token::classdef_end))
-          {
-            int l = tok_val->line ();
-            int c = tok_val->column ();
-
-            // First non-copyright comments found above and below
-            // function keyword are candidates for the documentation
-            // string.  Use the first one that is not empty.
-
-            std::string doc_string;
-
-            if (lc)
-              doc_string = lc->find_doc_string ();
-
-            if (doc_string.empty () && bc)
-              doc_string = bc->find_doc_string ();
-
-            if (! body)
-              body = new tree_classdef_body ();
-
-            // FIXME - pass body comment to tree_classdef constructor.
-
-            retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (),
-                                        doc_string, a, id, sc, body, lc, tc,
-                                        m_curr_package_name, full_name, l, c);
-          }
-        else
-          {
-            delete a;
-            delete id;
-            delete sc;
-            delete body;
-            delete lc;
-            delete bc;
-            delete tc;
-
-            end_token_error (end_tok, token::switch_end);
-          }
-      }
-
-    return retval;
-  }
-
-  // LC contains comments appearing before the properties keyword.
-  // If this properties block appears first in the list of classdef
-  // elements, this comment list will be used for the help text for the
-  // classdef block.
-
-  // TC contains comments appearing between the list of properties
-  // and the final end token for the properties block and may be used to
-  // find the doc string for the final property in the list.
-
-  tree_classdef_properties_block *
-  base_parser::make_classdef_properties_block (token *tok_val,
-                                               tree_classdef_attribute_list *a,
-                                               tree_classdef_property_list *plist,
-                                               token *end_tok,
-                                               comment_list *lc,
-                                               comment_list *tc)
-  {
-    tree_classdef_properties_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::properties_end))
-      {
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (plist)
-          {
-            // If the element at the end of the list doesn't have a doc
-            // string, see whether the first element of TC is an
-            // end-of-line comment for us to use.
-
-            if (tc)
-              {
-                tree_classdef_property *last_elt = plist->back ();
-
-                if (! last_elt->have_doc_string ())
-                  {
-                    comment_elt first_comment_elt = tc->front ();
-
-                    if (first_comment_elt.is_end_of_line ())
-                      {
-                        std::string eol_comment = first_comment_elt.text ();
-
-                        last_elt->doc_string (eol_comment);
-                      }
-                  }
-              }
-          }
-        else
-          plist = new tree_classdef_property_list ();
-
-        retval = new tree_classdef_properties_block (a, plist, lc, tc, l, c);
+        if (tok_id == DQ_STRING)
+          txt = undo_string_escapes (txt);
+
+        // FIXME: maybe the addition of delims should be handled by
+        // tok->text_rep () for character strings?
+
+        retval = new tree_constant (tmp, delim + txt + delim, *tok);
       }
-    else
-      {
-        delete a;
-        delete plist;
-        delete lc;
-        delete tc;
-
-        end_token_error (end_tok, token::properties_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_property_list *
-  base_parser::make_classdef_property_list (tree_classdef_property *prop)
-  {
-    return new tree_classdef_property_list (prop);
-  }
-
-  tree_classdef_property *
-  base_parser::make_classdef_property (comment_list *lc, tree_identifier *id,
-                                       tree_arg_validation *av)
-  {
-    av->arg_name (id);
-
-    if (av->size_spec () || av->class_name () || av->validation_fcns ())
-      warning ("size, class, and validation function specifications are not yet supported for classdef properties; INCORRECT RESULTS ARE POSSIBLE!");
-
-    return new tree_classdef_property (av, lc);
-  }
-
-  // LC contains comments appearing before the methods keyword.
-  // If this methods block appears first in the list of classdef
-  // elements, this comment list will be used for the help text for the
-  // classdef block.
-
-  tree_classdef_methods_block *
-  base_parser::make_classdef_methods_block (token *tok_val,
-                                            tree_classdef_attribute_list *a,
-                                            tree_classdef_methods_list *mlist,
-                                            token *end_tok, comment_list *lc,
-                                            comment_list *tc)
-  {
-    tree_classdef_methods_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::methods_end))
-      {
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! mlist)
-          mlist = new tree_classdef_methods_list ();
-
-        retval = new tree_classdef_methods_block (a, mlist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete mlist;
-        delete lc;
-        delete tc;
-
-        end_token_error (end_tok, token::methods_end);
-      }
-
-    return retval;
-  }
-
-  // LC contains comments appearing before the events keyword.
-  // If this events block appears first in the list of classdef
-  // elements, this comment list will be used for the help text for the
-  // classdef block.
-
-  // TC contains comments appearing between the list of events and
-  // the final end token for the events block and may be used to find
-  // the doc string for the final event in the list.
-
-  tree_classdef_events_block *
-  base_parser::make_classdef_events_block (token *tok_val,
-                                           tree_classdef_attribute_list *a,
-                                           tree_classdef_events_list *elist,
-                                           token *end_tok,
-                                           comment_list *lc,
-                                           comment_list *tc)
-  {
-    tree_classdef_events_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::events_end))
-      {
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! elist)
-          elist = new tree_classdef_events_list ();
-
-        retval = new tree_classdef_events_block (a, elist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete elist;
-        delete lc;
-        delete tc;
-
-        end_token_error (end_tok, token::events_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_events_list *
-  base_parser::make_classdef_events_list (tree_classdef_event *e)
-  {
-    return new tree_classdef_events_list (e);
-  }
-
-  tree_classdef_event *
-  base_parser::make_classdef_event (comment_list *lc, tree_identifier *id)
-  {
-    return new tree_classdef_event (id, lc);
-  }
-
-  // LC contains comments appearing before the enumeration keyword.
-  // If this enumeration block appears first in the list of classdef
-  // elements, this comment list will be used for the help text for the
-  // classdef block.
-
-  // TC contains comments appearing between the list of
-  // enumerations and the final end token for the enumeration block and
-  // may be used to find the doc string for the final enumeration in the
-  // list.
-
-  tree_classdef_enum_block *
-  base_parser::make_classdef_enum_block (token *tok_val,
-                                         tree_classdef_attribute_list *a,
-                                         tree_classdef_enum_list *elist,
-                                         token *end_tok,
-                                         comment_list *lc,
-                                         comment_list *tc)
-  {
-    tree_classdef_enum_block *retval = nullptr;
-
-    if (end_token_ok (end_tok, token::enumeration_end))
-      {
-        int l = tok_val->line ();
-        int c = tok_val->column ();
-
-        if (! elist)
-          elist = new tree_classdef_enum_list ();
-
-        retval = new tree_classdef_enum_block (a, elist, lc, tc, l, c);
-      }
-    else
-      {
-        delete a;
-        delete elist;
-        delete lc;
-        delete tc;
-
-        end_token_error (end_tok, token::enumeration_end);
-      }
-
-    return retval;
-  }
-
-  tree_classdef_enum_list *
-  base_parser::make_classdef_enum_list (tree_classdef_enum *e)
-  {
-    return new tree_classdef_enum_list (e);
-  }
-
-  tree_classdef_enum *
-  base_parser::make_classdef_enum (tree_identifier *id, tree_expression *expr,
-                                   comment_list *lc)
-  {
-    return new tree_classdef_enum (id, expr, lc);
-  }
-
-  tree_classdef_property_list *
-  base_parser::append_classdef_property (tree_classdef_property_list *list,
-                                         tree_classdef_property *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_classdef_events_list *
-  base_parser::append_classdef_event (tree_classdef_events_list *list,
-                                      tree_classdef_event *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_classdef_enum_list *
-  base_parser::append_classdef_enum (tree_classdef_enum_list *list,
-                                     tree_classdef_enum *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_classdef_superclass_list *
-  base_parser::make_classdef_superclass_list (tree_classdef_superclass *sc)
-  {
-    return new tree_classdef_superclass_list (sc);
-  }
-
-  tree_classdef_superclass *
-  base_parser::make_classdef_superclass (token *fqident)
-  {
-    return new tree_classdef_superclass (fqident->text ());
-  }
-
-  tree_classdef_superclass_list *
-  base_parser::append_classdef_superclass (tree_classdef_superclass_list *list,
-                                           tree_classdef_superclass *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_classdef_attribute_list *
-  base_parser::make_classdef_attribute_list (tree_classdef_attribute *attr)
-  {
-    return new tree_classdef_attribute_list (attr);
-  }
-
-  tree_classdef_attribute *
-  base_parser::make_classdef_attribute (tree_identifier *id,
-                                        tree_expression *expr)
-  {
-    return (expr
-            ? new tree_classdef_attribute (id, expr)
-            : new tree_classdef_attribute (id));
-  }
-
-  tree_classdef_attribute *
-  base_parser::make_not_classdef_attribute (tree_identifier *id)
-  {
-    return new tree_classdef_attribute (id, false);
-  }
-
-  tree_classdef_attribute_list *
-  base_parser::append_classdef_attribute (tree_classdef_attribute_list *list,
-                                          tree_classdef_attribute *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_classdef_body *
-  base_parser::make_classdef_body (tree_classdef_properties_block *pb)
-  {
-    return new tree_classdef_body (pb);
-  }
-
-  tree_classdef_body *
-  base_parser::make_classdef_body (tree_classdef_methods_block *mb)
-  {
-    return new tree_classdef_body (mb);
-  }
-
-  tree_classdef_body *
-  base_parser::make_classdef_body (tree_classdef_events_block *evb)
-  {
-    return new tree_classdef_body (evb);
-  }
-
-  tree_classdef_body *
-  base_parser::make_classdef_body  (tree_classdef_enum_block *enb)
-  {
-    return new tree_classdef_body (enb);
-  }
-
-  tree_classdef_body *
-  base_parser::append_classdef_properties_block (tree_classdef_body *body,
-                                                 tree_classdef_properties_block *block)
-  {
-    return list_append (body, block);
-  }
-
-  tree_classdef_body *
-  base_parser::append_classdef_methods_block (tree_classdef_body *body,
-                                              tree_classdef_methods_block *block)
-  {
-    return list_append (body, block);
-  }
-
-  tree_classdef_body *
-  base_parser::append_classdef_events_block (tree_classdef_body *body,
-                                             tree_classdef_events_block *block)
-  {
-    return list_append (body, block);
-  }
-
-  tree_classdef_body *
-  base_parser::append_classdef_enum_block (tree_classdef_body *body,
-                                           tree_classdef_enum_block *block)
-  {
-    return list_append (body, block);
-  }
-
-  octave_user_function*
-  base_parser::start_classdef_external_method (tree_identifier *id,
-                                               tree_parameter_list *pl)
-  {
-    octave_user_function* retval = nullptr;
-
-    // External methods are only allowed within @-folders. In this case,
-    // m_curr_class_name will be non-empty.
-
-    if (! m_curr_class_name.empty ())
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_constant");
+      break;
+    }
+
+  return retval;
+}
+
+tree_black_hole *
+base_parser::make_black_hole (token *tilde)
+{
+  return new tree_black_hole (*tilde);
+}
+
+// Make a function handle.
+
+tree_fcn_handle *
+base_parser::make_fcn_handle (token *tok)
+{
+  tree_fcn_handle *retval = new tree_fcn_handle (*tok);
+
+  return retval;
+}
+
+// Make an anonymous function handle.
+
+tree_anon_fcn_handle *
+base_parser::make_anon_fcn_handle (token *at_tok, tree_parameter_list *param_list, tree_expression *expr)
+{
+  // FIXME: We need to examine EXPR and issue an error if any
+  // sub-expression contains an assignment, compound assignment,
+  // increment, or decrement operator.
+
+  anon_fcn_validator validator (param_list, expr);
+
+  if (! validator.ok ())
+    {
+      delete param_list;
+      delete expr;
+
+      bison_error (validator.message (), validator.beg_pos ());
+
+      return nullptr;
+    }
+
+  symbol_scope fcn_scope = m_lexer.m_symtab_context.curr_scope ();
+  symbol_scope parent_scope = m_lexer.m_symtab_context.parent_scope ();
+
+  m_lexer.m_symtab_context.pop ();
+
+  expr->set_print_flag (false);
+
+  fcn_scope.mark_static ();
+
+  tree_anon_fcn_handle *retval = new tree_anon_fcn_handle (*at_tok, param_list, expr, fcn_scope, parent_scope);
+
+  std::ostringstream buf;
+
+  tree_print_code tpc (buf);
+
+  retval->accept (tpc);
+
+  std::string file = m_lexer.m_fcn_file_full_name;
+  if (! file.empty ())
+    buf << ": file: " << file;
+  else if (m_lexer.input_from_terminal ())
+    buf << ": *terminal input*";
+  else if (m_lexer.input_from_eval_string ())
+    buf << ": *eval string*";
+
+  filepos at_pos = at_tok->beg_pos ();
+  buf << ": line: " << at_pos.line () << " column: " << at_pos.column ();
+
+  std::string scope_name = buf.str ();
+
+  fcn_scope.cache_name (scope_name);
+
+  // FIXME: Stash the filename.  This does not work and produces
+  // errors when executed.
+  //retval->stash_file_name (m_lexer.m_fcn_file_name);
+
+  return retval;
+}
+
+// Build a colon expression.
+
+tree_expression *
+base_parser::make_colon_expression (tree_expression *base, token *colon_tok, tree_expression *limit)
+{
+  return make_colon_expression (base, colon_tok, nullptr, nullptr, limit);
+}
+
+tree_expression *
+base_parser::make_colon_expression (tree_expression *base, token *colon_1_tok, tree_expression *incr, token *colon_2_tok, tree_expression *limit)
+{
+  tree_expression *retval = nullptr;
+
+  if (! base || ! limit)
+    {
+      delete base;
+      delete limit;
+      delete incr;
+
+      return retval;
+    }
+
+  token tmp_colon_2_tok = colon_2_tok ? *colon_2_tok : token ();
+
+  tree_colon_expression *expr = new tree_colon_expression (base, *colon_1_tok, incr, tmp_colon_2_tok, limit);
+
+  retval = expr;
+
+  if (base->is_constant () && limit->is_constant () && (! incr || incr->is_constant ()))
+    {
+      interpreter& interp = m_lexer.m_interpreter;
+
+      try
+        {
+          // If the evaluation generates a warning message, restore
+          // the previous value of last_warning_message and skip the
+          // conversion to a constant value.
+
+          error_system& es = interp.get_error_system ();
+
+          unwind_action restore_last_warning_message (&error_system::set_last_warning_message, &es, es.last_warning_message (""));
+
+          unwind_action restore_discard_warning_messages (&error_system::set_discard_warning_messages, &es, es.discard_warning_messages (true));
+
+          tree_evaluator& tw = interp.get_evaluator ();
+
+          octave_value tmp = expr->evaluate (tw);
+
+          std::string msg = es.last_warning_message ();
+
+          if (msg.empty ())
+            {
+              std::ostringstream buf;
+
+              tree_print_code tpc (buf);
+
+              expr->accept (tpc);
+
+              std::string orig_text = buf.str ();
+
+              token tok (CONSTANT, tmp, orig_text, expr->beg_pos (), expr->end_pos ());
+
+              tree_constant *tc_retval = new tree_constant (tmp, orig_text, tok);
+
+              delete expr;
+
+              retval = tc_retval;
+            }
+        }
+      catch (const execution_exception&)
+        {
+          interp.recover_from_exception ();
+        }
+    }
+
+  return retval;
+}
+
+// Build a binary expression.
+
+tree_expression *
+base_parser::make_binary_op (tree_expression *op1, token *op_tok, tree_expression *op2)
+{
+  octave_value::binary_op t = octave_value::unknown_binary_op;
+
+  int tok_id = op_tok->token_id ();
+
+  switch (tok_id)
+    {
+    case POW:
+      t = octave_value::op_pow;
+      break;
+
+    case EPOW:
+      t = octave_value::op_el_pow;
+      break;
+
+    case '+':
+      t = octave_value::op_add;
+      break;
+
+    case '-':
+      t = octave_value::op_sub;
+      break;
+
+    case '*':
+      t = octave_value::op_mul;
+      break;
+
+    case '/':
+      t = octave_value::op_div;
+      break;
+
+    case EMUL:
+      t = octave_value::op_el_mul;
+      break;
+
+    case EDIV:
+      t = octave_value::op_el_div;
+      break;
+
+    case LEFTDIV:
+      t = octave_value::op_ldiv;
+      break;
+
+    case ELEFTDIV:
+      t = octave_value::op_el_ldiv;
+      break;
+
+    case EXPR_LT:
+      t = octave_value::op_lt;
+      break;
+
+    case EXPR_LE:
+      t = octave_value::op_le;
+      break;
+
+    case EXPR_EQ:
+      t = octave_value::op_eq;
+      break;
+
+    case EXPR_GE:
+      t = octave_value::op_ge;
+      break;
+
+    case EXPR_GT:
+      t = octave_value::op_gt;
+      break;
+
+    case EXPR_NE:
+      t = octave_value::op_ne;
+      break;
+
+    case EXPR_AND:
+      t = octave_value::op_el_and;
+      break;
+
+    case EXPR_OR:
+      t = octave_value::op_el_or;
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_binary_op");
+      break;
+    }
+
+  return maybe_compound_binary_expression (op1, *op_tok, op2, t);
+}
+
+void
+base_parser::maybe_convert_to_braindead_shortcircuit (tree_expression*& expr)
+{
+  if (expr->is_binary_expression ())
+    {
+      tree_binary_expression *binexp = dynamic_cast<tree_binary_expression *> (expr);
+
+      token op_tok = binexp->operator_token ();
+
+      tree_expression *lhs = binexp->lhs ();
+      tree_expression *rhs = binexp->rhs ();
+
+      maybe_convert_to_braindead_shortcircuit (lhs);
+      maybe_convert_to_braindead_shortcircuit (rhs);
+
+      // Operands may have changed.
+      binexp->lhs (lhs);
+      binexp->rhs (rhs);
+
+      octave_value::binary_op op_type = binexp->op_type ();
+      if (op_type == octave_value::op_el_and || op_type == octave_value::op_el_or)
+        {
+          binexp->preserve_operands ();
+
+          delete expr;
+
+          expr = new tree_braindead_shortcircuit_binary_expression (lhs, op_tok, rhs, op_type);
+        }
+    }
+}
+
+// Build a boolean expression.
+
+tree_expression *
+base_parser::make_boolean_op (tree_expression *op1, token *op_tok, tree_expression *op2)
+{
+  tree_boolean_expression::type t;
+
+  int tok_id = op_tok->token_id ();
+
+  switch (tok_id)
+    {
+    case EXPR_AND_AND:
+      t = tree_boolean_expression::bool_and;
+      break;
+
+    case EXPR_OR_OR:
+      t = tree_boolean_expression::bool_or;
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_boolean_op");
+      break;
+    }
+
+  return new tree_boolean_expression (op1, *op_tok, op2, t);
+}
+
+// Build a prefix expression.
+
+tree_expression *
+base_parser::make_prefix_op (token *op_tok, tree_expression *op1)
+{
+  octave_value::unary_op t = octave_value::unknown_unary_op;
+
+  int tok_id = op_tok->token_id ();
+
+  switch (tok_id)
+    {
+    case '~':
+    case '!':
+      t = octave_value::op_not;
+      break;
+
+    case '+':
+      t = octave_value::op_uplus;
+      break;
+
+    case '-':
+      t = octave_value::op_uminus;
+      break;
+
+    case PLUS_PLUS:
+      t = octave_value::op_incr;
+      break;
+
+    case MINUS_MINUS:
+      t = octave_value::op_decr;
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_prefix_op");
+      break;
+    }
+
+  return new tree_prefix_expression (*op_tok, op1, t);
+}
+
+// Build a postfix expression.
+
+tree_expression *
+base_parser::make_postfix_op (tree_expression *op1, token *op_tok)
+{
+  octave_value::unary_op t = octave_value::unknown_unary_op;
+
+  int tok_id = op_tok->token_id ();
+
+  switch (tok_id)
+    {
+    case HERMITIAN:
+      t = octave_value::op_hermitian;
+      break;
+
+    case TRANSPOSE:
+      t = octave_value::op_transpose;
+      break;
+
+    case PLUS_PLUS:
+      t = octave_value::op_incr;
+      break;
+
+    case MINUS_MINUS:
+      t = octave_value::op_decr;
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_postfix_op");
+      break;
+    }
+
+  return new tree_postfix_expression (op1, *op_tok, t);
+}
+
+// Build an unwind-protect command.
+
+tree_command *
+base_parser::make_unwind_command (token *unwind_tok, tree_statement_list *body, token *cleanup_tok, tree_statement_list *cleanup_stmts, token *end_tok)
+{
+  tree_command *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::unwind_protect_end))
+    {
+      retval = new tree_unwind_protect_command (*unwind_tok, body, *cleanup_tok, cleanup_stmts, *end_tok);
+    }
+  else
+    {
+      delete body;
+      delete cleanup_stmts;
+
+      end_token_error (end_tok, token::unwind_protect_end);
+    }
+
+  return retval;
+}
+
+// Build a try-catch command.
+
+tree_command *
+base_parser::make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, char catch_sep, tree_statement_list *cleanup_stmts, token *end_tok)
+{
+  tree_command *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::try_catch_end))
+    {
+      tree_identifier *id = nullptr;
+
+      // Look for exception ID.  Could this be done in the grammar or
+      // does that create another shift-reduce conflict?
+
+      if (! catch_sep && cleanup_stmts && ! cleanup_stmts->empty ())
+        {
+          tree_statement *stmt = cleanup_stmts->front ();
+
+          if (stmt)
+            {
+              tree_expression *expr = stmt->expression ();
+
+              if (expr && expr->is_identifier ())
+                {
+                  id = dynamic_cast<tree_identifier *> (expr);
+
+                  cleanup_stmts->pop_front ();
+
+                  stmt->set_expression (nullptr);
+                  delete stmt;
+                }
+            }
+        }
+
+      token tmp_catch_tok = catch_tok ? *catch_tok : token ();
+
+      retval = new tree_try_catch_command (*try_tok, body, tmp_catch_tok, id, cleanup_stmts, *end_tok);
+    }
+  else
+    {
+      delete body;
+      delete cleanup_stmts;
+
+      end_token_error (end_tok, token::try_catch_end);
+    }
+
+  return retval;
+}
+
+// Build a while command.
+
+tree_command *
+base_parser::make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok)
+{
+  tree_command *retval = nullptr;
+
+  maybe_warn_assign_as_truth_value (expr);
+
+  if (end_token_ok (end_tok, token::while_end))
+    {
+      m_lexer.m_looping--;
+
+      retval = new tree_while_command (*while_tok, expr, body, *end_tok);
+    }
+  else
+    {
+      delete expr;
+      delete body;
+
+      end_token_error (end_tok, token::while_end);
+    }
+
+  return retval;
+}
+
+// Build a do-until command.
+
+tree_command *
+base_parser::make_do_until_command (token *do_tok, tree_statement_list *body, token *until_tok, tree_expression *expr)
+{
+  maybe_warn_assign_as_truth_value (expr);
+
+  m_lexer.m_looping--;
+
+  return new tree_do_until_command (*do_tok, body, *until_tok, expr);
+}
+
+// Build a for command.
+
+tree_command *
+base_parser::make_for_command (token *for_tok, token *open_paren, tree_argument_list *lhs, token *eq_tok, tree_expression *expr, token *sep_tok, tree_expression *maxproc, token *close_paren, tree_statement_list *body, token *end_tok)
+{
+  tree_command *retval = nullptr;
+
+  bool parfor = for_tok->token_id () == PARFOR;
+
+  token tmp_open_paren = open_paren ? *open_paren : token ();
+  token tmp_close_paren = close_paren ? *close_paren : token ();
+  token tmp_sep_tok = sep_tok ? *sep_tok : token ();
+
+  if (end_token_ok (end_tok, parfor ? token::parfor_end : token::for_end))
+    {
+      expr->mark_as_for_cmd_expr ();
+
+      m_lexer.m_looping--;
+
+      if (lhs->size () == 1)
+        {
+          tree_expression *tmp = lhs->remove_front ();
+
+          m_lexer.mark_as_variable (tmp->name ());
+
+          retval = new tree_simple_for_command (parfor, *for_tok, tmp_open_paren, tmp, *eq_tok, expr, tmp_sep_tok, maxproc, tmp_close_paren, body, *end_tok);
+
+          delete lhs;
+        }
+      else if (parfor)
+        {
+          delete lhs;
+          delete expr;
+          delete maxproc;
+          delete body;
+
+          bison_error ("invalid syntax for parfor statement");
+        }
+      else
+        {
+          m_lexer.mark_as_variables (lhs->variable_names ());
+
+          retval = new tree_complex_for_command (*for_tok, lhs, *eq_tok, expr, body, *end_tok);
+        }
+    }
+  else
+    {
+      delete lhs;
+      delete expr;
+      delete maxproc;
+      delete body;
+
+      end_token_error (end_tok, parfor ? token::parfor_end : token::for_end);
+    }
+
+  return retval;
+}
+
+// Build a break command.
+
+tree_command *
+base_parser::make_break_command (token *break_tok)
+{
+  if (! m_lexer.m_looping)
+    {
+      bison_error ("break must appear within a loop");
+      return nullptr;
+    }
+  else
+    return new tree_break_command (*break_tok);
+}
+
+// Build a continue command.
+
+tree_command *
+base_parser::make_continue_command (token *continue_tok)
+{
+  if (! m_lexer.m_looping)
+    {
+      bison_error ("continue must appear within a loop");
+      return nullptr;
+    }
+  else
+    return new tree_continue_command (*continue_tok);
+}
+
+// Build a return command.
+
+tree_command *
+base_parser::make_return_command (token *return_tok)
+{
+  return new tree_return_command (*return_tok);
+}
+
+// Build an spmd command.
+
+tree_spmd_command *
+base_parser::make_spmd_command (token *spmd_tok, tree_statement_list *body, token *end_tok)
+{
+  tree_spmd_command *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::spmd_end))
+    retval = new tree_spmd_command (*spmd_tok, body, *end_tok);
+  else
+    {
+      delete body;
+
+      end_token_error (end_tok, token::spmd_end);
+    }
+
+  return retval;
+}
+
+// Start an if command.
+
+tree_if_command_list *
+base_parser::start_if_command (tree_if_clause *clause)
+{
+  return new tree_if_command_list (clause);
+}
+
+// Finish an if command.
+
+tree_if_command *
+base_parser::finish_if_command (tree_if_command_list *list, tree_if_clause *else_clause, token *end_tok)
+{
+  tree_if_command *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::if_end))
+    {
+      if (else_clause)
+        list_append (list, else_clause);
+
+      token if_tok = list->if_token ();
+
+      retval = new tree_if_command (if_tok, list, *end_tok);
+    }
+  else
+    {
+      delete list;
+      delete else_clause;
+
+      end_token_error (end_tok, token::if_end);
+    }
+
+  return retval;
+}
+
+// Build an if, elseif, or else clause.
+
+tree_if_clause *
+base_parser::make_if_clause (token *tok, tree_expression *expr, tree_statement_list *list)
+{
+  if (expr)
+    {
+      maybe_warn_assign_as_truth_value (expr);
+
+      maybe_convert_to_braindead_shortcircuit (expr);
+    }
+
+  return new tree_if_clause (*tok, expr, list);
+}
+
+tree_if_command_list *
+base_parser::append_if_clause (tree_if_command_list *list, tree_if_clause *clause)
+{
+  return list_append (list, clause);
+}
+
+// Finish a switch command.
+
+tree_switch_command *
+base_parser::finish_switch_command (token *switch_tok, tree_expression *expr, tree_switch_case_list *list, token *end_tok)
+{
+  tree_switch_command *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::switch_end))
+    retval = new tree_switch_command (*switch_tok, expr, list, *end_tok);
+  else
+    {
+      delete expr;
+      delete list;
+
+      end_token_error (end_tok, token::switch_end);
+    }
+
+  return retval;
+}
+
+tree_switch_case_list *
+base_parser::make_switch_case_list (tree_switch_case *switch_case)
+{
+  return new tree_switch_case_list (switch_case);
+}
+
+// Build a switch case.
+
+tree_switch_case *
+base_parser::make_switch_case (token *case_tok, tree_expression *expr, tree_statement_list *list)
+{
+  maybe_warn_variable_switch_label (expr);
+
+  return new tree_switch_case (*case_tok, expr, list);
+}
+
+tree_switch_case *
+base_parser::make_default_switch_case (token *default_tok, tree_statement_list *list)
+{
+  return new tree_switch_case (*default_tok, list);
+}
+
+tree_switch_case_list *
+base_parser::append_switch_case (tree_switch_case_list *list, tree_switch_case *elt)
+{
+  return list_append (list, elt);
+}
+
+// Build an assignment to a variable.
+
+tree_expression *
+base_parser::make_assign_op (tree_argument_list *lhs, token *eq_tok, tree_expression *rhs)
+{
+  octave_value::assign_op t = octave_value::unknown_assign_op;
+
+  int tok_id = eq_tok->token_id ();
+
+  switch (tok_id)
+    {
+    case '=':
+      t = octave_value::op_asn_eq;
+      break;
+
+    case ADD_EQ:
+      t = octave_value::op_add_eq;
+      break;
+
+    case SUB_EQ:
+      t = octave_value::op_sub_eq;
+      break;
+
+    case MUL_EQ:
+      t = octave_value::op_mul_eq;
+      break;
+
+    case DIV_EQ:
+      t = octave_value::op_div_eq;
+      break;
+
+    case LEFTDIV_EQ:
+      t = octave_value::op_ldiv_eq;
+      break;
+
+    case POW_EQ:
+      t = octave_value::op_pow_eq;
+      break;
+
+    case EMUL_EQ:
+      t = octave_value::op_el_mul_eq;
+      break;
+
+    case EDIV_EQ:
+      t = octave_value::op_el_div_eq;
+      break;
+
+    case ELEFTDIV_EQ:
+      t = octave_value::op_el_ldiv_eq;
+      break;
+
+    case EPOW_EQ:
+      t = octave_value::op_el_pow_eq;
+      break;
+
+    case AND_EQ:
+      t = octave_value::op_el_and_eq;
+      break;
+
+    case OR_EQ:
+      t = octave_value::op_el_or_eq;
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_assign_op");
+      break;
+    }
+
+  if (! lhs->is_simple_assign_lhs () && t != octave_value::op_asn_eq)
+    {
+      // Multiple assignments like [x,y] OP= rhs are only valid for
+      // '=', not '+=', etc.
+
+      delete lhs;
+      delete rhs;
+
+      bison_error ("computed multiple assignment not allowed", eq_tok->beg_pos ());
+
+      return nullptr;
+    }
+
+  if (lhs->is_simple_assign_lhs ())
+    {
+      // We are looking at a simple assignment statement like x = rhs;
+
+      tree_expression *tmp = lhs->remove_front ();
+
+      if ((tmp->is_identifier () || tmp->is_index_expression ()) && iskeyword (tmp->name ()))
+        {
+          std::string kw = tmp->name ();
+
+          delete tmp;
+          delete lhs;
+          delete rhs;
+
+          bison_error ("invalid assignment to keyword \"" + kw + "\"", eq_tok->beg_pos ());
+
+          return nullptr;
+        }
+
+      delete lhs;
+
+      m_lexer.mark_as_variable (tmp->name ());
+
+      return new tree_simple_assignment (tmp, rhs, false, t);
+    }
+  else
+    {
+      std::list<std::string> names = lhs->variable_names ();
+
+      for (const auto& kw : names)
+        {
+          if (iskeyword (kw))
+            {
+              delete lhs;
+              delete rhs;
+
+              bison_error ("invalid assignment to keyword \"" + kw + "\"", eq_tok->beg_pos ());
+
+              return nullptr;
+            }
+        }
+
+      m_lexer.mark_as_variables (names);
+
+      return new tree_multi_assignment (lhs, rhs, false);
+    }
+}
+
+void
+base_parser::make_script (tree_statement_list *cmds, tree_statement *end_script)
+{
+  // Any comments at the beginning of a script file should be
+  // attached to the first statement in the file or the END_SCRIPT
+  // statement created by the parser.
+
+  if (! cmds)
+    cmds = new tree_statement_list ();
+
+  cmds->push_back (end_script);
+
+  symbol_scope script_scope = m_lexer.m_symtab_context.curr_scope ();
+
+  script_scope.cache_name (m_lexer.m_fcn_file_full_name);
+  script_scope.cache_fcn_file_name (m_lexer.m_fcn_file_full_name);
+  script_scope.cache_dir_name (m_lexer.m_dir_name);
+
+  // First non-copyright comment in classdef body, before first
+  // properties, methods, etc. block.
+
+  comment_list leading_comments = cmds->leading_comments ();
+
+  std::string doc_string = leading_comments.find_doc_string ();
+
+  octave_user_script *script = new octave_user_script (m_lexer.m_fcn_file_full_name, m_lexer.m_fcn_file_name, script_scope, cmds, doc_string);
+
+  m_lexer.m_symtab_context.pop ();
+
+  sys::time now;
+
+  script->stash_fcn_file_time (now);
+  script->stash_dir_name (m_lexer.m_dir_name);
+
+  m_primary_fcn = octave_value (script);
+}
+
+tree_identifier *
+base_parser::make_fcn_name (tree_identifier *id)
+{
+  std::string id_name = id->name ();
+
+  // Make classdef local functions unique from classdef methods.
+
+  if (m_parsing_local_functions && m_curr_fcn_depth == 0)
+    id_name = m_lexer.m_fcn_file_name + ">" + id_name;
+
+  if (! m_function_scopes.name_current_scope (id_name))
+    {
+      // FIXME: is this correct?  Before using position, the column
+      // was incremented.  Hmm.
+
+      filepos id_pos = id->beg_pos ();
+      id_pos.increment_column ();
+
+      bison_error ("duplicate subfunction or nested function name", id_pos);
+
+      delete id;
+      return nullptr;
+    }
+
+  symbol_scope curr_scope = m_lexer.m_symtab_context.curr_scope ();
+  curr_scope.cache_name (id_name);
+
+  m_lexer.m_parsed_function_name.top () = true;
+  m_lexer.m_maybe_classdef_get_set_method = false;
+
+  return id;
+}
+
+// Define a function.
+
+// FIXME: combining start_function, finish_function, and
+// recover_from_parsing_function should be possible, but it makes
+// for a large mess.  Maybe this could be a bit better organized?
+
+tree_function_def *
+base_parser::make_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt)
+{
+  // First non-copyright comments found above and below function keyword.
+  comment_elt leading_doc_comment;
+  comment_elt body_doc_comment;
+
+  comment_list lc = fcn_tok->leading_comments ();
+
+  if (! lc.empty ())
+    leading_doc_comment = lc.find_doc_comment ();
+
+  if (body)
+    {
+      comment_list bc = body->leading_comments ();
+
+      if (! bc.empty ())
+        body_doc_comment = bc.find_doc_comment ();
+    }
+  else if (end_fcn_stmt)
+    {
+      comment_list ec = end_fcn_stmt->leading_comments ();
+
+      if (! ec.empty ())
+        body_doc_comment = ec.find_doc_comment ();
+    }
+
+  // Choose which comment to use for doc string.
+
+  // For ordinary functions, use the first comment that isn't empty.
+
+  // If we are looking at a classdef method and there is a comment
+  // prior to the function keyword and another after, then
+  //
+  //   * Choose the one outside the function definition if either of
+  //     the comments use hash '#' characters.  This is the preferred
+  //     Octave style.
+  //
+  //   * Choose the one inside the function definition if both
+  //     comments use percent '%' characters.  This is
+  //     Matlab-compatible behavior.
+
+  // FIXME: maybe choose which comment to used by checking whether
+  // any language extensions are noticed in the entire source file,
+  // not just in the comments that are candidates to become the
+  // function doc string.
+
+  std::string doc_string;
+
+  if (leading_doc_comment.empty ()
+      || (m_lexer.m_parsing_classdef && ! body_doc_comment.empty ()
+          && (! (leading_doc_comment.uses_hash_char () || body_doc_comment.uses_hash_char ()))))
+    doc_string = body_doc_comment.text ();
+  else
+    doc_string = leading_doc_comment.text ();
+
+  octave_user_function *tmp_fcn = start_function (id, param_list, body, end_fcn_stmt, doc_string);
+
+  tree_function_def *retval = finish_function (fcn_tok, ret_list, eq_tok, tmp_fcn);
+
+  recover_from_parsing_function ();
+
+  return retval;
+}
+
+// Begin defining a function.
+
+octave_user_function *
+base_parser::start_function (tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt, const std::string& doc_string)
+{
+  // We'll fill in the return list later.
+
+  std::string id_name = id->name ();
+
+  if (m_lexer.m_parsing_classdef_get_method)
+    id_name.insert (0, "get.");
+  else if (m_lexer.m_parsing_classdef_set_method)
+    id_name.insert (0, "set.");
+
+  m_lexer.m_parsing_classdef_get_method = false;
+  m_lexer.m_parsing_classdef_set_method = false;
+
+  if (! body)
+    body = new tree_statement_list ();
+
+  body->push_back (end_fcn_stmt);
+
+  octave_user_function *fcn = new octave_user_function (m_lexer.m_symtab_context.curr_scope (), id, param_list, nullptr, body);
+
+  // If input is coming from a file, issue a warning if the name of
+  // the file does not match the name of the function stated in the
+  // file.  Matlab doesn't provide a diagnostic (it ignores the stated
+  // name).
+  if (! m_autoloading && m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
+    {
+      // FIXME: should m_lexer.m_fcn_file_name already be
+      // preprocessed when we get here?  It seems to only be a
+      // problem with relative filenames.
+
+      std::string nm = m_lexer.m_fcn_file_name;
+
+      std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_chars ());
+
+      if (pos != std::string::npos)
+        nm = m_lexer.m_fcn_file_name.substr (pos+1);
+
+      if (nm != id_name)
+        {
+          warning_with_id ("Octave:function-name-clash", "function name '%s' does not agree with function filename '%s'", id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
+
+          id_name = nm;
+        }
+    }
+
+  sys::time now;
+
+  fcn->stash_fcn_file_name (m_lexer.m_fcn_file_full_name);
+  fcn->stash_fcn_file_time (now);
+  fcn->stash_dir_name (m_lexer.m_dir_name);
+  fcn->stash_package_name (m_lexer.m_package_name);
+  fcn->mark_as_system_fcn_file ();
+  fcn->stash_function_name (id_name);
+
+  if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_classdef_file || m_autoloading)
+    {
+      if (m_fcn_file_from_relative_lookup)
+        fcn->mark_relative ();
+
+      if (m_lexer.m_parsing_class_method)
+        {
+          if (m_lexer.m_parsing_classdef)
+            {
+              if (m_curr_class_name == id_name)
+                fcn->mark_as_classdef_constructor ();
+              else
+                fcn->mark_as_classdef_method ();
+            }
+          else
+            {
+              if (m_curr_class_name == id_name)
+                fcn->mark_as_legacy_constructor ();
+              else
+                fcn->mark_as_legacy_method ();
+            }
+
+          fcn->stash_dispatch_class (m_curr_class_name);
+        }
+
+      std::string nm = fcn->fcn_file_name ();
+
+      sys::file_stat fs (nm);
+
+      if (fs && fs.is_newer (now))
+        warning_with_id ("Octave:future-time-stamp", "time stamp for '%s' is in the future", nm.c_str ());
+    }
+  else if (! m_lexer.input_from_tmp_history_file () && ! m_lexer.m_force_script && m_lexer.m_reading_script_file && m_lexer.m_fcn_file_name == id_name)
+    warning ("function '%s' defined within script file '%s'", id_name.c_str (), m_lexer.m_fcn_file_full_name.c_str ());
+
+  // Record doc string for functions other than nested functions.
+  // We cannot currently record help for nested functions (bug #46008)
+  // because the doc_string of the outermost function is read first,
+  // whereas this function is called for the innermost function first.
+  // We could have a stack of doc_string objects in lexer.
+  if (! doc_string.empty () && m_curr_fcn_depth == 0)
+    fcn->document (doc_string);
+
+
+  if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
+    m_primary_fcn = octave_value (fcn);
+
+  return fcn;
+}
+
+tree_statement *
+base_parser::make_end (const std::string& type, bool eof, token *end_tok)
+{
+  return make_statement (new tree_no_op_command (type, eof, *end_tok));
+}
+
+tree_function_def *
+base_parser::finish_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, octave_user_function *fcn)
+{
+  tree_function_def *retval = nullptr;
+
+  if (! ret_list)
+    ret_list = new tree_parameter_list (tree_parameter_list::out);
+
+  ret_list->mark_as_formal_parameters ();
+
+  if (fcn)
+    {
+      fcn->set_fcn_tok (*fcn_tok);
+
+      if (eq_tok)
+        fcn->set_eq_tok (*eq_tok);
+
+      std::string fcn_nm = fcn->name ();
+      std::string file = fcn->fcn_file_name ();
+
+      std::string tmp = fcn_nm;
+      if (! file.empty ())
+        tmp += ": " + file;
+
+      symbol_scope fcn_scope = fcn->scope ();
+      fcn_scope.cache_name (tmp);
+      fcn_scope.cache_fcn_name (fcn_nm);
+      fcn_scope.cache_fcn_file_name (file);
+      fcn_scope.cache_dir_name (m_lexer.m_dir_name);
+
+      fcn->define_ret_list (ret_list);
+
+      if (m_curr_fcn_depth > 0 || m_parsing_subfunctions)
+        {
+          octave_value ov_fcn (fcn);
+
+          if (m_endfunction_found && m_function_scopes.size () > 1)
+            {
+              fcn->mark_as_nested_function ();
+              fcn_scope.set_nesting_depth (m_curr_fcn_depth);
+
+              symbol_scope pscope = m_function_scopes.parent_scope ();
+              fcn_scope.set_parent (pscope);
+              fcn_scope.set_primary_parent (m_primary_fcn_scope);
+
+              pscope.install_nestfunction (fcn_nm, ov_fcn, fcn_scope);
+
+              // For nested functions, the list of parent functions is
+              // set in symbol_scope::update_nest.
+            }
+          else
+            {
+              fcn->mark_as_subfunction ();
+              m_subfunction_names.push_back (fcn_nm);
+
+              fcn_scope.set_parent (m_primary_fcn_scope);
+              if (m_parsing_subfunctions)
+                fcn_scope.set_primary_parent (m_primary_fcn_scope);
+
+              m_primary_fcn_scope.install_subfunction (fcn_nm, ov_fcn);
+            }
+        }
+
+      if (m_curr_fcn_depth == 0)
+        fcn_scope.update_nest ();
+
+      if (! m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0)
+        {
+          // We are either reading a script file or defining a function
+          // at the command line, so this definition creates a
+          // tree_function object that is placed in the parse tree.
+          // Otherwise, it is just inserted in the symbol table,
+          // either as a subfunction or nested function (see above),
+          // or as the primary function for the file, via
+          // m_primary_fcn (see also load_fcn_from_file,,
+          // parse_fcn_file, and
+          // fcn_info::fcn_info_rep::find_user_function).
+
+          if (m_lexer.m_buffer_function_text)
+            {
+              fcn->cache_function_text (m_lexer.m_function_text, fcn->time_parsed ());
+              m_lexer.m_buffer_function_text = false;
+            }
+
+          retval = new tree_function_def (fcn);
+        }
+    }
+
+  return retval;
+}
+
+tree_statement_list *
+base_parser::append_function_body (tree_statement_list *body, tree_statement_list *list)
+{
+  if (list)
+    {
+      for (const auto& elt : *list)
+        list_append (body, elt);
+
+      list->clear ();
+      delete (list);
+    }
+
+  return body;
+}
+
+tree_arguments_block *
+base_parser::make_arguments_block (token *arguments_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, token *end_tok)
+{
+  tree_arguments_block *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::arguments_end))
+    retval = new tree_arguments_block (*arguments_tok, attr_list, validation_list, *end_tok);
+  else
+    {
+      delete attr_list;
+      delete validation_list;
+    }
+
+  return retval;
+}
+
+tree_arg_validation *
+base_parser::make_arg_validation (tree_arg_size_spec *size_spec, tree_identifier *class_name, tree_arg_validation_fcns *validation_fcns, token *eq_tok, tree_expression *default_value)
+{
+  // FIXME: Validate arguments and convert to more specific types
+  // (std::string for arg_name and class_name, etc).
+
+  token tmp_eq_tok = eq_tok ? *eq_tok : token ();
+
+  return new tree_arg_validation (size_spec, class_name, validation_fcns, tmp_eq_tok, default_value);
+}
+
+tree_args_block_attribute_list *
+base_parser::make_args_attribute_list (tree_identifier *attribute_name)
+{
+  // FIXME: Validate argument and convert to more specific type
+  // (std::string for attribute_name).
+
+  return new tree_args_block_attribute_list (attribute_name);
+}
+
+tree_args_block_validation_list *
+base_parser::make_args_validation_list (tree_arg_validation *arg_validation)
+{
+  return new tree_args_block_validation_list (arg_validation);
+}
+
+tree_args_block_validation_list *
+base_parser::append_args_validation_list (tree_args_block_validation_list *list, tree_arg_validation *arg_validation)
+{
+  return list_append (list, arg_validation);
+}
+
+tree_arg_size_spec *
+base_parser::make_arg_size_spec (tree_argument_list *size_args)
+{
+  // FIXME: Validate argument.
+
+  return new tree_arg_size_spec (size_args);
+}
+
+tree_arg_validation_fcns *
+base_parser::make_arg_validation_fcns (tree_argument_list *fcn_args)
+{
+  // FIXME: Validate argument.
+
+  return new tree_arg_validation_fcns (fcn_args);
+}
+
+void
+base_parser::recover_from_parsing_function ()
+{
+  m_lexer.m_symtab_context.pop ();
+
+  if (m_lexer.m_reading_fcn_file && m_curr_fcn_depth == 0 && ! m_parsing_subfunctions)
+    m_parsing_subfunctions = true;
+
+  m_curr_fcn_depth--;
+  m_function_scopes.pop ();
+
+  m_lexer.m_defining_fcn--;
+  m_lexer.m_parsed_function_name.pop ();
+  m_lexer.m_looking_at_return_list = false;
+  m_lexer.m_looking_at_parameter_list = false;
+}
+
+// A CLASSDEF block defines a class that has a constructor and other
+// methods, but it is not an executable command.  Parsing the block
+// makes some changes in the symbol table (inserting the constructor
+// and methods, and adding to the list of known objects) and creates
+// a parse tree containing meta information about the class.
+
+tree_classdef *
+base_parser::make_classdef (token *cdef_tok, tree_classdef_attribute_list *a, tree_identifier *id, tree_classdef_superclass_list *sc, tree_classdef_body *body, token *end_tok)
+{
+  tree_classdef *retval = nullptr;
+
+  m_lexer.m_symtab_context.pop ();
+
+  std::string cls_name = id->name ();
+
+  std::string full_name = m_lexer.m_fcn_file_full_name;
+  std::string short_name = m_lexer.m_fcn_file_name;
+
+  std::size_t pos = short_name.find_last_of (sys::file_ops::dir_sep_chars ());
+
+  if (pos != std::string::npos)
+    short_name = short_name.substr (pos+1);
+
+  if (short_name != cls_name)
+    {
+      filepos f_pos = id->beg_pos ();
+
+      delete a;
+      delete id;
+      delete sc;
+      delete body;
+
+      bison_error ("invalid classdef definition, the class name must match the filename", f_pos);
+
+    }
+  else
+    {
+      if (end_token_ok (end_tok, token::classdef_end))
+        {
+          if (! body)
+            body = new tree_classdef_body ();
+
+          retval = new tree_classdef (m_lexer.m_symtab_context.curr_scope (), *cdef_tok, a, id, sc, body, *end_tok, m_curr_package_name, full_name);
+        }
+      else
+        {
+          delete a;
+          delete id;
+          delete sc;
+          delete body;
+
+          end_token_error (end_tok, token::switch_end);
+        }
+    }
+
+  return retval;
+}
+
+tree_classdef_properties_block *
+base_parser::make_classdef_properties_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, token *end_tok)
+{
+  tree_classdef_properties_block *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::properties_end))
+    {
+      if (plist)
+        {
+          // If the element at the end of the list doesn't have a doc
+          // string, see whether the first element of the comments
+          // attached to the end token is an end-of-line comment for
+          // us to use.
+
+          tree_classdef_property *last_elt = plist->back ();
+
+          if (last_elt && ! last_elt->have_doc_string ())
+            {
+              comment_list comments = end_tok->leading_comments ();
+
+              if (! comments.empty ())
+                {
+                  comment_elt elt = comments.front ();
+
+                  if (elt.is_end_of_line ())
+                    last_elt->doc_string (elt.text ());
+                }
+            }
+        }
+      else
+        plist = new tree_classdef_property_list ();
+
+      retval = new tree_classdef_properties_block (*tok, a, plist, *end_tok);
+    }
+  else
+    {
+      delete a;
+      delete plist;
+
+      end_token_error (end_tok, token::properties_end);
+    }
+
+  return retval;
+}
+
+tree_classdef_property_list *
+base_parser::make_classdef_property_list (tree_classdef_property *prop)
+{
+  return new tree_classdef_property_list (prop);
+}
+
+tree_classdef_property *
+base_parser::make_classdef_property (tree_identifier *id, tree_arg_validation *av)
+{
+  av->arg_name (id);
+
+  if (av->size_spec () || av->class_name () || av->validation_fcns ())
+    warning ("size, class, and validation function specifications are not yet supported for classdef properties; INCORRECT RESULTS ARE POSSIBLE!");
+
+  return new tree_classdef_property (av);
+}
+
+tree_classdef_methods_block *
+base_parser::make_classdef_methods_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, token *end_tok)
+{
+  tree_classdef_methods_block *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::methods_end))
+    {
+      if (! mlist)
+        mlist = new tree_classdef_method_list ();
+
+      retval = new tree_classdef_methods_block (*tok, a, mlist, *end_tok);
+    }
+  else
+    {
+      delete a;
+      delete mlist;
+
+      end_token_error (end_tok, token::methods_end);
+    }
+
+  return retval;
+}
+
+tree_classdef_events_block *
+base_parser::make_classdef_events_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, token *end_tok)
+{
+  tree_classdef_events_block *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::events_end))
+    {
+      if (! elist)
+        elist = new tree_classdef_event_list ();
+
+      retval = new tree_classdef_events_block (*tok, a, elist, *end_tok);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+
+      end_token_error (end_tok, token::events_end);
+    }
+
+  return retval;
+}
+
+tree_classdef_event_list *
+base_parser::make_classdef_event_list (tree_classdef_event *e)
+{
+  return new tree_classdef_event_list (e);
+}
+
+tree_classdef_event *
+base_parser::make_classdef_event (tree_identifier *id)
+{
+  return new tree_classdef_event (id);
+}
+
+tree_classdef_enum_block *
+base_parser::make_classdef_enum_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, token *end_tok)
+{
+  tree_classdef_enum_block *retval = nullptr;
+
+  if (end_token_ok (end_tok, token::enumeration_end))
+    {
+      if (! elist)
+        elist = new tree_classdef_enum_list ();
+
+      retval = new tree_classdef_enum_block (*tok, a, elist, *end_tok);
+    }
+  else
+    {
+      delete a;
+      delete elist;
+
+      end_token_error (end_tok, token::enumeration_end);
+    }
+
+  return retval;
+}
+
+tree_classdef_enum_list *
+base_parser::make_classdef_enum_list (tree_classdef_enum *e)
+{
+  return new tree_classdef_enum_list (e);
+}
+
+tree_classdef_enum *
+base_parser::make_classdef_enum (tree_identifier *id, token *open_paren, tree_expression *expr, token *close_paren)
+{
+  return new tree_classdef_enum (id, *open_paren, expr, *close_paren);
+}
+
+tree_classdef_property_list *
+base_parser::append_classdef_property (tree_classdef_property_list *list, tree_classdef_property *elt)
+{
+  return list_append (list, elt);
+}
+
+tree_classdef_event_list *
+base_parser::append_classdef_event (tree_classdef_event_list *list, tree_classdef_event *elt)
+{
+  return list_append (list, elt);
+}
+
+tree_classdef_enum_list *
+base_parser::append_classdef_enum (tree_classdef_enum_list *list, tree_classdef_enum *elt)
+{
+  return list_append (list, elt);
+}
+
+tree_classdef_superclass_list *
+base_parser::make_classdef_superclass_list (token *lt_tok, tree_classdef_superclass *sc)
+{
+  sc->set_separator (*lt_tok);
+
+  return new tree_classdef_superclass_list (sc);
+}
+
+tree_classdef_superclass *
+base_parser::make_classdef_superclass (token *fqident)
+{
+  return new tree_classdef_superclass (*fqident);
+}
+
+tree_classdef_superclass_list *
+base_parser::append_classdef_superclass (tree_classdef_superclass_list *list, token *and_tok, tree_classdef_superclass *elt)
+{
+  elt->set_separator (*and_tok);
+
+  return list_append (list, elt);
+}
+
+tree_classdef_attribute_list *
+base_parser::make_classdef_attribute_list (tree_classdef_attribute *attr)
+{
+  return new tree_classdef_attribute_list (attr);
+}
+
+tree_classdef_attribute *
+base_parser::make_classdef_attribute (tree_identifier *id)
+{
+  return make_classdef_attribute (id, nullptr, nullptr);
+}
+
+tree_classdef_attribute *
+base_parser::make_classdef_attribute (tree_identifier *id, token *eq_tok, tree_expression *expr)
+{
+  return (expr ? new tree_classdef_attribute (id, *eq_tok, expr) : new tree_classdef_attribute (id));
+}
+
+tree_classdef_attribute *
+base_parser::make_not_classdef_attribute (token *not_tok, tree_identifier *id)
+{
+  return new tree_classdef_attribute (*not_tok, id, false);
+}
+
+tree_classdef_attribute_list *
+base_parser::append_classdef_attribute (tree_classdef_attribute_list *list, token *sep_tok, tree_classdef_attribute *elt)
+{
+  return list_append (list, *sep_tok, elt);
+}
+
+tree_classdef_body *
+base_parser::make_classdef_body (tree_classdef_properties_block *pb)
+{
+  return new tree_classdef_body (pb);
+}
+
+tree_classdef_body *
+base_parser::make_classdef_body (tree_classdef_methods_block *mb)
+{
+  return new tree_classdef_body (mb);
+}
+
+tree_classdef_body *
+base_parser::make_classdef_body (tree_classdef_events_block *evb)
+{
+  return new tree_classdef_body (evb);
+}
+
+tree_classdef_body *
+base_parser::make_classdef_body  (tree_classdef_enum_block *enb)
+{
+  return new tree_classdef_body (enb);
+}
+
+tree_classdef_body *
+base_parser::append_classdef_properties_block (tree_classdef_body *body, tree_classdef_properties_block *block)
+{
+  return body->append (block);
+}
+
+tree_classdef_body *
+base_parser::append_classdef_methods_block (tree_classdef_body *body, tree_classdef_methods_block *block)
+{
+  return body->append (block);
+}
+
+tree_classdef_body *
+base_parser::append_classdef_events_block (tree_classdef_body *body, tree_classdef_events_block *block)
+{
+  return body->append (block);
+}
+
+tree_classdef_body *
+base_parser::append_classdef_enum_block (tree_classdef_body *body, tree_classdef_enum_block *block)
+{
+  return body->append (block);
+}
+
+octave_user_function*
+base_parser::start_classdef_external_method (tree_identifier *id, tree_parameter_list *pl)
+{
+  octave_user_function* retval = nullptr;
+
+  // External methods are only allowed within @-folders. In this case,
+  // m_curr_class_name will be non-empty.
+
+  if (! m_curr_class_name.empty ())
+    {
+      std::string mname = id->name ();
+
+      // Methods that cannot be declared outside the classdef file:
+      // - methods with '.' character (e.g. property accessors)
+      // - class constructor
+      // - 'delete'
+
+      if (mname.find_first_of (".") == std::string::npos && mname != "delete" && mname != m_curr_class_name)
+        {
+          // Create a dummy function that is used until the real method
+          // is loaded.
+
+          retval = new octave_user_function (symbol_scope::anonymous (), id, pl);
+
+          retval->stash_function_name (mname);
+        }
+      else
+        bison_error ("invalid external method declaration, an external method cannot be the class constructor, 'delete' or have a dot (.) character in its name");
+    }
+  else
+    bison_error ("external methods are only allowed in @-folders");
+
+  return retval;
+}
+
+tree_function_def *
+base_parser::finish_classdef_external_method (octave_user_function *fcn, tree_parameter_list *ret_list, token *eq_tok)
+{
+  if (! ret_list)
+    ret_list = new tree_parameter_list (tree_parameter_list::out);
+
+  fcn->define_ret_list (ret_list);
+
+  if (eq_tok)
+    fcn->set_eq_tok (*eq_tok);
+
+  return new tree_function_def (fcn);
+}
+
+tree_classdef_method_list *
+base_parser::make_classdef_method_list (tree_function_def *fcn_def)
+{
+  octave_value fcn;
+
+  if (fcn_def)
+    fcn = fcn_def->function ();
+
+  delete fcn_def;
+
+  return new tree_classdef_method_list (fcn);
+}
+
+tree_classdef_method_list *
+base_parser::append_classdef_method (tree_classdef_method_list *list, tree_function_def *fcn_def)
+{
+  octave_value fcn;
+
+  if (fcn_def)
+    {
+      fcn = fcn_def->function ();
+
+      delete fcn_def;
+    }
+
+  return list_append (list, fcn);
+}
+
+bool
+base_parser::finish_classdef_file (tree_classdef *cls, tree_statement_list *local_fcns, token *eof_tok)
+{
+  parse_tree_validator validator;
+
+  cls->accept (validator);
+
+  if (local_fcns)
+    {
+      for (tree_statement *elt : *local_fcns)
+        {
+          tree_command *cmd = elt->command ();
+
+          tree_function_def *fcn_def = dynamic_cast<tree_function_def *> (cmd);
+
+          fcn_def->accept (validator);
+        }
+    }
+
+  if (! validator.ok ())
+    {
+      delete cls;
+      delete local_fcns;
+
+      bison_error (validator.error_list ());
+
+      return false;
+    }
+
+  // Require all validations to succeed before installing any local
+  // functions or defining the classdef object for later use.
+
+  if (local_fcns)
+    {
+      interpreter& interp = m_lexer.m_interpreter;
+
+      symbol_table& symtab = interp.get_symbol_table ();
+
+      for (tree_statement *elt : *local_fcns)
+        {
+          tree_command *cmd = elt->command ();
+
+          tree_function_def *fcn_def = dynamic_cast<tree_function_def *> (cmd);
+
+          octave_value ov_fcn = fcn_def->function ();
+          octave_user_function *fcn = ov_fcn.user_function_value ();
+
+          std::string nm = fcn->name ();
+          std::string file = fcn->fcn_file_name ();
+
+          fcn->attach_trailing_comments (eof_tok->leading_comments ());
+
+          symtab.install_local_function (nm, ov_fcn, file);
+        }
+
+      delete local_fcns;
+    }
+
+  // FIXME: Is it possible for the following condition to be false?
+  if (m_lexer.m_reading_classdef_file)
+    m_classdef_object = std::shared_ptr<tree_classdef> (cls);
+
+  return true;
+}
+
+// Make a word list command.
+tree_index_expression *
+base_parser::make_word_list_command (tree_expression *expr, tree_argument_list *args)
+{
+  tree_index_expression *retval = make_index_expression (expr, nullptr, args, nullptr, '(');
+
+  if (retval)
+    retval->mark_word_list_cmd ();
+
+  return retval;
+}
+
+// Make an index expression.
+
+tree_index_expression *
+base_parser::make_index_expression (tree_expression *expr, token *open_delim, tree_argument_list *args, token *close_delim, char type)
+{
+  tree_index_expression *retval = nullptr;
+
+  if (! args)
+    args = new tree_argument_list ();
+
+  if (args->has_magic_tilde ())
+    {
+      delete expr;
+      delete args;
+
+      bison_error ("invalid use of empty argument (~) in index expression");
+    }
+  else
+    {
+      if (! expr->is_postfix_indexed ())
+        expr->set_postfix_index (type);
+
+      token tmp_open_delim = open_delim ? *open_delim : token ();
+      token tmp_close_delim = close_delim ? *close_delim : token ();
+
+      if (expr->is_index_expression ())
+        {
+          retval = dynamic_cast<tree_index_expression *> (expr);
+
+          retval->append (tmp_open_delim, args, tmp_close_delim, type);
+        }
+      else
+        retval = new tree_index_expression (expr, tmp_open_delim, args, tmp_close_delim, type);
+    }
+
+  return retval;
+}
+
+// Make an indirect reference expression.
+
+tree_index_expression *
+base_parser::make_indirect_ref (tree_expression *expr, token *dot_tok, token *struct_elt_tok)
+{
+  tree_index_expression *retval = nullptr;
+
+  if (! expr->is_postfix_indexed ())
+    expr->set_postfix_index ('.');
+
+  if (expr->is_index_expression ())
+    {
+      retval = dynamic_cast<tree_index_expression *> (expr);
+
+      retval->append (*dot_tok, *struct_elt_tok);
+    }
+  else
+    retval = new tree_index_expression (expr, *dot_tok, *struct_elt_tok);
+
+  m_lexer.m_looking_at_indirect_ref = false;
+
+  return retval;
+}
+
+// Make an indirect reference expression with dynamic field name.
+
+tree_index_expression *
+base_parser::make_indirect_ref (tree_expression *expr, token *dot_tok, token *open_paren, tree_expression *elt, token *close_paren)
+{
+  tree_index_expression *retval = nullptr;
+
+  if (! expr->is_postfix_indexed ())
+    expr->set_postfix_index ('.');
+
+  if (expr->is_index_expression ())
+    {
+      retval = dynamic_cast<tree_index_expression *> (expr);
+
+      retval->append (*dot_tok, *open_paren, elt, *close_paren);
+    }
+  else
+    retval = new tree_index_expression (expr, *dot_tok, *open_paren, elt, *close_paren);
+
+  m_lexer.m_looking_at_indirect_ref = false;
+
+  return retval;
+}
+
+// Make a declaration command.
+
+tree_decl_command *
+base_parser::make_decl_command (token *tok, tree_decl_init_list *lst)
+{
+  tree_decl_command *retval = nullptr;
+
+  if (lst)
+    m_lexer.mark_as_variables (lst->variable_names ());
+
+  int tok_id = tok->token_id ();
+
+  switch (tok->token_id ())
+    {
+    case GLOBAL:
       {
-
-        std::string mname = id->name ();
-
-        // Methods that cannot be declared outside the classdef file:
-        // - methods with '.' character (e.g. property accessors)
-        // - class constructor
-        // - 'delete'
-
-        if (mname.find_first_of (".") == std::string::npos
-            && mname != "delete"
-            && mname != m_curr_class_name)
-          {
-            // Create a dummy function that is used until the real method
-            // is loaded.
-
-            retval = new octave_user_function (symbol_scope::anonymous (), pl);
-
-            retval->stash_function_name (mname);
-
-            int l = id->line ();
-            int c = id->column ();
-
-            retval->stash_fcn_location (l, c);
-          }
-        else
-          bison_error ("invalid external method declaration, an external "
-                       "method cannot be the class constructor, 'delete' "
-                       "or have a dot (.) character in its name");
-      }
-    else
-      bison_error ("external methods are only allowed in @-folders");
-
-    if (! retval)
-      delete id;
-
-    return retval;
-  }
-
-  tree_function_def *
-  base_parser::finish_classdef_external_method (octave_user_function *fcn,
-                                                tree_parameter_list *ret_list,
-                                                comment_list *cl)
-  {
-    if (! ret_list)
-      ret_list = new tree_parameter_list (tree_parameter_list::out);
-
-    fcn->define_ret_list (ret_list);
-
-    if (cl)
-      fcn->stash_leading_comment (cl);
-
-    int l = fcn->beginning_line ();
-    int c = fcn->beginning_column ();
-
-    return new tree_function_def (fcn, l, c);
-  }
-
-  tree_classdef_methods_list *
-  base_parser::make_classdef_methods_list (tree_function_def *fcn_def)
-  {
-    octave_value fcn;
-
-    if (fcn_def)
-      fcn = fcn_def->function ();
-
-    delete fcn_def;
-
-    return new tree_classdef_methods_list (fcn);
-  }
-
-  tree_classdef_methods_list *
-  base_parser::append_classdef_method (tree_classdef_methods_list *list,
-                                       tree_function_def *fcn_def)
-  {
-    octave_value fcn;
-
-    if (fcn_def)
-      {
-        fcn = fcn_def->function ();
-
-        delete fcn_def;
-      }
-
-    return list_append (list, fcn);
-  }
-
-  bool
-  base_parser::finish_classdef_file (tree_classdef *cls,
-                                     tree_statement_list *local_fcns)
-  {
-    parse_tree_validator validator;
-
-    cls->accept (validator);
-
-    if (local_fcns)
-      {
-        for (tree_statement *elt : *local_fcns)
-          {
-            tree_command *cmd = elt->command ();
-
-            tree_function_def *fcn_def
-              = dynamic_cast<tree_function_def *> (cmd);
-
-            fcn_def->accept (validator);
-          }
-      }
-
-    if (! validator.ok ())
-      {
-        delete cls;
-        delete local_fcns;
-
-        bison_error (validator.error_list ());
-
-        return false;
-      }
-
-    // Require all validations to succeed before installing any local
-    // functions or defining the classdef object for later use.
-
-    if (local_fcns)
-      {
-        interpreter& interp = m_lexer.m_interpreter;
-
-        symbol_table& symtab = interp.get_symbol_table ();
-
-        for (tree_statement *elt : *local_fcns)
-          {
-            tree_command *cmd = elt->command ();
-
-            tree_function_def *fcn_def
-              = dynamic_cast<tree_function_def *> (cmd);
-
-            octave_value ov_fcn = fcn_def->function ();
-            octave_user_function *fcn = ov_fcn.user_function_value ();
-
-            std::string nm = fcn->name ();
-            std::string file = fcn->fcn_file_name ();
-
-            symtab.install_local_function (nm, ov_fcn, file);
-          }
-
-        delete local_fcns;
-      }
-
-    // FIXME: Is it possible for the following condition to be false?
-    if (m_lexer.m_reading_classdef_file)
-      m_classdef_object = std::shared_ptr<tree_classdef> (cls);
-
-    return true;
-  }
-
-  // Make an index expression.
-
-  tree_index_expression *
-  base_parser::make_index_expression (tree_expression *expr,
-                                      tree_argument_list *args,
-                                      char type)
-  {
-    tree_index_expression *retval = nullptr;
-
-    if (args && args->has_magic_tilde ())
-      {
-        delete expr;
-        delete args;
-
-        bison_error ("invalid use of empty argument (~) in index expression");
-      }
-    else
-      {
-        int l = expr->line ();
-        int c = expr->column ();
-
-        if (! expr->is_postfix_indexed ())
-          expr->set_postfix_index (type);
-
-        if (expr->is_index_expression ())
-          {
-            tree_index_expression *tmp
-              = dynamic_cast<tree_index_expression *> (expr);
-
-            retval = tmp->append (args, type);
-          }
-        else
-          retval = new tree_index_expression (expr, args, l, c, type);
-      }
-
-    return retval;
-  }
-
-  // Make an indirect reference expression.
-
-  tree_index_expression *
-  base_parser::make_indirect_ref (tree_expression *expr,
-                                  const std::string& elt)
-  {
-    tree_index_expression *retval = nullptr;
-
-    int l = expr->line ();
-    int c = expr->column ();
-
-    if (! expr->is_postfix_indexed ())
-      expr->set_postfix_index ('.');
-
-    if (expr->is_index_expression ())
-      {
-        tree_index_expression *tmp
-          = dynamic_cast<tree_index_expression *> (expr);
-
-        retval = tmp->append (elt);
-      }
-    else
-      retval = new tree_index_expression (expr, elt, l, c);
-
-    m_lexer.m_looking_at_indirect_ref = false;
-
-    return retval;
-  }
-
-  // Make an indirect reference expression with dynamic field name.
-
-  tree_index_expression *
-  base_parser::make_indirect_ref (tree_expression *expr,
-                                  tree_expression *elt)
-  {
-    tree_index_expression *retval = nullptr;
-
-    int l = expr->line ();
-    int c = expr->column ();
-
-    if (! expr->is_postfix_indexed ())
-      expr->set_postfix_index ('.');
-
-    if (expr->is_index_expression ())
-      {
-        tree_index_expression *tmp
-          = dynamic_cast<tree_index_expression *> (expr);
-
-        retval = list_append (tmp, elt);
-      }
-    else
-      retval = new tree_index_expression (expr, elt, l, c);
-
-    m_lexer.m_looking_at_indirect_ref = false;
-
-    return retval;
-  }
-
-  // Make a declaration command.
-
-  tree_decl_command *
-  base_parser::make_decl_command (int tok, token *tok_val,
-                                  tree_decl_init_list *lst)
-  {
-    tree_decl_command *retval = nullptr;
-
-    int l = tok_val->line ();
-    int c = tok_val->column ();
-
-    if (lst)
-      m_lexer.mark_as_variables (lst->variable_names ());
-
-    switch (tok)
-      {
-      case GLOBAL:
-        {
-          retval = new tree_decl_command ("global", lst, l, c);
-          retval->mark_global ();
-        }
-        break;
-
-      case PERSISTENT:
-        if (m_curr_fcn_depth >= 0)
-          {
-            retval = new tree_decl_command ("persistent", lst, l, c);
-            retval->mark_persistent ();
-          }
-        else
-          {
-            if (m_lexer.m_reading_script_file)
-              warning ("ignoring persistent declaration near line %d of file '%s'",
-                       l, m_lexer.m_fcn_file_full_name.c_str ());
-            else
-              warning ("ignoring persistent declaration near line %d", l);
-          }
-        break;
-
-      default:
-        panic_impossible ();
-        break;
-      }
-
-    return retval;
-  }
-
-  tree_decl_init_list *
-  base_parser::make_decl_init_list (tree_decl_elt *elt)
-  {
-    return new tree_decl_init_list (elt);
-  }
-
-  tree_decl_init_list *
-  base_parser::append_decl_init_list (tree_decl_init_list *list,
-                                      tree_decl_elt *elt)
-  {
-    return list_append (list, elt);
-  }
-
-  tree_decl_elt *
-  base_parser::make_decl_elt (tree_identifier *id, token */*eq_op*/,
-                              tree_expression *expr)
-  {
-    return expr ? new tree_decl_elt (id, expr) : new tree_decl_elt (id);
-  }
-
-  bool
-  base_parser::validate_param_list (tree_parameter_list *lst,
-                                    tree_parameter_list::in_or_out type)
-  {
-    std::set<std::string> dict;
-
-    for (tree_decl_elt *elt : *lst)
-      {
-        tree_identifier *id = elt->ident ();
-
-        if (id)
-          {
-            std::string name = id->name ();
-
-            if (id->is_black_hole ())
-              {
-                if (type != tree_parameter_list::in)
-                  {
-                    bison_error ("invalid use of ~ in output list");
-                    return false;
-                  }
-              }
-            else if (iskeyword (name))
-              {
-                bison_error ("invalid use of keyword '" + name
-                             + "' in parameter list");
-                return false;
-              }
-            else if (dict.find (name) != dict.end ())
-              {
-                bison_error ("'" + name
-                             + "' appears more than once in parameter list");
-                return false;
-              }
-            else
-              dict.insert (name);
-          }
+        retval = new tree_decl_command ("global", *tok, lst);
+        retval->mark_global ();
       }
-
-    std::string va_type = (type == tree_parameter_list::in
-                           ? "varargin" : "varargout");
-
-    std::size_t len = lst->length ();
-
-    if (len > 0)
-      {
-        tree_decl_elt *elt = lst->back ();
-
-        tree_identifier *id = elt->ident ();
-
-        if (id && id->name () == va_type)
-          {
-            if (len == 1)
-              lst->mark_varargs_only ();
-            else
-              lst->mark_varargs ();
-
-            tree_parameter_list::iterator p = lst->end ();
-            --p;
-            delete *p;
-            lst->erase (p);
-          }
-      }
-
-    return true;
-  }
-
-  bool
-  base_parser::validate_array_list (tree_expression *e)
-  {
-    bool retval = true;
-
-    tree_array_list *al = dynamic_cast<tree_array_list *> (e);
-
-    for (tree_argument_list* row : *al)
-      {
-        if (row && row->has_magic_tilde ())
-          {
-            retval = false;
-
-            if (e->is_matrix ())
-              bison_error ("invalid use of tilde (~) in matrix expression");
-            else
-              bison_error ("invalid use of tilde (~) in cell expression");
-
-            break;
-          }
-      }
-
-    return retval;
-  }
-
-  tree_argument_list *
-  base_parser::validate_matrix_for_assignment (tree_expression *e)
-  {
-    tree_argument_list *retval = nullptr;
-
-    if (e->is_constant ())
-      {
-        interpreter& interp = m_lexer.m_interpreter;
-
-        tree_evaluator& tw = interp.get_evaluator ();
-
-        octave_value ov = e->evaluate (tw);
-
-        delete e;
-
-        if (ov.isempty ())
-          bison_error ("invalid empty left hand side of assignment");
-        else
-          bison_error ("invalid constant left hand side of assignment");
-      }
-    else
-      {
-        bool is_simple_assign = true;
-
-        tree_argument_list *tmp = nullptr;
-
-        if (e->is_matrix ())
-          {
-            tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
-
-            if (mat && mat->size () == 1)
-              {
-                tmp = mat->front ();
-                mat->pop_front ();
-                delete e;
-                is_simple_assign = false;
-              }
-          }
-        else
-          tmp = new tree_argument_list (e);
-
-        if (tmp && tmp->is_valid_lvalue_list ())
-          {
-            m_lexer.mark_as_variables (tmp->variable_names ());
-            retval = tmp;
-          }
-        else
-          {
-            delete tmp;
-
-            bison_error ("invalid left hand side of assignment");
-          }
-
-        if (retval && is_simple_assign)
-          retval->mark_as_simple_assign_lhs ();
-      }
-
-    return retval;
-  }
-
-  // Finish building an array_list.
-
-  tree_expression *
-  base_parser::finish_array_list (tree_array_list *array_list,
-                                  token */*open_delim*/, token *close_delim)
-  {
-    tree_expression *retval = array_list;
-
-    array_list->set_location (close_delim->line (), close_delim->column ());
-
-    if (array_list->all_elements_are_constant ())
-      {
-        interpreter& interp = m_lexer.m_interpreter;
-
-        try
-          {
-            // If the evaluation generates a warning message, restore
-            // the previous value of last_warning_message and skip the
-            // conversion to a constant value.
-
-            error_system& es = interp.get_error_system ();
-
-            unwind_action restore_last_warning_message
-              (&error_system::set_last_warning_message, &es,
-               es.last_warning_message (""));
-
-            unwind_action restore_discard_warning_messages
-              (&error_system::set_discard_warning_messages, &es,
-               es.discard_warning_messages (true));
-
-            tree_evaluator& tw = interp.get_evaluator ();
-
-            octave_value tmp = array_list->evaluate (tw);
-
-            std::string msg = es.last_warning_message ();
-
-            if (msg.empty ())
-              {
-                tree_constant *tc_retval
-                  = new tree_constant (tmp, close_delim->line (),
-                                       close_delim->column ());
-
-                std::ostringstream buf;
-
-                tree_print_code tpc (buf);
-
-                array_list->accept (tpc);
-
-                tc_retval->stash_original_text (buf.str ());
-
-                delete array_list;
-
-                retval = tc_retval;
-              }
-          }
-        catch (const execution_exception&)
-          {
-            interp.recover_from_exception ();
-          }
-      }
-
-    return retval;
-  }
-
-  // Finish building a matrix list.
-
-  tree_expression *
-  base_parser::finish_matrix (tree_matrix *m, token *open_delim,
-                              token *close_delim)
-  {
-    return (m
-            ? finish_array_list (m, open_delim, close_delim)
-            : new tree_constant (octave_null_matrix::instance,
-                                 close_delim->line (), close_delim->column ()));
-  }
-
-  tree_matrix *
-  base_parser::make_matrix (tree_argument_list *row)
-  {
-    return row ? new tree_matrix (row) : nullptr;
-  }
-
-  tree_matrix *
-  base_parser::append_matrix_row (tree_matrix *matrix, tree_argument_list *row)
-  {
-    if (! matrix)
-      return make_matrix (row);
-
-    return row ? list_append (matrix, row) : matrix;
-  }
-
-  // Finish building a cell list.
-
-  tree_expression *
-  base_parser::finish_cell (tree_cell *c, token *open_delim,
-                            token *close_delim)
-  {
-    return (c
-            ? finish_array_list (c, open_delim, close_delim)
-            : new tree_constant (octave_value (Cell ()),
-                                 close_delim->line (), close_delim->column ()));
-  }
-
-  tree_cell *
-  base_parser::make_cell (tree_argument_list *row)
-  {
-    return row ? new tree_cell (row) : nullptr;
-  }
-
-  tree_cell *
-  base_parser::append_cell_row (tree_cell *cell, tree_argument_list *row)
-  {
-    if (! cell)
-      return make_cell (row);
-
-    return row ? list_append (cell, row) : cell;
-  }
-
-  tree_identifier *
-  base_parser::make_identifier (token *ident)
-  {
-    // Find the token in the symbol table.
-    symbol_scope scope = m_lexer.m_symtab_context.curr_scope ();
-
-    std::string nm = ident->text ();
-
-    symbol_record sr = (scope ? scope.insert (nm) : symbol_record (nm));
-
-
-    int l = ident->line ();
-    int c = ident->column ();
-
-    return new tree_identifier (sr, l, c);
-  }
-
-  tree_superclass_ref *
-  base_parser::make_superclass_ref (token *superclassref)
-  {
-    std::string meth = superclassref->superclass_method_name ();
-    std::string cls = superclassref->superclass_class_name ();
-
-    int l = superclassref->line ();
-    int c = superclassref->column ();
-
-    return new tree_superclass_ref (meth, cls, l, c);
-  }
-
-  tree_metaclass_query *
-  base_parser::make_metaclass_query (token *metaquery)
-  {
-    std::string cls = metaquery->text ();
-
-    int l = metaquery->line ();
-    int c = metaquery->column ();
-
-    return new tree_metaclass_query (cls, l, c);
-  }
-
-  tree_statement_list *
-  base_parser::set_stmt_print_flag (tree_statement_list *list,
-                                    char sep, bool warn_missing_semi)
-  {
-    tree_statement *tmp = list->back ();
-
-    switch (sep)
-      {
-      case ';':
-        tmp->set_print_flag (false);
-        break;
-
-      case 0:
-      case ',':
-      case '\n':
-        tmp->set_print_flag (true);
-        if (warn_missing_semi)
-          maybe_warn_missing_semi (list);
-        break;
-
-      default:
-        warning ("unrecognized separator type!");
-        break;
-      }
-
-    // Even if a statement is null, we add it to the list then remove it
-    // here so that the print flag is applied to the correct statement.
-
-    if (tmp->is_null_statement ())
-      {
-        list->pop_back ();
-        delete tmp;
-      }
-
-    return list;
-  }
-
-  // Finish building a statement.
-  template <typename T>
-  tree_statement *
-  base_parser::make_statement (T *arg)
-  {
-    comment_list *comment = m_lexer.get_comment ();
-
-    return new tree_statement (arg, comment);
-  }
-
-  tree_statement_list *
-  base_parser::make_statement_list (tree_statement *stmt)
-  {
-    return new tree_statement_list (stmt);
-  }
-
-  tree_statement_list *
-  base_parser::append_statement_list (tree_statement_list *list,
-                                      char sep, tree_statement *stmt,
-                                      bool warn_missing_semi)
-  {
-    set_stmt_print_flag (list, sep, warn_missing_semi);
-
-    return list_append (list, stmt);
-  }
-
-  tree_argument_list *
-  base_parser::make_argument_list (tree_expression *expr)
-  {
-    return new tree_argument_list (expr);
-  }
-
-  tree_argument_list *
-  base_parser::append_argument_list (tree_argument_list *list,
-                                     tree_expression *expr)
-  {
-    return list_append (list, expr);
-  }
-
-  tree_parameter_list *
-  base_parser::make_parameter_list (tree_parameter_list::in_or_out io)
-  {
-    return new tree_parameter_list (io);
-  }
-
-  tree_parameter_list *
-  base_parser::make_parameter_list (tree_parameter_list::in_or_out io,
-                                    tree_decl_elt *t)
-  {
-    return new tree_parameter_list (io, t);
-  }
-
-  tree_parameter_list *
-  base_parser::make_parameter_list (tree_parameter_list::in_or_out io,
-                                    tree_identifier *id)
-  {
-    return new tree_parameter_list (io, id);
-  }
-
-  tree_parameter_list *
-  base_parser::append_parameter_list (tree_parameter_list *list,
-                                      tree_decl_elt *t)
-  {
-    return list_append (list, t);
-  }
-
-  tree_parameter_list *
-  base_parser::append_parameter_list (tree_parameter_list *list,
-                                      tree_identifier *id)
-  {
-    return list_append (list, new tree_decl_elt (id));
-  }
-
-  void
-  base_parser::disallow_command_syntax ()
-  {
-    m_lexer.m_allow_command_syntax = false;
-  }
-
-  // FIXME: this function partially duplicates do_dbtype in debug.cc.
-  static std::string
-  get_file_line (const std::string& name, int line)
-  {
-    // NAME should be an absolute file name and the file should exist.
-
-    std::ifstream fs = sys::ifstream (name.c_str (), std::ios::in);
-
-    std::string text;
-
-    if (fs)
-      {
-        int i = 1;
-
-        do
-          {
-            if (! std::getline (fs, text))
-              {
-                text = "";
-                break;
-              }
-          }
-        while (i++ < line);
-      }
-
-    return text;
-  }
-
-  void
-  base_parser::bison_error (const std::string& str)
-  {
-    bison_error (str, m_lexer.m_filepos);
-  }
-
-  void
-  base_parser::bison_error (const std::string& str, const filepos& pos)
-  {
-    bison_error (str, pos.line (), pos.column ());
-  }
-
-  void
-  base_parser::bison_error (const std::string& str, int err_line, int err_col)
-  {
-    std::ostringstream output_buf;
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
-        || m_lexer.m_reading_classdef_file)
-      output_buf << "parse error near line " << err_line
-                 << " of file " << m_lexer.m_fcn_file_full_name;
-    else
-      output_buf << "parse error:";
-
-    if (str != "parse error")
-      output_buf << "\n\n  " << str;
-
-    output_buf << "\n\n";
-
-    std::string curr_line;
-
-    if (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file
-        || m_lexer.m_reading_classdef_file)
-      curr_line = get_file_line (m_lexer.m_fcn_file_full_name, err_line);
-    else
-      curr_line = m_lexer.m_current_input_line;
-
-    // Adjust the error column for display because it is 1-based in the
-    // lexer for easier reporting.
-    err_col--;
-
-    if (! curr_line.empty ())
-      {
-        // FIXME: we could do better if we just cached lines from the
-        // input file in a list.  See also functions for managing input
-        // buffers in lex.ll.
-
-        std::size_t len = curr_line.length ();
-
-        if (curr_line[len-1] == '\n')
-          curr_line.resize (len-1);
-
-        // Print the line, maybe with a pointer near the error token.
-
-        output_buf << ">>> " << curr_line << "\n";
-
-        if (err_col == 0)
-          err_col = len;
-
-        for (int i = 0; i < err_col + 3; i++)
-          output_buf << " ";
-
-        output_buf << "^";
-      }
-
-    output_buf << "\n";
-
-    m_parse_error_msg = output_buf.str ();
-  }
-
-  void
-  base_parser::bison_error (const parse_exception& pe)
-  {
-    bison_error (pe.message (), pe.line (), pe.column ());
-  }
-
-  void
-  base_parser::bison_error (const std::list<parse_exception>& pe_list)
-  {
-    // For now, we just report the first error found.  Reporting all
-    // errors will require a bit more refactoring.
-
-    parse_exception pe = pe_list.front ();
-
-    bison_error (pe.message (), pe.line (), pe.column ());
-  }
-
-  int
-  parser::run ()
-  {
-    int status = -1;
-
-    yypstate *pstate = static_cast<yypstate *> (m_parser_state);
-
-    try
-      {
-        status = octave_pull_parse (pstate, *this);
-      }
-    catch (const execution_exception&)
-      {
-        // FIXME: In previous versions, we emitted a parse error here
-        // but that is not always correct because the error could have
-        // happened inside a GUI callback functions executing in the
-        // readline event_hook loop.  Maybe we need a separate exception
-        // class for parse errors?
-
-        throw;
-      }
-    catch (const exit_exception&)
-      {
-        throw;
-      }
-    catch (const interrupt_exception&)
-      {
-        throw;
-      }
-    catch (...)
-      {
-        std::string file = m_lexer.m_fcn_file_full_name;
-
-        if (file.empty ())
-          error ("unexpected exception while parsing input");
-        else
-          error ("unexpected exception while parsing %s", file.c_str ());
-      }
-
-    if (status != 0)
-      parse_error ("%s", m_parse_error_msg.c_str ());
-
-    return status;
-  }
-
-  // Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
-  // finish the parse.
-
-  int
-  push_parser::run (const std::string& input, bool eof)
-  {
-    int status = -1;
-
-    dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);
-
-    do
-      {
-        YYSTYPE lval;
-
-        int token = octave_lex (&lval, m_lexer.m_scanner);
-
-        if (token < 0)
-          {
-            // TOKEN == -2 means that the lexer recognized a comment
-            // and we should be at the end of the buffer but not the
-            // end of the file so we should return 0 to indicate
-            // "complete input" instead of -1 to request more input.
-
-            status = (token == -2 ? 0 : -1);
-
-            if (! eof && m_lexer.at_end_of_buffer ())
-              return status;
-
-            break;
-          }
-
-        yypstate *pstate = static_cast<yypstate *> (m_parser_state);
-
-        try
-          {
-            status = octave_push_parse (pstate, token, &lval, *this);
-          }
-        catch (execution_exception& e)
-          {
-            std::string file = m_lexer.m_fcn_file_full_name;
-
-            if (file.empty ())
-              error (e, "parse error");
-            else
-              error (e, "parse error in %s", file.c_str ());
-          }
-        catch (const exit_exception&)
-          {
-            throw;
-          }
-        catch (interrupt_exception &)
-          {
-            throw;
-          }
-        catch (...)
-          {
-            std::string file = m_lexer.m_fcn_file_full_name;
-
-            if (file.empty ())
-              error ("unexpected exception while parsing input");
-            else
-              error ("unexpected exception while parsing %s", file.c_str ());
-          }
-      }
-    while (status == YYPUSH_MORE || ! m_lexer.at_end_of_buffer ());
-
-    if (status != 0)
-      parse_error ("%s", m_parse_error_msg.c_str ());
-
-    return status;
-  }
-
-  int
-  push_parser::run ()
-  {
-    if (! m_reader)
-      error ("push_parser::run requires valid input_reader");
-
-    int exit_status = 0;
-
-    std::string prompt
-      = command_editor::decode_prompt_string (m_interpreter.PS1 ());
-
-    do
-      {
-        // Reset status each time through the read loop so that
-        // it won't be set to -1 and cause us to exit the outer
-        // loop early if there is an exception while reading
-        // input or parsing.
-
-        exit_status = 0;
-
-        bool eof = false;
-        std::string input_line = m_reader->get_input (prompt, eof);
-
-        if (eof)
-          {
-            exit_status = EOF;
-            break;
-          }
-
-        exit_status = run (input_line, false);
-
-        prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());
-      }
-    while (exit_status < 0);
-
-    return exit_status;
-  }
-
-  octave_value
-  parse_fcn_file (interpreter& interp, const std::string& full_file,
-                  const std::string& file, const std::string& dir_name,
-                  const std::string& dispatch_type,
-                  const std::string& package_name, bool require_file,
-                  bool force_script, bool autoload, bool relative_lookup)
-  {
-    octave_value retval;
-
-    FILE *ffile = nullptr;
-
-    if (! full_file.empty ())
+      break;
+
+    case PERSISTENT:
+      if (m_curr_fcn_depth >= 0)
+        {
+          retval = new tree_decl_command ("persistent", *tok, lst);
+          retval->mark_persistent ();
+        }
+      else
+        {
+          filepos pos = tok->beg_pos ();
+          int line = pos.line ();
+
+          if (m_lexer.m_reading_script_file)
+            warning ("ignoring persistent declaration near line %d of file '%s'", line, m_lexer.m_fcn_file_full_name.c_str ());
+          else
+            warning ("ignoring persistent declaration near line %d", line);
+        }
+      break;
+
+    default:
+      unexpected_token (tok_id, "base_parser::make_decl_command");
+      break;
+    }
+
+  return retval;
+}
+
+tree_decl_init_list *
+base_parser::make_decl_init_list (tree_decl_elt *elt)
+{
+  return new tree_decl_init_list (elt);
+}
+
+tree_decl_init_list *
+base_parser::append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt)
+{
+  return list_append (list, elt);
+}
+
+tree_decl_elt *
+base_parser::make_decl_elt (tree_identifier *id, token */*eq_op*/, tree_expression *expr)
+{
+  // FIXME XXX! need to capture EQ_OP here.
+  return expr ? new tree_decl_elt (id, expr) : new tree_decl_elt (id);
+}
+
+bool
+base_parser::validate_param_list (tree_parameter_list *lst, tree_parameter_list::in_or_out type)
+{
+  std::set<std::string> dict;
+
+  for (tree_decl_elt *elt : *lst)
+    {
+      tree_identifier *id = elt->ident ();
+
+      if (id)
+        {
+          std::string name = id->name ();
+
+          if (id->is_black_hole ())
+            {
+              if (type != tree_parameter_list::in)
+                {
+                  bison_error ("invalid use of ~ in output list");
+                  return false;
+                }
+            }
+          else if (iskeyword (name))
+            {
+              bison_error ("invalid use of keyword '" + name + "' in parameter list");
+              return false;
+            }
+          else if (dict.find (name) != dict.end ())
+            {
+              bison_error ("'" + name + "' appears more than once in parameter list");
+              return false;
+            }
+          else
+            dict.insert (name);
+        }
+    }
+
+  std::string va_type = (type == tree_parameter_list::in ? "varargin" : "varargout");
+
+  std::size_t len = lst->size ();
+
+  if (len > 0)
+    {
+      tree_decl_elt *elt = lst->back ();
+
+      tree_identifier *id = elt->ident ();
+
+      if (id && id->name () == va_type)
+        {
+          if (len == 1)
+            lst->mark_varargs_only ();
+          else
+            lst->mark_varargs ();
+
+          tree_parameter_list::iterator p = lst->end ();
+          --p;
+          delete *p;
+          lst->erase (p);
+        }
+    }
+
+  return true;
+}
+
+bool
+base_parser::validate_array_list (tree_expression *e)
+{
+  bool retval = true;
+
+  tree_array_list *al = dynamic_cast<tree_array_list *> (e);
+
+  for (tree_argument_list* row : *al)
+    {
+      if (row && row->has_magic_tilde ())
+        {
+          retval = false;
+
+          if (e->is_matrix ())
+            bison_error ("invalid use of tilde (~) in matrix expression");
+          else
+            bison_error ("invalid use of tilde (~) in cell expression");
+
+          break;
+        }
+    }
+
+  return retval;
+}
+
+tree_argument_list *
+base_parser::validate_matrix_for_assignment (tree_expression *e)
+{
+  tree_argument_list *retval = nullptr;
+
+  if (e->is_constant ())
+    {
+      interpreter& interp = m_lexer.m_interpreter;
+
+      tree_evaluator& tw = interp.get_evaluator ();
+
+      octave_value ov = e->evaluate (tw);
+
+      delete e;
+
+      if (ov.isempty ())
+        bison_error ("invalid empty left hand side of assignment");
+      else
+        bison_error ("invalid constant left hand side of assignment");
+    }
+  else
+    {
+      bool is_simple_assign = true;
+
+      tree_argument_list *tmp = nullptr;
+
+      if (e->is_matrix ())
+        {
+          tree_matrix *mat = dynamic_cast<tree_matrix *> (e);
+
+          if (mat && mat->size () == 1)
+            {
+              tmp = mat->front ();
+              mat->pop_front ();
+              delete e;
+              is_simple_assign = false;
+            }
+        }
+      else
+        tmp = new tree_argument_list (e);
+
+      if (tmp && tmp->is_valid_lvalue_list ())
+        {
+          m_lexer.mark_as_variables (tmp->variable_names ());
+          retval = tmp;
+        }
+      else
+        {
+          delete tmp;
+
+          bison_error ("invalid left hand side of assignment");
+        }
+
+      if (retval && is_simple_assign)
+        retval->mark_as_simple_assign_lhs ();
+    }
+
+  return retval;
+}
+
+// Finish building an array_list.
+
+tree_expression *
+base_parser::finish_array_list (token *open_delim, tree_array_list *array_list, token *close_delim)
+{
+  tree_expression *retval = array_list;
+
+  array_list->mark_in_delims (*open_delim, *close_delim);
+
+  if (array_list->all_elements_are_constant ())
+    {
+      interpreter& interp = m_lexer.m_interpreter;
+
+      try
+        {
+          // If the evaluation generates a warning message, restore
+          // the previous value of last_warning_message and skip the
+          // conversion to a constant value.
+
+          error_system& es = interp.get_error_system ();
+
+          unwind_action restore_last_warning_message (&error_system::set_last_warning_message, &es, es.last_warning_message (""));
+
+          unwind_action restore_discard_warning_messages (&error_system::set_discard_warning_messages, &es, es.discard_warning_messages (true));
+
+          tree_evaluator& tw = interp.get_evaluator ();
+
+          octave_value tmp = array_list->evaluate (tw);
+
+          std::string msg = es.last_warning_message ();
+
+          if (msg.empty ())
+            {
+              std::ostringstream buf;
+
+              tree_print_code tpc (buf);
+
+              array_list->accept (tpc);
+
+              std::string orig_text = buf.str ();
+
+              token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());
+
+              tree_constant *tc_retval = new tree_constant (tmp, orig_text, tok);
+
+              delete array_list;
+
+              retval = tc_retval;
+            }
+        }
+      catch (const execution_exception&)
+        {
+          interp.recover_from_exception ();
+        }
+    }
+
+  return retval;
+}
+
+// Finish building a matrix list.
+
+tree_expression *
+base_parser::finish_matrix (token *open_delim, tree_matrix *m, token *close_delim)
+{
+  if (m)
+    return finish_array_list (open_delim, m, close_delim);
+
+  octave_value tmp {octave_null_matrix::instance};
+  std::string orig_text {"{}"};
+
+  token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());
+
+  return new tree_constant (tmp, orig_text, tok);
+}
+
+tree_matrix *
+base_parser::make_matrix (tree_argument_list *row)
+{
+  return row ? new tree_matrix (row) : nullptr;
+}
+
+tree_matrix *
+base_parser::append_matrix_row (tree_matrix *matrix, token *sep_tok, tree_argument_list *row)
+{
+  if (! matrix)
+    return make_matrix (row);
+
+  return row ? list_append (matrix, *sep_tok, row) : matrix;
+}
+
+// Finish building a cell list.
+
+tree_expression *
+base_parser::finish_cell (token *open_delim, tree_cell *c, token *close_delim)
+{
+  if (c)
+    return finish_array_list (open_delim, c, close_delim);
+
+  octave_value tmp {Cell ()};
+  std::string orig_text {"{}"};
+
+  token tok (CONSTANT, tmp, orig_text, open_delim->beg_pos (), close_delim->end_pos ());
+
+  return new tree_constant (tmp, orig_text, tok);
+}
+
+tree_cell *
+base_parser::make_cell (tree_argument_list *row)
+{
+  return row ? new tree_cell (row) : nullptr;
+}
+
+tree_cell *
+base_parser::append_cell_row (tree_cell *cell, token *sep_tok, tree_argument_list *row)
+{
+  if (! cell)
+    return make_cell (row);
+
+  return row ? list_append (cell, *sep_tok, row) : cell;
+}
+
+tree_identifier *
+base_parser::make_identifier (token *ident)
+{
+  symbol_scope scope = m_lexer.m_symtab_context.curr_scope ();
+
+  return new tree_identifier (scope, *ident);
+}
+
+tree_superclass_ref *
+base_parser::make_superclass_ref (token *superclassref)
+{
+  std::string meth = superclassref->superclass_method_name ();
+  std::string cls = superclassref->superclass_class_name ();
+
+  return new tree_superclass_ref (meth, cls, *superclassref);
+}
+
+tree_metaclass_query *
+base_parser::make_metaclass_query (token *metaquery)
+{
+  std::string cls = metaquery->text ();
+
+  return new tree_metaclass_query (cls, *metaquery);
+}
+
+tree_statement_list *
+base_parser::set_stmt_print_flag (tree_statement_list *list, char sep, bool warn_missing_semi)
+{
+  tree_statement *tmp = list->back ();
+
+  switch (sep)
+    {
+    case ';':
+      tmp->set_print_flag (false);
+      break;
+
+    case 0:
+    case ',':
+    case '\n':
+      tmp->set_print_flag (true);
+      if (warn_missing_semi)
+        maybe_warn_missing_semi (list);
+      break;
+
+    default:
+      warning ("unrecognized separator type!");
+      break;
+    }
+
+  // Even if a statement is null, we add it to the list then remove it
+  // here so that the print flag is applied to the correct statement.
+
+  if (tmp->is_null_statement ())
+    {
+      list->pop_back ();
+      delete tmp;
+    }
+
+  return list;
+}
+
+// Finish building a statement.
+template <typename T>
+tree_statement *
+base_parser::make_statement (T *arg)
+{
+  return new tree_statement (arg);
+}
+
+tree_statement_list *
+base_parser::make_statement_list (tree_statement *stmt)
+{
+  return new tree_statement_list (stmt);
+}
+
+tree_statement_list *
+base_parser::append_statement_list (tree_statement_list *list, char sep, tree_statement *stmt, bool warn_missing_semi)
+{
+  set_stmt_print_flag (list, sep, warn_missing_semi);
+
+  return list_append (list, stmt);
+}
+
+tree_statement_list *
+base_parser::make_function_def_list (tree_function_def *fcn_def)
+{
+  tree_statement *stmt = make_statement (fcn_def);
+
+  return new tree_statement_list (stmt);
+}
+
+tree_statement_list *
+base_parser::append_function_def_list (tree_statement_list *list, char, tree_function_def *fcn_def)
+{
+  tree_statement *stmt = make_statement (fcn_def);
+
+  return list_append (list, stmt);
+}
+
+tree_argument_list *
+base_parser::make_argument_list (tree_expression *expr)
+{
+  return new tree_argument_list (expr);
+}
+
+tree_argument_list *
+base_parser::append_argument_list (tree_argument_list *list, token *sep_tok, tree_expression *expr)
+{
+  return list_append (list, *sep_tok, expr);
+}
+
+tree_parameter_list *
+base_parser::make_parameter_list (tree_parameter_list::in_or_out io)
+{
+  return new tree_parameter_list (io);
+}
+
+tree_parameter_list *
+base_parser::make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t)
+{
+  return new tree_parameter_list (io, t);
+}
+
+tree_parameter_list *
+base_parser::make_parameter_list (tree_parameter_list::in_or_out io, tree_identifier *id)
+{
+  return new tree_parameter_list (io, id);
+}
+
+tree_parameter_list *
+base_parser::append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_decl_elt *t)
+{
+  return list_append (list, *sep_tok, t);
+}
+
+tree_parameter_list *
+base_parser::append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_identifier *id)
+{
+  return list_append (list, *sep_tok, new tree_decl_elt (id));
+}
+
+void
+base_parser::disallow_command_syntax ()
+{
+  m_lexer.m_allow_command_syntax = false;
+}
+
+void
+base_parser::bison_error (const std::string& str)
+{
+  bison_error (str, m_lexer.m_filepos);
+}
+
+void
+base_parser::bison_error (const std::string& str, const filepos& pos)
+{
+  std::ostringstream output_buf;
+
+  int err_line = pos.line ();
+  int err_col = pos.column ();
+
+  bool in_file = (m_lexer.m_reading_fcn_file || m_lexer.m_reading_script_file || m_lexer.m_reading_classdef_file);
+
+  // Adjust the error column for display because it is 1-based in the
+  // lexer for easier reporting.
+  err_col--;
+
+  if (in_file)
+    output_buf << str << " near line " << err_line << ", column " << err_col << " in file " << m_lexer.m_fcn_file_full_name << "\n";
+  else
+    {
+      // On command line, point directly to error
+      output_buf << str << "\n\n";
+      std::string curr_line = m_lexer.m_current_input_line;
+
+      if (! curr_line.empty ())
+        {
+          // FIXME: we could do better if we just cached lines from the
+          // input file in a list.  See also functions for managing input
+          // buffers in lex.ll.
+          std::size_t len = curr_line.length ();
+
+          if (curr_line[len-1] == '\n')
+            curr_line.resize (len-1);
+
+          // Print the line, maybe with a pointer near the error token.
+          output_buf << ">>> " << curr_line << "\n";
+
+          if (err_col == 0)
+            err_col = len;
+
+          for (int i = 0; i < err_col + 3; i++)
+            output_buf << " ";
+
+          output_buf << "^" << "\n";
+        }
+
+    }
+
+  m_parse_error_msg = output_buf.str ();
+}
+
+void
+base_parser::bison_error (const parse_exception& pe)
+{
+  bison_error (pe.message (), pe.pos ());
+}
+
+void
+base_parser::bison_error (const std::list<parse_exception>& pe_list)
+{
+  // For now, we just report the first error found.  Reporting all
+  // errors will require a bit more refactoring.
+
+  parse_exception pe = pe_list.front ();
+
+  bison_error (pe.message (), pe.pos ());
+}
+
+int
+parser::run ()
+{
+  int status = -1;
+
+  yypstate *pstate = static_cast<yypstate *> (m_parser_state);
+
+  try
+    {
+      status = octave_pull_parse (pstate, *this);
+    }
+  catch (const execution_exception&)
+    {
+      // FIXME: In previous versions, we emitted a parse error here
+      // but that is not always correct because the error could have
+      // happened inside a GUI callback functions executing in the
+      // readline event_hook loop.  Maybe we need a separate exception
+      // class for parse errors?
+
+      throw;
+    }
+  catch (const exit_exception&)
+    {
+      throw;
+    }
+  catch (const interrupt_exception&)
+    {
+      throw;
+    }
+  catch (...)
+    {
+      std::string file = m_lexer.m_fcn_file_full_name;
+
+      if (file.empty ())
+        error ("unexpected exception while parsing input");
+      else
+        error ("unexpected exception while parsing %s", file.c_str ());
+    }
+
+  if (status != 0)
+    parse_error_with_id ("Octave:parse-error", "%s", m_parse_error_msg.c_str ());
+
+  return status;
+}
+
+// Parse input from INPUT.  Pass TRUE for EOF if the end of INPUT should
+// finish the parse.
+
+int
+push_parser::run (const std::string& input, bool eof)
+{
+  int status = -1;
+
+  dynamic_cast<push_lexer&> (m_lexer).append_input (input, eof);
+
+  do
+    {
+      YYSTYPE lval;
+
+      int tok_id = octave_lex (&lval, m_lexer.m_scanner);
+
+      if (tok_id < 0)
+        {
+          // TOKEN == -2 means that the lexer recognized a comment
+          // and we should be at the end of the buffer but not the
+          // end of the file so we should return 0 to indicate
+          // "complete input" instead of -1 to request more input.
+
+          status = (tok_id == -2 ? 0 : -1);
+
+          if (! eof && m_lexer.at_end_of_buffer ())
+            return status;
+
+          break;
+        }
+
+      yypstate *pstate = static_cast<yypstate *> (m_parser_state);
+
+      try
+        {
+          status = octave_push_parse (pstate, tok_id, &lval, *this);
+        }
+      catch (execution_exception& e)
+        {
+          std::string file = m_lexer.m_fcn_file_full_name;
+
+          if (file.empty ())
+            error (e, "parse error");
+          else
+            error (e, "parse error in %s", file.c_str ());
+        }
+      catch (const exit_exception&)
+        {
+          throw;
+        }
+      catch (interrupt_exception &)
+        {
+          throw;
+        }
+      catch (...)
+        {
+          std::string file = m_lexer.m_fcn_file_full_name;
+
+          if (file.empty ())
+            error ("unexpected exception while parsing input");
+          else
+            error ("unexpected exception while parsing %s", file.c_str ());
+        }
+    }
+  while (status == YYPUSH_MORE || ! m_lexer.at_end_of_buffer ());
+
+  if (status != 0)
+    parse_error_with_id ("Octave:parse-error", "%s", m_parse_error_msg.c_str ());
+
+  return status;
+}
+
+int
+push_parser::run ()
+{
+  if (! m_reader)
+    error ("push_parser::run requires valid input_reader");
+
+  int exit_status = 0;
+
+  std::string prompt = command_editor::decode_prompt_string (m_interpreter.PS1 ());
+
+  do
+    {
+      // Reset status each time through the read loop so that
+      // it won't be set to -1 and cause us to exit the outer
+      // loop early if there is an exception while reading
+      // input or parsing.
+
+      exit_status = 0;
+
+      bool eof = false;
+      std::string input_line = m_reader->get_input (prompt, eof);
+
+      if (eof)
+        {
+          exit_status = EOF;
+          break;
+        }
+
+      exit_status = run (input_line, false);
+
+      prompt = command_editor::decode_prompt_string (m_interpreter.PS2 ());
+    }
+  while (exit_status < 0);
+
+  return exit_status;
+}
+
+octave_value
+parse_fcn_file (interpreter& interp, const std::string& full_file, const std::string& file, const std::string& dir_name, const std::string& dispatch_type, const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup)
+{
+  octave_value retval;
+
+  FILE *ffile = nullptr;
+
+  if (! full_file.empty ())
     {
       // Check that m-file is not overly large which can segfault interpreter.
       const int max_file_size = 512 * 1024 * 1024;  // 512 MB
@@ -5857,333 +5263,302 @@
       ffile = sys::fopen (full_file, "rb");
     }
 
-    if (! ffile)
-      {
-        if (require_file)
-          error ("no such file, '%s'", full_file.c_str ());
-
-        return octave_value ();
-      }
-
-    unwind_action act ([=] () { ::fclose (ffile); });
-
-    // get the encoding for this folder
-    input_system& input_sys = interp.get_input_system ();
-    parser parser (ffile, interp, input_sys.dir_encoding (dir_name));
-
-    parser.m_curr_class_name = dispatch_type;
-    parser.m_curr_package_name = package_name;
-    parser.m_autoloading = autoload;
-    parser.m_fcn_file_from_relative_lookup = relative_lookup;
-
-    parser.m_lexer.m_force_script = force_script;
-    parser.m_lexer.prep_for_file ();
-    parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
-
-    parser.m_lexer.m_fcn_file_name = file;
-    parser.m_lexer.m_fcn_file_full_name = full_file;
-    parser.m_lexer.m_dir_name = dir_name;
-    parser.m_lexer.m_package_name = package_name;
-
-    int err = parser.run ();
-
-    if (err)
-      error ("parse error while reading file %s", full_file.c_str ());
-
-    octave_value ov_fcn = parser.m_primary_fcn;
-
-    if (parser.m_lexer.m_reading_classdef_file
-        && parser.classdef_object ())
-      {
-        // Convert parse tree for classdef object to
-        // meta.class info (and stash it in the symbol
-        // table?).  Return pointer to constructor?
-
-        if (ov_fcn.is_defined ())
-          panic_impossible ();
-
-        bool is_at_folder = ! dispatch_type.empty ();
-
-        std::shared_ptr<tree_classdef> cdef_obj
-          = parser.classdef_object();
-
-        return cdef_obj->make_meta_class (interp, is_at_folder);
-      }
-    else if (ov_fcn.is_defined ())
-      {
-        octave_function *fcn = ov_fcn.function_value ();
-
-        fcn->maybe_relocate_end ();
-
-        if (parser.m_parsing_subfunctions)
-          {
-            if (! parser.m_endfunction_found)
-              parser.m_subfunction_names.reverse ();
-
-            fcn->stash_subfunction_names (parser.m_subfunction_names);
-          }
-
-        return ov_fcn;
-      }
-
-    return octave_value ();
-  }
-
-  bool
-  base_parser::finish_input (tree_statement_list *lst, bool at_eof)
-  {
-    m_lexer.m_end_of_input = at_eof;
-
-    if (lst)
-      {
-        parse_tree_validator validator;
-
-        lst->accept (validator);
-
-        if (! validator.ok ())
-          {
-            delete lst;
-
-            bison_error (validator.error_list ());
-
-            return false;
-          }
-      }
-
-    std::shared_ptr<tree_statement_list> tmp_lst (lst);
-
-    statement_list (tmp_lst);
-
-    return true;
-  }
-
-  // Check script or function for semantic errors.
-  bool
-  base_parser::validate_primary_fcn ()
-  {
-    octave_user_code *code = m_primary_fcn.user_code_value ();
-
-    if (code)
-      {
-        parse_tree_validator validator;
-
-        code->accept (validator);
-
-        if (! validator.ok ())
-          {
-            bison_error (validator.error_list ());
-
-            return false;
-          }
-      }
-
-    return true;
-  }
-
-  // Maybe print a warning if an assignment expression is used as the
-  // test in a logical expression.
-
-  void
-  base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
-  {
-    if (expr->is_assignment_expression ()
-        && expr->paren_count () < 2)
-      {
-        if (m_lexer.m_fcn_file_full_name.empty ())
-          warning_with_id
-            ("Octave:assign-as-truth-value",
-             "suggest parenthesis around assignment used as truth value");
-        else
-          warning_with_id
-            ("Octave:assign-as-truth-value",
-             "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'",
-             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  // Maybe print a warning about switch labels that aren't constants.
-
-  void
-  base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
-  {
-    if (! expr->is_constant ())
-      {
-        if (m_lexer.m_fcn_file_full_name.empty ())
-          warning_with_id ("Octave:variable-switch-label",
-                           "variable switch label");
-        else
-          warning_with_id
-            ("Octave:variable-switch-label",
-             "variable switch label near line %d, column %d in file '%s'",
-             expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  void
-  base_parser::maybe_warn_missing_semi (tree_statement_list *t)
-  {
-    if (m_curr_fcn_depth >= 0)
-      {
-        tree_statement *tmp = t->back ();
-
-        if (tmp->is_expression ())
-          warning_with_id
-            ("Octave:missing-semicolon",
-             "missing semicolon near line %d, column %d in file '%s'",
-             tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());
-      }
-  }
-
-  std::string
-  get_help_from_file (const std::string& nm, bool& symbol_found,
-                      std::string& full_file)
-  {
-    std::string retval;
-
-    full_file = fcn_file_in_path (nm);
-
-    std::string file = full_file;
-
-    std::size_t file_len = file.length ();
-
-    if ((file_len > 4 && file.substr (file_len-4) == ".oct")
-        || (file_len > 4 && file.substr (file_len-4) == ".mex")
-        || (file_len > 2 && file.substr (file_len-2) == ".m"))
-      {
-        file = sys::env::base_pathname (file);
-        file = file.substr (0, file.find_last_of ('.'));
-
-        std::size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());
-        if (pos != std::string::npos)
-          file = file.substr (pos+1);
-      }
-
-    if (! file.empty ())
-      {
-        interpreter& interp = __get_interpreter__ ();
-
-        symbol_found = true;
-
-        octave_value ov_fcn
-          = parse_fcn_file (interp, full_file, file, "", "", "", true,
-                            false, false, false);
-
-        if (ov_fcn.is_defined ())
-          {
-            octave_function *fcn = ov_fcn.function_value ();
-
-            if (fcn)
-              retval = fcn->doc_string ();
-          }
-      }
-
-    return retval;
-  }
-
-  std::string
-  get_help_from_file (const std::string& nm, bool& symbol_found)
-  {
-    std::string file;
-    return get_help_from_file (nm, symbol_found, file);
-  }
-
-  octave_value
-  load_fcn_from_file (const std::string& file_name,
-                      const std::string& dir_name,
-                      const std::string& dispatch_type,
-                      const std::string& package_name,
-                      const std::string& fcn_name, bool autoload)
-  {
-    octave_value retval;
-
-    unwind_protect frame;
-
-    std::string nm = file_name;
-
-    std::size_t nm_len = nm.length ();
-
-    std::string file;
-
-    bool relative_lookup = false;
-
-    file = nm;
-
-    if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
-        || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
-        || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
-      {
-        nm = sys::env::base_pathname (file);
-        nm = nm.substr (0, nm.find_last_of ('.'));
-
-        std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());
-        if (pos != std::string::npos)
-          nm = nm.substr (pos+1);
-      }
-
-    relative_lookup = ! sys::env::absolute_pathname (file);
-
-    file = sys::env::make_absolute (file);
-
-    int len = file.length ();
-
-    interpreter& interp = __get_interpreter__ ();
-
-    dynamic_loader& dyn_loader = interp.get_dynamic_loader ();
-
-    if (len > 4 && file.substr (len-4, len-1) == ".oct")
-      {
-        if (autoload && ! fcn_name.empty ())
-          nm = fcn_name;
-
-        octave_function *tmpfcn
-          = dyn_loader.load_oct (nm, file, relative_lookup);
-
-        if (tmpfcn)
-          {
-            tmpfcn->stash_package_name (package_name);
-            retval = octave_value (tmpfcn);
-          }
-      }
-    else if (len > 4 && file.substr (len-4, len-1) == ".mex")
-      {
-        // Temporarily load m-file version of mex-file, if it exists,
-        // to get the help-string to use.
-
-        std::string doc_string;
-
-        octave_value ov_fcn
-          = parse_fcn_file (interp, file.substr (0, len - 2), nm, dir_name,
-                            dispatch_type, package_name, false,
-                            autoload, autoload, relative_lookup);
-
-        if (ov_fcn.is_defined ())
-          {
-            octave_function *tmpfcn = ov_fcn.function_value ();
-
-            if (tmpfcn)
-              doc_string = tmpfcn->doc_string ();
-          }
-
-        octave_function *tmpfcn
-          = dyn_loader.load_mex (nm, file, relative_lookup);
-
-        if (tmpfcn)
-          {
-            tmpfcn->document (doc_string);
-            tmpfcn->stash_package_name (package_name);
-
-            retval = octave_value (tmpfcn);
-          }
-      }
-    else if (len > 2)
-      {
-        retval = parse_fcn_file (interp, file, nm, dir_name,
-                                 dispatch_type, package_name, true,
-                                 autoload, autoload, relative_lookup);
-      }
-
-    return retval;
-  }
+  if (! ffile)
+    {
+      if (require_file)
+        error ("no such file, '%s'", full_file.c_str ());
+
+      return octave_value ();
+    }
+
+  unwind_action act ([ffile] () { ::fclose (ffile); });
+
+  // get the encoding for this folder
+  input_system& input_sys = interp.get_input_system ();
+  parser parser (ffile, interp, input_sys.dir_encoding (dir_name));
+
+  parser.m_curr_class_name = dispatch_type;
+  parser.m_curr_package_name = package_name;
+  parser.m_autoloading = autoload;
+  parser.m_fcn_file_from_relative_lookup = relative_lookup;
+
+  parser.m_lexer.m_force_script = force_script;
+  parser.m_lexer.prep_for_file ();
+  parser.m_lexer.m_parsing_class_method = ! dispatch_type.empty ();
+
+  parser.m_lexer.m_fcn_file_name = file;
+  parser.m_lexer.m_fcn_file_full_name = full_file;
+  parser.m_lexer.m_dir_name = dir_name;
+  parser.m_lexer.m_package_name = package_name;
+
+  int err = parser.run ();
+
+  if (err)
+    error ("parse error while reading file %s", full_file.c_str ());
+
+  octave_value ov_fcn = parser.m_primary_fcn;
+
+  if (parser.m_lexer.m_reading_classdef_file && parser.classdef_object ())
+    {
+      // Convert parse tree for classdef object to
+      // meta.class info (and stash it in the symbol
+      // table?).  Return pointer to constructor?
+
+      if (ov_fcn.is_defined ())
+        error ("unexpected: defining classdef object but primary_fcn is already defined - please report this bug");
+
+      bool is_at_folder = ! dispatch_type.empty ();
+
+      std::shared_ptr<tree_classdef> cdef_obj = parser.classdef_object();
+
+      return cdef_obj->make_meta_class (interp, is_at_folder);
+    }
+  else if (ov_fcn.is_defined ())
+    {
+      octave_function *fcn = ov_fcn.function_value ();
+
+      fcn->maybe_relocate_end ();
+
+      if (parser.m_parsing_subfunctions)
+        {
+          if (! parser.m_endfunction_found)
+            parser.m_subfunction_names.reverse ();
+
+          fcn->stash_subfunction_names (parser.m_subfunction_names);
+        }
+
+      return ov_fcn;
+    }
+
+  return octave_value ();
+}
+
+bool
+base_parser::finish_input (tree_statement_list *lst, bool at_eof)
+{
+  m_lexer.m_end_of_input = at_eof;
+
+  if (lst)
+    {
+      parse_tree_validator validator;
+
+      lst->accept (validator);
+
+      if (! validator.ok ())
+        {
+          delete lst;
+
+          bison_error (validator.error_list ());
+
+          return false;
+        }
+    }
+
+  std::shared_ptr<tree_statement_list> tmp_lst (lst);
+
+  statement_list (tmp_lst);
+
+  return true;
+}
+
+// Check script or function for semantic errors.
+bool
+base_parser::validate_primary_fcn ()
+{
+  octave_user_code *code = m_primary_fcn.user_code_value ();
+
+  if (code)
+    {
+      parse_tree_validator validator;
+
+      code->accept (validator);
+
+      if (! validator.ok ())
+        {
+          bison_error (validator.error_list ());
+
+          return false;
+        }
+    }
+
+  return true;
+}
+
+// Maybe print a warning if an assignment expression is used as the
+// test in a logical expression.
+
+void
+base_parser::maybe_warn_assign_as_truth_value (tree_expression *expr)
+{
+  if (expr->is_assignment_expression () && expr->delim_count () < 2)
+    {
+      if (m_lexer.m_fcn_file_full_name.empty ())
+        warning_with_id ("Octave:assign-as-truth-value", "suggest parenthesis around assignment used as truth value");
+      else
+        warning_with_id ("Octave:assign-as-truth-value", "suggest parenthesis around assignment used as truth value near line %d, column %d in file '%s'", expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
+    }
+}
+
+// Maybe print a warning about switch labels that aren't constants.
+
+void
+base_parser::maybe_warn_variable_switch_label (tree_expression *expr)
+{
+  if (! expr->is_constant ())
+    {
+      if (m_lexer.m_fcn_file_full_name.empty ())
+        warning_with_id ("Octave:variable-switch-label", "variable switch label");
+      else
+        warning_with_id ("Octave:variable-switch-label", "variable switch label near line %d, column %d in file '%s'", expr->line (), expr->column (), m_lexer.m_fcn_file_full_name.c_str ());
+    }
+}
+
+void
+base_parser::maybe_warn_missing_semi (tree_statement_list *t)
+{
+  if (m_curr_fcn_depth >= 0)
+    {
+      tree_statement *tmp = t->back ();
+
+      if (tmp->is_expression ())
+        warning_with_id ("Octave:missing-semicolon", "missing semicolon near line %d, column %d in file '%s'", tmp->line (), tmp->column (), m_lexer.m_fcn_file_full_name.c_str ());
+    }
+}
+
+std::string
+get_help_from_file (const std::string& nm, bool& symbol_found, std::string& full_file)
+{
+  std::string retval;
+
+  full_file = fcn_file_in_path (nm);
+
+  std::string file = full_file;
+
+  std::size_t file_len = file.length ();
+
+  if ((file_len > 4 && file.substr (file_len-4) == ".oct")
+      || (file_len > 4 && file.substr (file_len-4) == ".mex")
+      || (file_len > 2 && file.substr (file_len-2) == ".m"))
+    {
+      file = sys::env::base_pathname (file);
+      file = file.substr (0, file.find_last_of ('.'));
+
+      std::size_t pos = file.find_last_of (sys::file_ops::dir_sep_str ());
+      if (pos != std::string::npos)
+        file = file.substr (pos+1);
+    }
+
+  if (! file.empty ())
+    {
+      interpreter& interp = __get_interpreter__ ();
+
+      symbol_found = true;
+
+      octave_value ov_fcn = parse_fcn_file (interp, full_file, file, "", "", "", true, false, false, false);
+
+      if (ov_fcn.is_defined ())
+        {
+          octave_function *fcn = ov_fcn.function_value ();
+
+          if (fcn)
+            retval = fcn->doc_string ();
+        }
+    }
+
+  return retval;
+}
+
+std::string
+get_help_from_file (const std::string& nm, bool& symbol_found)
+{
+  std::string file;
+  return get_help_from_file (nm, symbol_found, file);
+}
+
+octave_value
+load_fcn_from_file (const std::string& file_name, const std::string& dir_name, const std::string& dispatch_type, const std::string& package_name, const std::string& fcn_name, bool autoload)
+{
+  octave_value retval;
+
+  unwind_protect frame;
+
+  std::string nm = file_name;
+
+  std::size_t nm_len = nm.length ();
+
+  std::string file;
+
+  bool relative_lookup = false;
+
+  file = nm;
+
+  if ((nm_len > 4 && nm.substr (nm_len-4) == ".oct")
+      || (nm_len > 4 && nm.substr (nm_len-4) == ".mex")
+      || (nm_len > 2 && nm.substr (nm_len-2) == ".m"))
+    {
+      nm = sys::env::base_pathname (file);
+      nm = nm.substr (0, nm.find_last_of ('.'));
+
+      std::size_t pos = nm.find_last_of (sys::file_ops::dir_sep_str ());
+      if (pos != std::string::npos)
+        nm = nm.substr (pos+1);
+    }
+
+  relative_lookup = ! sys::env::absolute_pathname (file);
+
+  file = sys::env::make_absolute (file);
+
+  int len = file.length ();
+
+  interpreter& interp = __get_interpreter__ ();
+
+  dynamic_loader& dyn_loader = interp.get_dynamic_loader ();
+
+  if (len > 4 && file.substr (len-4, len-1) == ".oct")
+    {
+      if (autoload && ! fcn_name.empty ())
+        nm = fcn_name;
+
+      octave_function *tmpfcn = dyn_loader.load_oct (nm, file, relative_lookup);
+
+      if (tmpfcn)
+        {
+          tmpfcn->stash_package_name (package_name);
+          retval = octave_value (tmpfcn);
+        }
+    }
+  else if (len > 4 && file.substr (len-4, len-1) == ".mex")
+    {
+      // Temporarily load m-file version of mex-file, if it exists,
+      // to get the help-string to use.
+
+      std::string doc_string;
+
+      octave_value ov_fcn = parse_fcn_file (interp, file.substr (0, len - 2), nm, dir_name, dispatch_type, package_name, false, autoload, autoload, relative_lookup);
+
+      if (ov_fcn.is_defined ())
+        {
+          octave_function *tmpfcn = ov_fcn.function_value ();
+
+          if (tmpfcn)
+            doc_string = tmpfcn->doc_string ();
+        }
+
+      octave_function *tmpfcn = dyn_loader.load_mex (nm, file, relative_lookup);
+
+      if (tmpfcn)
+        {
+          tmpfcn->document (doc_string);
+          tmpfcn->stash_package_name (package_name);
+
+          retval = octave_value (tmpfcn);
+        }
+    }
+  else if (len > 2)
+    retval = parse_fcn_file (interp, file, nm, dir_name, dispatch_type, package_name, true, autoload, autoload, relative_lookup);
+
+  return retval;
+}
 
 DEFMETHOD (autoload, interp, args, ,
            doc: /* -*- texinfo -*-
@@ -6243,8 +5618,7 @@
       else if (nargin == 3)
         {
           if (argv[3] != "remove")
-            error_with_id ("Octave:invalid-input-arg",
-                           "autoload: third argument can only be 'remove'");
+            error_with_id ("Octave:invalid-input-arg", "autoload: third argument can only be 'remove'");
 
           tw.remove_autoload (argv[1], argv[2]);
         }
@@ -6319,8 +5693,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  std::string file_name
-    = args(0).xstring_value ("source: FILE must be a string");
+  std::string file_name = args(0).xstring_value ("source: FILE must be a string");
 
   std::string context;
   if (nargin == 2)
@@ -6525,8 +5898,7 @@
     return interp.eval (try_code, nargout);
   else
     {
-      if (! args(1).is_string () || args(1).rows () > 1
-          || args(1).ndims () != 2)
+      if (! args(1).is_string () || args(1).rows () > 1 || args(1).ndims () != 2)
         error ("eval: CATCH must be a string");
 
       std::string catch_code = args(1).string_value ();
@@ -6598,11 +5970,9 @@
   if (args.length () != 3)
     print_usage ();
 
-  std::string context
-    = args(0).xstring_value ("assignin: CONTEXT must be a string");
-
-  std::string varname
-    = args(1).xstring_value ("assignin: VARNAME must be a string");
+  std::string context = args(0).xstring_value ("assignin: CONTEXT must be a string");
+
+  std::string varname = args(1).xstring_value ("assignin: VARNAME must be a string");
 
   interp.assignin (context, varname, args(2));
 
@@ -6629,16 +5999,13 @@
   if (nargin < 2 || nargin > 3)
     print_usage ();
 
-  std::string context
-    = args(0).xstring_value ("evalin: CONTEXT must be a string");
-
-  std::string try_code
-    = args(1).xstring_value ("evalin: TRY must be a string");
+  std::string context = args(0).xstring_value ("evalin: CONTEXT must be a string");
+
+  std::string try_code = args(1).xstring_value ("evalin: TRY must be a string");
 
   if (nargin == 3)
     {
-      std::string catch_code
-        = args(2).xstring_value ("evalin: CATCH must be a string");
+      std::string catch_code = args(2).xstring_value ("evalin: CATCH must be a string");
 
       return interp.evalin (context, try_code, catch_code, nargout);
     }
@@ -6697,7 +6064,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 ([=] ()
+  unwind_action act ([old_out_buf, old_err_buf] ()
                              {
                                octave_stdout.rdbuf (old_out_buf);
                                std::cerr.rdbuf (old_err_buf);
@@ -6837,8 +6204,7 @@
   if (nargin < 1 || nargin > 2)
     print_usage ();
 
-  std::string file
-    = args(0).xstring_value ("__parse_file__: expecting filename as argument");
+  std::string file = args(0).xstring_value ("__parse_file__: expecting filename as argument");
 
   std::string full_file = sys::file_ops::tilde_expand (file);
 
@@ -6866,9 +6232,7 @@
   if (nargin == 2)
     octave_stdout << "parsing " << full_file << std::endl;
 
-  octave_value ov_fcn
-    = parse_fcn_file (interp, full_file, file, dir_name, "", "", true,
-                      false, false, false);
+  octave_value ov_fcn = parse_fcn_file (interp, full_file, file, dir_name, "", "", true, false, false, false);
 
   return retval;
 }
--- a/libinterp/parse-tree/octave.gperf	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/octave.gperf	Fri Apr 12 15:10:26 2024 +0200
@@ -83,7 +83,7 @@
 
 %}
 
-struct octave_kw { const char *name; int tok; octave_kw_id kw_id; };
+struct octave_kw { const char *name; int tok_id; octave_kw_id kw_id; };
 
 %%
 arguments, ARGUMENTS, arguments_kw
@@ -114,7 +114,7 @@
 enumeration, ENUMERATION, enumeration_kw
 events, EVENTS, events_kw
 for, FOR, for_kw
-function, FCN, function_kw
+function, FUNCTION, function_kw
 get, GET, get_kw
 global, GLOBAL, global_kw
 if, IF, if_kw
@@ -123,7 +123,7 @@
 parfor, PARFOR, parfor_kw
 persistent, PERSISTENT, persistent_kw
 properties, PROPERTIES, properties_kw
-return, FUNC_RET, return_kw
+return, RETURN, return_kw
 set, SET, set_kw
 spmd, SPMD, spmd_kw
 switch, SWITCH, switch_kw
--- a/libinterp/parse-tree/parse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/parse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,7 +48,6 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class comment_list;
 class parse_exception;
 class tree;
 class tree_anon_fcn_handle;
@@ -67,9 +66,9 @@
 class tree_classdef_enum_block;
 class tree_classdef_enum_list;
 class tree_classdef_events_block;
-class tree_classdef_events_list;
+class tree_classdef_event_list;
 class tree_classdef_methods_block;
-class tree_classdef_methods_list;
+class tree_classdef_method_list;
 class tree_classdef_properties_block;
 class tree_classdef_property_list;
 class tree_classdef_superclass_list;
@@ -234,37 +233,38 @@
   OCTINTERP_API bool push_fcn_symtab ();
 
   // Build a constant.
-  OCTINTERP_API tree_constant * make_constant (token *tok_val);
+  OCTINTERP_API tree_constant * make_constant (token *tok);
 
-  OCTINTERP_API tree_black_hole * make_black_hole ();
+  OCTINTERP_API tree_black_hole * make_black_hole (token *tilde);
 
   OCTINTERP_API tree_matrix * make_matrix (tree_argument_list *row);
 
   OCTINTERP_API tree_matrix *
-  append_matrix_row (tree_matrix *matrix, tree_argument_list *row);
+  append_matrix_row (tree_matrix *matrix, token *sep_tok, tree_argument_list *row);
 
   OCTINTERP_API tree_cell * make_cell (tree_argument_list *row);
 
   OCTINTERP_API tree_cell *
-  append_cell_row (tree_cell *cell, tree_argument_list *row);
+  append_cell_row (tree_cell *cell, token *sep_tok, tree_argument_list *row);
 
   // Build a function handle.
-  OCTINTERP_API tree_fcn_handle * make_fcn_handle (token *tok_val);
+  OCTINTERP_API tree_fcn_handle * make_fcn_handle (token *tok);
 
   // Build an anonymous function handle.
   OCTINTERP_API tree_anon_fcn_handle *
-  make_anon_fcn_handle (tree_parameter_list *param_list,
-                        tree_expression *expr, const filepos& at_pos);
+  make_anon_fcn_handle (token *at_tok, tree_parameter_list *param_list, tree_expression *expr);
 
   // Build a colon expression.
   OCTINTERP_API tree_expression *
-  make_colon_expression (tree_expression *base, tree_expression *limit,
-                         tree_expression *incr = nullptr);
+  make_colon_expression (tree_expression *base, token *colon_tok, tree_expression *limit);
+
+  // Build a colon expression.
+  OCTINTERP_API tree_expression *
+  make_colon_expression (tree_expression *base, token *colon_1_tok, tree_expression *incr, token *colon_2_tok, tree_expression *limit);
 
   // Build a binary expression.
   OCTINTERP_API tree_expression *
-  make_binary_op (int op, tree_expression *op1, token *tok_val,
-                  tree_expression *op2);
+  make_binary_op (tree_expression *op1, token *op_tok, tree_expression *op2);
 
   // Maybe convert EXPR to a braindead_shortcircuit expression.
   OCTINTERP_API void
@@ -272,47 +272,35 @@
 
   // Build a boolean expression.
   OCTINTERP_API tree_expression *
-  make_boolean_op (int op, tree_expression *op1, token *tok_val,
-                   tree_expression *op2);
+  make_boolean_op (tree_expression *op1, token *op_tok, tree_expression *op2);
 
   // Build a prefix expression.
   OCTINTERP_API tree_expression *
-  make_prefix_op (int op, tree_expression *op1, token *tok_val);
+  make_prefix_op (token *op_tok, tree_expression *op1);
 
   // Build a postfix expression.
   OCTINTERP_API tree_expression *
-  make_postfix_op (int op, tree_expression *op1, token *tok_val);
+  make_postfix_op (tree_expression *op1, token *op_tok);
 
   // Build an unwind-protect command.
   OCTINTERP_API tree_command *
-  make_unwind_command (token *unwind_tok, tree_statement_list *body,
-                       tree_statement_list *cleanup, token *end_tok,
-                       comment_list *lc, comment_list *mc);
+  make_unwind_command (token *unwind_tok, tree_statement_list *body, token *cleanup_tok, tree_statement_list *cleanup, token *end_tok);
 
   // Build a try-catch command.
   OCTINTERP_API tree_command *
-  make_try_command (token *try_tok, tree_statement_list *body,
-                    char catch_sep, tree_statement_list *cleanup,
-                    token *end_tok, comment_list *lc,
-                    comment_list *mc);
+  make_try_command (token *try_tok, tree_statement_list *body, token *catch_tok, char catch_sep, tree_statement_list *cleanup, token *end_tok);
 
   // Build a while command.
   OCTINTERP_API tree_command *
-  make_while_command (token *while_tok, tree_expression *expr,
-                      tree_statement_list *body, token *end_tok,
-                      comment_list *lc);
+  make_while_command (token *while_tok, tree_expression *expr, tree_statement_list *body, token *end_tok);
 
   // Build a do-until command.
   OCTINTERP_API tree_command *
-  make_do_until_command (token *until_tok, tree_statement_list *body,
-                         tree_expression *expr, comment_list *lc);
+  make_do_until_command (token *do_tok, tree_statement_list *body, token *until_tok, tree_expression *expr);
 
   // Build a for command.
   OCTINTERP_API tree_command *
-  make_for_command (int tok_id, token *for_tok, tree_argument_list *lhs,
-                    tree_expression *expr, tree_expression *maxproc,
-                    tree_statement_list *body, token *end_tok,
-                    comment_list *lc);
+  make_for_command (token *for_tok, token *open_paren, tree_argument_list *lhs, token *eq_tok, tree_expression *expr, token *sep_tok, tree_expression *maxproc, token *close_paren, tree_statement_list *body, token *end_tok);
 
   // Build a break command.
   OCTINTERP_API tree_command * make_break_command (token *break_tok);
@@ -326,55 +314,43 @@
   // Build an spmd command.
 
   OCTINTERP_API tree_spmd_command *
-  make_spmd_command (token *spmd_tok, tree_statement_list *body,
-                     token *end_tok, comment_list *lc, comment_list *tc);
+  make_spmd_command (token *spmd_tok, tree_statement_list *body, token *end_tok);
 
   // Start an if command.
   OCTINTERP_API tree_if_command_list *
-  start_if_command (tree_expression *expr, tree_statement_list *list);
+  start_if_command (tree_if_clause *clause);
 
   // Finish an if command.
   OCTINTERP_API tree_if_command *
-  finish_if_command (token *if_tok, tree_if_command_list *list,
-                     token *end_tok, comment_list *lc);
+  finish_if_command (tree_if_command_list *list, tree_if_clause *else_clause, token *end_tok);
 
   // Build an elseif clause.
   OCTINTERP_API tree_if_clause *
-  make_elseif_clause (token *elseif_tok, tree_expression *expr,
-                      tree_statement_list *list, comment_list *lc);
-
-  OCTINTERP_API tree_if_clause *
-  make_else_clause (token *else_tok, comment_list *lc,
-                    tree_statement_list *list);
+  make_if_clause (token *if_tok, tree_expression *expr, tree_statement_list *list);
 
   OCTINTERP_API tree_if_command_list *
   append_if_clause (tree_if_command_list *list, tree_if_clause *clause);
 
   // Finish a switch command.
   OCTINTERP_API tree_switch_command *
-  finish_switch_command (token *switch_tok, tree_expression *expr,
-                         tree_switch_case_list *list, token *end_tok,
-                         comment_list *lc);
+  finish_switch_command (token *switch_tok, tree_expression *expr, tree_switch_case_list *list, token *end_tok);
 
   OCTINTERP_API tree_switch_case_list *
   make_switch_case_list (tree_switch_case *switch_case);
 
   // Build a switch case.
   OCTINTERP_API tree_switch_case *
-  make_switch_case (token *case_tok, tree_expression *expr,
-                    tree_statement_list *list, comment_list *lc);
+  make_switch_case (token *case_tok, tree_expression *expr, tree_statement_list *list);
 
   OCTINTERP_API tree_switch_case *
-  make_default_switch_case (token *default_tok, comment_list *lc,
-                            tree_statement_list *list);
+  make_default_switch_case (token *default_tok, tree_statement_list *list);
 
   OCTINTERP_API tree_switch_case_list *
   append_switch_case (tree_switch_case_list *list, tree_switch_case *elt);
 
   // Build an assignment to a variable.
   OCTINTERP_API tree_expression *
-  make_assign_op (int op, tree_argument_list *lhs, token *eq_tok,
-                  tree_expression *rhs);
+  make_assign_op (tree_argument_list *lhs, token *eq_tok, tree_expression *rhs);
 
   // Define a script.
   OCTINTERP_API void
@@ -386,21 +362,15 @@
 
   // Define a function.
   OCTINTERP_API tree_function_def *
-  make_function (token *fcn_tok, tree_parameter_list *ret_list,
-                 tree_identifier *id, tree_parameter_list *param_list,
-                 tree_statement_list *body, tree_statement *end_fcn_stmt,
-                 comment_list *lc, comment_list *bc);
+  make_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_fcn_stmt);
 
   // Begin defining a function.
   OCTINTERP_API octave_user_function *
-  start_function (tree_identifier *id, tree_parameter_list *param_list,
-                  tree_statement_list *body, tree_statement *end_function,
-                  const std::string& doc_string);
+  start_function (tree_identifier *id, tree_parameter_list *param_list, tree_statement_list *body, tree_statement *end_function, const std::string& doc_string);
 
   // Create a no-op statement for end_function.
   OCTINTERP_API tree_statement *
-  make_end (const std::string& type, bool eof,
-            const filepos& beg_pos, const filepos& end_pos);
+  make_end (const std::string& type, bool eof, token *tok);
 
   // Do most of the work for defining a function.
   OCTINTERP_API octave_user_function *
@@ -408,29 +378,21 @@
 
   // Finish defining a function.
   OCTINTERP_API tree_function_def *
-  finish_function (tree_parameter_list *ret_list,
-                   octave_user_function *fcn, comment_list *lc,
-                   int l, int c);
+  finish_function (token *fcn_tok, tree_parameter_list *ret_list, token *eq_tok, octave_user_function *fcn);
 
   OCTINTERP_API tree_statement_list *
   append_function_body (tree_statement_list *body, tree_statement_list *list);
 
   // Make an arguments validation block.
   OCTINTERP_API tree_arguments_block *
-  make_arguments_block (token *arguments_tok,
-                        tree_args_block_attribute_list *attr_list,
-                        tree_args_block_validation_list *validation_list,
-                        token *end_tok, comment_list *lc, comment_list *tc);
+  make_arguments_block (token *arguments_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, token *end_tok);
 
   OCTINTERP_API tree_args_block_attribute_list *
   make_args_attribute_list (tree_identifier *attribute_name);
 
   // Make an argument validation.
   OCTINTERP_API tree_arg_validation *
-  make_arg_validation (tree_arg_size_spec *size_spec,
-                       tree_identifier *class_name,
-                       tree_arg_validation_fcns *validation_fcns,
-                       tree_expression *default_value);
+  make_arg_validation (tree_arg_size_spec *size_spec, tree_identifier *class_name, tree_arg_validation_fcns *validation_fcns, token *eq_tok = nullptr, tree_expression *default_value = nullptr);
 
   // Make an argument validation list.
   OCTINTERP_API tree_args_block_validation_list *
@@ -438,8 +400,7 @@
 
   // Append an argument validation to an existing list.
   OCTINTERP_API tree_args_block_validation_list *
-  append_args_validation_list (tree_args_block_validation_list *list,
-                               tree_arg_validation *arg_validation);
+  append_args_validation_list (tree_args_block_validation_list *list, tree_arg_validation *arg_validation);
 
   // Make an argument size specification object.
   OCTINTERP_API tree_arg_size_spec *
@@ -454,94 +415,70 @@
   recover_from_parsing_function ();
 
   OCTINTERP_API tree_classdef *
-  make_classdef (token *tok_val, tree_classdef_attribute_list *a,
-                 tree_identifier *id, tree_classdef_superclass_list *sc,
-                 tree_classdef_body *body, token *end_tok,
-                 comment_list *lc, comment_list *bc, comment_list *tc);
+  make_classdef (token *tok, tree_classdef_attribute_list *a, tree_identifier *id, tree_classdef_superclass_list *sc, tree_classdef_body *body, token *end_tok);
 
   OCTINTERP_API tree_classdef_properties_block *
-  make_classdef_properties_block (token *tok_val,
-                                  tree_classdef_attribute_list *a,
-                                  tree_classdef_property_list *plist,
-                                  token *end_tok, comment_list *lc,
-                                  comment_list *tc);
+  make_classdef_properties_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, token *end_tok);
 
   OCTINTERP_API tree_classdef_property_list *
   make_classdef_property_list (tree_classdef_property *prop);
 
   OCTINTERP_API tree_classdef_property *
-  make_classdef_property (comment_list *lc, tree_identifier *id,
-                          tree_arg_validation *av);
+  make_classdef_property (tree_identifier *id, tree_arg_validation *av);
 
   OCTINTERP_API tree_classdef_property_list *
-  append_classdef_property (tree_classdef_property_list *list,
-                            tree_classdef_property *elt);
+  append_classdef_property (tree_classdef_property_list *list, tree_classdef_property *elt);
 
   OCTINTERP_API tree_classdef_methods_block *
-  make_classdef_methods_block (token *tok_val,
-                               tree_classdef_attribute_list *a,
-                               tree_classdef_methods_list *mlist,
-                               token *end_tok, comment_list *lc,
-                               comment_list *tc);
+  make_classdef_methods_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, token *end_tok);
 
   OCTINTERP_API tree_classdef_events_block *
-  make_classdef_events_block (token *tok_val,
-                              tree_classdef_attribute_list *a,
-                              tree_classdef_events_list *elist,
-                              token *end_tok, comment_list *lc,
-                              comment_list *tc);
+  make_classdef_events_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, token *end_tok);
 
-  OCTINTERP_API tree_classdef_events_list *
-  make_classdef_events_list (tree_classdef_event *e);
+  OCTINTERP_API tree_classdef_event_list *
+  make_classdef_event_list (tree_classdef_event *e);
 
   OCTINTERP_API tree_classdef_event *
-  make_classdef_event (comment_list *lc, tree_identifier *id);
+  make_classdef_event (tree_identifier *id);
 
-  OCTINTERP_API tree_classdef_events_list *
-  append_classdef_event (tree_classdef_events_list *list,
-                         tree_classdef_event *elt);
+  OCTINTERP_API tree_classdef_event_list *
+  append_classdef_event (tree_classdef_event_list *list, tree_classdef_event *elt);
 
   OCTINTERP_API tree_classdef_enum_block *
-  make_classdef_enum_block (token *tok_val,
-                            tree_classdef_attribute_list *a,
-                            tree_classdef_enum_list *elist,
-                            token *end_tok, comment_list *lc,
-                            comment_list *tc);
+  make_classdef_enum_block (token *tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, token *end_tok);
 
   OCTINTERP_API tree_classdef_enum_list *
   make_classdef_enum_list (tree_classdef_enum *e);
 
   OCTINTERP_API tree_classdef_enum *
-  make_classdef_enum (tree_identifier *id, tree_expression *expr,
-                      comment_list *lc);
+  make_classdef_enum (tree_identifier *id, token *open_paren, tree_expression *expr, token *close_paren);
 
   OCTINTERP_API tree_classdef_enum_list *
-  append_classdef_enum (tree_classdef_enum_list *list,
-                        tree_classdef_enum *elt);
+  append_classdef_enum (tree_classdef_enum_list *list, tree_classdef_enum *elt);
 
   OCTINTERP_API tree_classdef_superclass_list *
-  make_classdef_superclass_list (tree_classdef_superclass *sc);
+  make_classdef_superclass_list (token *lt_tok, tree_classdef_superclass *sc);
 
   OCTINTERP_API tree_classdef_superclass *
   make_classdef_superclass (token *fqident);
 
   OCTINTERP_API tree_classdef_superclass_list *
-  append_classdef_superclass (tree_classdef_superclass_list *list,
-                              tree_classdef_superclass *elt);
+  append_classdef_superclass (tree_classdef_superclass_list *list, token *and_tok, tree_classdef_superclass *elt);
 
   OCTINTERP_API tree_classdef_attribute_list *
   make_classdef_attribute_list (tree_classdef_attribute *attr);
 
   OCTINTERP_API tree_classdef_attribute *
-  make_classdef_attribute (tree_identifier *id,
-                           tree_expression *expr = nullptr);
+  make_classdef_attribute (tree_identifier *id);
 
   OCTINTERP_API tree_classdef_attribute *
-  make_not_classdef_attribute (tree_identifier *id);
+  make_classdef_attribute (tree_identifier *id, token *eq_tok, tree_expression *expr);
+
+  OCTINTERP_API tree_classdef_attribute *
+  make_not_classdef_attribute (token *not_tok, tree_identifier *id);
 
   OCTINTERP_API tree_classdef_attribute_list *
-  append_classdef_attribute (tree_classdef_attribute_list *list,
-                             tree_classdef_attribute *elt);
+  append_classdef_attribute (tree_classdef_attribute_list *list, token *sep_tok, tree_classdef_attribute *elt);
 
   OCTINTERP_API tree_classdef_body *
   make_classdef_body (tree_classdef_properties_block *pb);
@@ -556,72 +493,64 @@
   make_classdef_body  (tree_classdef_enum_block *enb);
 
   OCTINTERP_API tree_classdef_body *
-  append_classdef_properties_block (tree_classdef_body *body,
-                                    tree_classdef_properties_block *block);
+  append_classdef_properties_block (tree_classdef_body *body, tree_classdef_properties_block *block);
 
   OCTINTERP_API tree_classdef_body *
-  append_classdef_methods_block (tree_classdef_body *body,
-                                 tree_classdef_methods_block *block);
+  append_classdef_methods_block (tree_classdef_body *body, tree_classdef_methods_block *block);
 
   OCTINTERP_API tree_classdef_body *
-  append_classdef_events_block (tree_classdef_body *body,
-                                tree_classdef_events_block *block);
+  append_classdef_events_block (tree_classdef_body *body, tree_classdef_events_block *block);
 
   OCTINTERP_API tree_classdef_body *
-  append_classdef_enum_block (tree_classdef_body *body,
-                              tree_classdef_enum_block *block);
+  append_classdef_enum_block (tree_classdef_body *body, tree_classdef_enum_block *block);
 
   OCTINTERP_API octave_user_function *
-  start_classdef_external_method (tree_identifier *id,
-                                  tree_parameter_list *pl);
+  start_classdef_external_method (tree_identifier *id, tree_parameter_list *pl = nullptr);
 
   OCTINTERP_API tree_function_def *
-  finish_classdef_external_method (octave_user_function *fcn,
-                                   tree_parameter_list *ret_list,
-                                   comment_list *cl);
+  finish_classdef_external_method (octave_user_function *fcn, tree_parameter_list *ret_list = nullptr, token *eq_tok = nullptr);
 
-  OCTINTERP_API tree_classdef_methods_list *
-  make_classdef_methods_list (tree_function_def *fcn_def);
+  OCTINTERP_API tree_classdef_method_list *
+  make_classdef_method_list (tree_function_def *fcn_def);
 
-  OCTINTERP_API tree_classdef_methods_list *
-  append_classdef_method (tree_classdef_methods_list *list,
-                          tree_function_def *fcn_def);
+  OCTINTERP_API tree_classdef_method_list *
+  append_classdef_method (tree_classdef_method_list *list, tree_function_def *fcn_def);
 
   OCTINTERP_API bool
-  finish_classdef_file (tree_classdef *cls,
-                        tree_statement_list *local_fcns);
+  finish_classdef_file (tree_classdef *cls, tree_statement_list *local_fcns, token *eof_tok);
+
+  // Make a word list command.
+  OCTINTERP_API tree_index_expression *
+  make_word_list_command (tree_expression *expr, tree_argument_list *args);
 
   // Make an index expression.
   OCTINTERP_API tree_index_expression *
-  make_index_expression (tree_expression *expr,
-                         tree_argument_list *args, char type);
+  make_index_expression (tree_expression *expr, token *open_paren, tree_argument_list *args, token *close_paren, char type);
 
   // Make an indirect reference expression.
   OCTINTERP_API tree_index_expression *
-  make_indirect_ref (tree_expression *expr, const std::string&);
+  make_indirect_ref (tree_expression *expr, token *dot_tok, token *struct_elt_tok);
 
   // Make an indirect reference expression with dynamic field name.
   OCTINTERP_API tree_index_expression *
-  make_indirect_ref (tree_expression *expr, tree_expression *field);
+  make_indirect_ref (tree_expression *expr, token *dot_tok, token *open_paren, tree_expression *field, token *close_paren);
 
   // Make a declaration command.
   OCTINTERP_API tree_decl_command *
-  make_decl_command (int tok, token *tok_val, tree_decl_init_list *lst);
+  make_decl_command (token *tok, tree_decl_init_list *lst);
 
   OCTINTERP_API tree_decl_init_list *
   make_decl_init_list (tree_decl_elt *elt);
 
   OCTINTERP_API tree_decl_elt *
-  make_decl_elt (tree_identifier *id, token *eq_op = nullptr,
-                 tree_expression *expr = nullptr);
+  make_decl_elt (tree_identifier *id, token *eq_op = nullptr, tree_expression *expr = nullptr);
 
   OCTINTERP_API tree_decl_init_list *
   append_decl_init_list (tree_decl_init_list *list, tree_decl_elt *elt);
 
   // Validate an function parameter list.
   OCTINTERP_API bool
-  validate_param_list (tree_parameter_list *lst,
-                       tree_parameter_list::in_or_out type);
+  validate_param_list (tree_parameter_list *lst, tree_parameter_list::in_or_out type);
   // Validate matrix or cell
   OCTINTERP_API bool validate_array_list (tree_expression *e);
 
@@ -632,16 +561,15 @@
   // Finish building an array_list (common action for finish_matrix
   // and finish_cell).
   OCTINTERP_API tree_expression *
-  finish_array_list (tree_array_list *a, token *open_delim,
-                     token *close_delim);
+  finish_array_list (token *open_delim, tree_array_list *a, token *close_delim);
 
   // Finish building a matrix list.
   OCTINTERP_API tree_expression *
-  finish_matrix (tree_matrix *m, token *open_delim, token *close_delim);
+  finish_matrix (token *open_delim, tree_matrix *m, token *close_delim);
 
   // Finish building a cell list.
   OCTINTERP_API tree_expression *
-  finish_cell (tree_cell *c, token *open_delim, token *close_delim);
+  finish_cell (token *open_delim, tree_cell *c, token *close_delim);
 
   OCTINTERP_API tree_identifier *
   make_identifier (token *ident);
@@ -666,14 +594,22 @@
 
   // Append a statement to an existing statement list.
   OCTINTERP_API tree_statement_list *
-  append_statement_list (tree_statement_list *list, char sep,
-                         tree_statement *stmt, bool warn_missing_semi);
+  append_statement_list (tree_statement_list *list, char sep, tree_statement *stmt, bool warn_missing_semi);
+
+  // Create a statement list containing only function_def commands.
+  OCTINTERP_API tree_statement_list *
+  make_function_def_list (tree_function_def *fcn_def);
+
+  // Append a function_def command to an existing statement list (that
+  // should contain only other function_def commands).
+  OCTINTERP_API tree_statement_list *
+  append_function_def_list (tree_statement_list *list, char sep, tree_function_def *fcn_def);
 
   OCTINTERP_API tree_argument_list *
   make_argument_list (tree_expression *expr);
 
   OCTINTERP_API tree_argument_list *
-  append_argument_list (tree_argument_list *list, tree_expression *expr);
+  append_argument_list (tree_argument_list *list, token *sep_tok, tree_expression *expr);
 
   OCTINTERP_API tree_parameter_list *
   make_parameter_list (tree_parameter_list::in_or_out io);
@@ -682,14 +618,13 @@
   make_parameter_list (tree_parameter_list::in_or_out io, tree_decl_elt *t);
 
   OCTINTERP_API tree_parameter_list *
-  make_parameter_list (tree_parameter_list::in_or_out io,
-                       tree_identifier *id);
+  make_parameter_list (tree_parameter_list::in_or_out io, tree_identifier *id);
 
   OCTINTERP_API tree_parameter_list *
-  append_parameter_list (tree_parameter_list *list, tree_decl_elt *t);
+  append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_decl_elt *t);
 
   OCTINTERP_API tree_parameter_list *
-  append_parameter_list (tree_parameter_list *list, tree_identifier *id);
+  append_parameter_list (tree_parameter_list *list, token *sep_tok, tree_identifier *id);
 
   // Don't allow parsing command syntax.  If the parser/lexer is
   // reset, this setting is also reset to the default (allow command
@@ -699,16 +634,11 @@
   // Generic error messages.
   OCTINTERP_API void bison_error (const std::string& s);
   OCTINTERP_API void bison_error (const std::string& s, const filepos& pos);
-  OCTINTERP_API void bison_error (const std::string& s, int line, int column);
   OCTINTERP_API void bison_error (const std::list<parse_exception>& pe);
   OCTINTERP_API void bison_error (const parse_exception& pe);
 
   friend OCTINTERP_API octave_value
-  parse_fcn_file (interpreter& interp, const std::string& full_file,
-                  const std::string& file, const std::string& dir_name,
-                  const std::string& dispatch_type,
-                  const std::string& package_name, bool require_file,
-                  bool force_script, bool autoload, bool relative_lookup);
+  parse_fcn_file (interpreter& interp, const std::string& full_file, const std::string& file, const std::string& dir_name, const std::string& dispatch_type, const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup);
 
   // Thih interface allows push or pull parsers to be used
   // equivalently, provided that the push parser also owns its input
@@ -722,8 +652,7 @@
   // semantic errors.
   OCTINTERP_API bool validate_primary_fcn ();
 
-  OCTINTERP_API bool finish_input (tree_statement_list *lst,
-                                   bool at_eof = false);
+  OCTINTERP_API bool finish_input (tree_statement_list *lst, bool at_eof = false);
 
 protected:
 
@@ -812,11 +741,7 @@
 // Publish externally used friend functions.
 
 extern OCTINTERP_API octave_value
-parse_fcn_file (interpreter& interp, const std::string& full_file,
-                const std::string& file, const std::string& dir_name,
-                const std::string& dispatch_type,
-                const std::string& package_name, bool require_file,
-                bool force_script, bool autoload, bool relative_lookup);
+parse_fcn_file (interpreter& interp, const std::string& full_file, const std::string& file, const std::string& dir_name, const std::string& dispatch_type, const std::string& package_name, bool require_file, bool force_script, bool autoload, bool relative_lookup);
 
 class parser : public base_parser
 {
@@ -858,16 +783,14 @@
 public:
 
   push_parser (interpreter& interp)
-    : base_parser (*(new push_lexer (interp))),
-      m_interpreter (interp), m_reader ()
+    : base_parser (*(new push_lexer (interp))), m_interpreter (interp), m_reader ()
   { }
 
   // The parser assumes ownership of READER, which must be created
   // with new.
 
   push_parser (interpreter& interp, input_reader *reader)
-    : base_parser (*(new push_lexer (interp))),
-      m_interpreter (interp), m_reader (reader)
+    : base_parser (*(new push_lexer (interp))), m_interpreter (interp), m_reader (reader)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (push_parser)
@@ -893,44 +816,28 @@
 };
 
 extern OCTINTERP_API std::string
-get_help_from_file (const std::string& nm, bool& symbol_found,
-                    std::string& file);
+get_help_from_file (const std::string& nm, bool& symbol_found, std::string& file);
 
 extern OCTINTERP_API std::string
 get_help_from_file (const std::string& nm, bool& symbol_found);
 
 extern OCTINTERP_API octave_value
-load_fcn_from_file (const std::string& file_name,
-                    const std::string& dir_name = "",
-                    const std::string& dispatch_type = "",
-                    const std::string& package_name = "",
-                    const std::string& fcn_name = "",
-                    bool autoload = false);
+load_fcn_from_file (const std::string& file_name, const std::string& dir_name = "", const std::string& dispatch_type = "", const std::string& package_name = "", const std::string& fcn_name = "", bool autoload = false);
 
 extern OCTINTERP_API void
-source_file (const std::string& file_name,
-             const std::string& context = "",
-             bool verbose = false, bool require_file = true);
+source_file (const std::string& file_name, const std::string& context = "", bool verbose = false, bool require_file = true);
 
 extern OCTINTERP_API octave_value_list
-feval (const char *name,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0);
+feval (const char *name, const octave_value_list& args = octave_value_list (), int nargout = 0);
 
 extern OCTINTERP_API octave_value_list
-feval (const std::string& name,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0);
+feval (const std::string& name, const octave_value_list& args = octave_value_list (), int nargout = 0);
 
 extern OCTINTERP_API octave_value_list
-feval (octave_function *fcn,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0);
+feval (octave_function *fcn, const octave_value_list& args = octave_value_list (), int nargout = 0);
 
 extern OCTINTERP_API octave_value_list
-feval (const octave_value& val,
-       const octave_value_list& args = octave_value_list (),
-       int nargout = 0);
+feval (const octave_value& val, const octave_value_list& args = octave_value_list (), int nargout = 0);
 
 extern OCTINTERP_API octave_value_list
 feval (const octave_value_list& args, int nargout = 0);
--- a/libinterp/parse-tree/profiler.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/profiler.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -86,11 +86,6 @@
 profiler::tree_node *
 profiler::tree_node::exit (octave_idx_type /* fcn */)
 {
-  // FIXME: These panic_unless statements don't make sense if profile() is
-  //  called from within a function hierarchy to begin with.  See bug #39587.
-  //  panic_unless (m_parent);
-  //  panic_unless (m_fcn_id == fcn);
-
   return m_parent;
 }
 
@@ -106,7 +101,9 @@
       entry.m_time += m_time;
       entry.m_calls += m_calls;
 
-      panic_unless (m_parent);
+      if (! m_parent)
+        error ("unexpected: m_parent is nullptr in profiler::tree_node::build_flat - please report this bug");
+
       if (m_parent->m_fcn_id != 0)
         {
           entry.m_parents.insert (m_parent->m_fcn_id);
@@ -193,8 +190,11 @@
 profiler::enter_function (const std::string& fcn)
 {
   // The enter class will check and only call us if the profiler is active.
-  panic_unless (enabled ());
-  panic_unless (m_call_tree);
+  if (! enabled ())
+    error ("unexpected: profiler not enabled in profiler::enter_function - please report this bug");
+
+  if (! m_call_tree)
+    error ("unexpected: m_call_tree is nullptr in profiler::enter_function - please report this bug");
 
   // If there is already an active function, add to its time before
   // pushing the new one.
@@ -227,11 +227,8 @@
 {
   if (m_active_fcn)
     {
-      panic_unless (m_call_tree);
-      // FIXME: This panic_unless statements doesn't make sense if profile()
-      //        is called from within a function hierarchy to begin with.
-      //        See bug #39587.
-      // panic_unless (m_active_fcn != m_call_tree);
+      if (! m_call_tree)
+        error ("unexpected: m_call_tree is nullptr in profiler::enter_function - please report this bug");
 
       // Usually, if we are disabled this function is not even called.  But
       // the call disabling the profiler is an exception.  So also check here
@@ -240,10 +237,7 @@
         add_current_time ();
 
       fcn_index_map::iterator pos = m_fcn_index.find (fcn);
-      // FIXME: This panic_unless statements doesn't make sense if profile()
-      //        is called from within a function hierarchy to begin with.
-      //        See bug #39587.
-      // panic_unless (pos != m_fcn_index.end ());
+
       m_active_fcn = m_active_fcn->exit (pos->second);
 
       // If this was an "inner call", we resume executing the parent function
@@ -364,11 +358,7 @@
 {
   sys::time now;
 
-  // FIXME: is this volatile declaration really needed?
-  // See bug #34210 for additional details.
-  volatile double dnow = now.double_value ();
-
-  return dnow;
+  return now.double_value ();
 }
 
 void
--- a/libinterp/parse-tree/profiler.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/profiler.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,9 +38,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTINTERP_API
-profiler
+class OCTINTERP_API profiler
 {
 public:
 
--- a/libinterp/parse-tree/pt-anon-scopes.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-anon-scopes.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
--- a/libinterp/parse-tree/pt-anon-scopes.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-anon-scopes.h	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#if !defined (octave_pt_anon_scopes_h)
+#if ! defined (octave_pt_anon_scopes_h)
 #define octave_pt_anon_scopes_h 1
 
 #include <set>
@@ -36,8 +36,7 @@
 // In possibly nested definitions of anonymous functions, collect
 // their scopes and the symbol records therein.
 
-class
-tree_anon_scopes : public tree_walker
+class tree_anon_scopes : public tree_walker
 {
 public:
 
--- a/libinterp/parse-tree/pt-arg-list.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-arg-list.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -54,9 +54,9 @@
 }
 
 void
-tree_argument_list::append (const element_type& s)
+tree_argument_list::push_back (const element_type& s)
 {
-  base_list<tree_expression *>::append (s);
+  std::list<tree_expression *>::push_back (s);
 
   if (! m_list_includes_magic_tilde && s && s->is_identifier ())
     {
@@ -100,7 +100,7 @@
 string_vector
 tree_argument_list::get_arg_names () const
 {
-  int len = length ();
+  int len = size ();
 
   string_vector retval (len);
 
@@ -143,9 +143,11 @@
   tree_argument_list *new_list = new tree_argument_list ();
 
   new_list->m_simple_assign_lhs = m_simple_assign_lhs;
+  new_list->m_list_includes_magic_tilde = m_list_includes_magic_tilde;
+  new_list->m_delims = m_delims;
 
   for (const tree_expression *elt : *this)
-    new_list->append (elt ? elt->dup (scope) : nullptr);
+    new_list->push_back (elt ? elt->dup (scope) : nullptr);
 
   return new_list;
 }
--- a/libinterp/parse-tree/pt-arg-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-arg-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,10 @@
 
 #include "str-vec.h"
 
-#include "base-list.h"
+#include "pt-delimiter-list.h"
+#include "pt-exp.h"
 #include "pt-walk.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -47,24 +49,54 @@
 // Argument lists.  Used to hold the list of expressions that are the
 // arguments in a function call or index expression.
 
-class tree_argument_list : public base_list<tree_expression *>
+class tree_argument_list : public std::list<tree_expression *>
 {
 public:
 
   typedef tree_expression *element_type;
 
-  tree_argument_list ()
-    : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false)
-  { }
+  tree_argument_list () { }
 
-  tree_argument_list (tree_expression *t)
-    : m_list_includes_magic_tilde (false), m_simple_assign_lhs (false)
-  { append (t); }
+  tree_argument_list (tree_expression *t) { push_back (t); }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_argument_list)
 
   ~tree_argument_list ();
 
+  tree_argument_list * mark_in_delims (const token& open_delim, const token& close_delim)
+  {
+    m_delims.push (open_delim, close_delim);
+    return this;
+  }
+
+  filepos beg_pos () const
+  {
+    if (m_delims.empty ())
+      {
+        if (empty ())
+          return filepos ();
+
+        tree_expression *elt = front ();
+        return elt->beg_pos ();
+      }
+
+    return m_delims.beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (m_delims.empty ())
+      {
+        if (empty ())
+          return filepos ();
+
+        tree_expression *elt = back ();
+        return elt->end_pos ();
+      }
+
+    return m_delims.end_pos ();
+  }
+
   bool has_magic_tilde () const
   {
     return m_list_includes_magic_tilde;
@@ -83,7 +115,7 @@
     return retval;
   }
 
-  void append (const element_type& s);
+  void push_back (const element_type& s);
 
   void mark_as_simple_assign_lhs () { m_simple_assign_lhs = true; }
 
@@ -106,9 +138,11 @@
 
 private:
 
-  bool m_list_includes_magic_tilde;
+  bool m_list_includes_magic_tilde {false};
 
-  bool m_simple_assign_lhs;
+  bool m_simple_assign_lhs {false};
+
+  tree_delimiter_list m_delims;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-args-block.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-args-block.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,19 +28,21 @@
 
 #include "octave-config.h"
 
+#include <list>
+
 #include "pt-arg-list.h"
 #include "pt-cmd.h"
 #include "pt-exp.h"
 #include "pt-id.h"
 #include "pt-walk.h"
 
-#include "base-list.h"
-
 // FIXME: We could maybe re-think the naming of some of these objects
 // before releasing a version that contains these new classes...
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class comment_list;
+
 class tree_arg_size_spec
 {
 public:
@@ -102,10 +104,11 @@
   tree_arg_validation (tree_arg_size_spec *size_spec,
                        tree_identifier *class_name,
                        tree_arg_validation_fcns *validation_fcns,
+                       const token& eq_tok,
                        tree_expression *default_value)
     : m_arg_name (nullptr), m_size_spec (size_spec),
       m_class_name (class_name), m_validation_fcns (validation_fcns),
-      m_default_value (default_value)
+      m_eq_tok (eq_tok), m_default_value (default_value)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arg_validation)
@@ -149,20 +152,21 @@
   tree_arg_size_spec *m_size_spec;
   tree_identifier *m_class_name;
   tree_arg_validation_fcns *m_validation_fcns;
+  token m_eq_tok;
   tree_expression *m_default_value;
 };
 
 class tree_args_block_validation_list
-  : public base_list<tree_arg_validation *>
+  : public std::list<tree_arg_validation *>
 {
 public:
 
   tree_args_block_validation_list () { }
 
-  tree_args_block_validation_list (tree_arg_validation *a) { append (a); }
+  tree_args_block_validation_list (tree_arg_validation *a) { push_back (a); }
 
-  tree_args_block_validation_list (const base_list<tree_arg_validation *>& a)
-    : base_list<tree_arg_validation *> (a)
+  tree_args_block_validation_list (const std::list<tree_arg_validation *>& a)
+    : std::list<tree_arg_validation *> (a)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_args_block_validation_list)
@@ -211,12 +215,8 @@
 {
 public:
 
-  tree_arguments_block (tree_args_block_attribute_list *attr_list,
-                        tree_args_block_validation_list *validation_list,
-                        int l = -1, int c = -1)
-    : tree_command (l, c), m_attr_list (attr_list),
-      m_validation_list (validation_list),
-      m_lead_comm (nullptr), m_trail_comm (nullptr)
+  tree_arguments_block (const token& args_tok, tree_args_block_attribute_list *attr_list, tree_args_block_validation_list *validation_list, const token& end_tok)
+    : m_args_tok (args_tok), m_attr_list (attr_list), m_validation_list (validation_list), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_arguments_block)
@@ -225,10 +225,10 @@
   {
     delete m_attr_list;
     delete m_validation_list;
+  }
 
-    delete m_lead_comm;
-    delete m_trail_comm;
-  }
+  filepos beg_pos () const { return m_args_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
 
   tree_args_block_attribute_list * attribute_list ()
   {
@@ -240,10 +240,6 @@
     return m_validation_list;
   }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
-
   void accept (tree_walker& tw)
   {
     tw.visit_arguments_block (*this);
@@ -251,15 +247,13 @@
 
 private:
 
+  token m_args_tok;
+
   tree_args_block_attribute_list *m_attr_list;
 
   tree_args_block_validation_list *m_validation_list;
 
-  // Comment preceding ARGUMENTS token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDARGUMENTS token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-array-list.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-array-list.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,7 +69,7 @@
                             symbol_scope& scope)
 {
   for (const tree_argument_list *elt : array_list)
-    append (elt ? elt->dup (scope) : nullptr);
+    push_back (elt ? elt->dup (scope) : nullptr);
 
   copy_base (*this);
 }
--- a/libinterp/parse-tree/pt-array-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-array-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,8 @@
 
 #include "octave-config.h"
 
-#include "base-list.h"
+#include <list>
+
 #include "pt-arg-list.h"
 #include "pt-exp.h"
 
@@ -40,20 +41,19 @@
 // Base class for cell arrays and matrices.
 
 class tree_array_list : public tree_expression,
-  public base_list<tree_argument_list *>
+  public std::list<tree_argument_list *>
 {
 public:
 
-  typedef base_list<tree_argument_list *>::iterator iterator;
-  typedef base_list<tree_argument_list *>::const_iterator const_iterator;
+  typedef std::list<tree_argument_list *>::iterator iterator;
+  typedef std::list<tree_argument_list *>::const_iterator const_iterator;
 
 protected:
 
-  tree_array_list (tree_argument_list *row = nullptr, int l = -1, int c = -1)
-    : tree_expression (l, c), base_list<tree_argument_list *> ()
+  tree_array_list (tree_argument_list *row = nullptr)
   {
     if (row)
-      append (row);
+      push_back (row);
   }
 
 public:
@@ -62,6 +62,12 @@
 
   ~tree_array_list ();
 
+  // The delimiter list for a cell array should never be empty.  But
+  // better safe than sorry, I guess.
+
+  filepos beg_pos () const { return m_delims.empty () ? filepos () : m_delims.beg_pos (); }
+  filepos end_pos () const { return m_delims.empty () ? filepos () : m_delims.end_pos (); }
+
   bool all_elements_are_constant () const;
 
   // FIXME: should we import the functions from the base class and
--- a/libinterp/parse-tree/pt-assign.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-assign.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -40,12 +40,8 @@
 
 // Simple assignment expressions.
 
-tree_simple_assignment::tree_simple_assignment (tree_expression *le,
-    tree_expression *re,
-    bool plhs, int l, int c,
-    octave_value::assign_op t)
-  : tree_expression (l, c), m_lhs (le), m_rhs (re), m_preserve (plhs),
-    m_ans_assign (), m_etype (t)
+tree_simple_assignment::tree_simple_assignment (tree_expression *le, tree_expression *re, bool plhs, octave_value::assign_op t)
+  : m_lhs (le), m_rhs (re), m_preserve (plhs), m_ans_assign (), m_etype (t)
 { }
 
 tree_simple_assignment::~tree_simple_assignment ()
@@ -153,10 +149,8 @@
 
 // Multi-valued assignment expressions.
 
-tree_multi_assignment::tree_multi_assignment (tree_argument_list *lst,
-    tree_expression *r,
-    bool plhs, int l, int c)
-  : tree_expression (l, c), m_lhs (lst), m_rhs (r), m_preserve (plhs)
+tree_multi_assignment::tree_multi_assignment (tree_argument_list *lst, tree_expression *r, bool plhs)
+  : m_lhs (lst), m_rhs (r), m_preserve (plhs)
 { }
 
 tree_multi_assignment::~tree_multi_assignment ()
--- a/libinterp/parse-tree/pt-assign.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-assign.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,12 @@
 class octave_value;
 class octave_value_list;
 
+#include "comment-list.h"
 #include "ov.h"
+#include "pt-arg-list.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -50,20 +53,17 @@
 {
 public:
 
-  tree_simple_assignment (bool plhs = false, int l = -1, int c = -1,
-                          octave_value::assign_op t = octave_value::op_asn_eq)
-    : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr),
-      m_preserve (plhs), m_ans_assign (), m_etype (t)
-  { }
-
-  tree_simple_assignment (tree_expression *le, tree_expression *re,
-                          bool plhs = false, int l = -1, int c = -1,
-                          octave_value::assign_op t = octave_value::op_asn_eq);
+  tree_simple_assignment (tree_expression *le, tree_expression *re, bool plhs = false, octave_value::assign_op t = octave_value::op_asn_eq);
 
   OCTAVE_DISABLE_COPY_MOVE (tree_simple_assignment)
 
   ~tree_simple_assignment ();
 
+  comment_list leading_comments () const { return m_lhs->leading_comments (); }
+
+  filepos beg_pos () const { return m_lhs->beg_pos (); }
+  filepos end_pos () const { return m_rhs->end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   bool is_assignment_expression () const { return true; }
@@ -119,13 +119,11 @@
 {
 public:
 
-  tree_multi_assignment (bool plhs = false, int l = -1, int c = -1)
-    : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr),
-      m_preserve (plhs)
+  tree_multi_assignment (bool plhs = false)
+    : m_lhs (nullptr), m_rhs (nullptr), m_preserve (plhs)
   { }
 
-  tree_multi_assignment (tree_argument_list *lst, tree_expression *r,
-                         bool plhs = false, int l = -1, int c = -1);
+  tree_multi_assignment (tree_argument_list *lst, tree_expression *r, bool plhs = false);
 
   OCTAVE_DISABLE_COPY_MOVE (tree_multi_assignment)
 
@@ -133,6 +131,9 @@
 
   bool is_assignment_expression () const { return true; }
 
+  filepos beg_pos () const { return m_lhs->beg_pos (); }
+  filepos end_pos () const { return m_rhs->end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   std::string oper () const;
--- a/libinterp/parse-tree/pt-binop.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-binop.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -58,8 +58,9 @@
 {
   tree_binary_expression *new_be
     = new tree_binary_expression (m_lhs ? m_lhs->dup (scope) : nullptr,
+                                  m_op_tok,
                                   m_rhs ? m_rhs->dup (scope) : nullptr,
-                                  line (), column (), m_etype);
+                                  m_etype);
 
   new_be->copy_base (*this);
 
@@ -108,8 +109,9 @@
   tree_braindead_shortcircuit_binary_expression *new_be
     = new tree_braindead_shortcircuit_binary_expression
   (m_lhs ? m_lhs->dup (scope) : nullptr,
+   m_op_tok,
    m_rhs ? m_rhs->dup (scope) : nullptr,
-   line (), column (), op_type ());
+   op_type ());
 
   new_be->copy_base (*this);
 
@@ -117,8 +119,7 @@
 }
 
 octave_value
-tree_braindead_shortcircuit_binary_expression::evaluate (tree_evaluator& tw,
-    int)
+tree_braindead_shortcircuit_binary_expression::evaluate (tree_evaluator& tw, int)
 {
   if (m_lhs)
     {
@@ -194,8 +195,9 @@
 {
   tree_boolean_expression *new_be
     = new tree_boolean_expression (m_lhs ? m_lhs->dup (scope) : nullptr,
+                                   m_op_tok,
                                    m_rhs ? m_rhs->dup (scope) : nullptr,
-                                   line (), column (), m_etype);
+                                   m_etype);
 
   new_be->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-binop.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-binop.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,19 +47,12 @@
 {
 public:
 
-  tree_binary_expression (int l = -1, int c = -1,
-                          octave_value::binary_op t
-                          = octave_value::unknown_binary_op)
-    : tree_expression (l, c), m_lhs (nullptr), m_rhs (nullptr), m_etype (t),
-      m_preserve_operands (false)
+  tree_binary_expression (octave_value::binary_op t = octave_value::unknown_binary_op)
+    : m_lhs (nullptr), m_rhs (nullptr), m_etype (t), m_preserve_operands (false)
   { }
 
-  tree_binary_expression (tree_expression *a, tree_expression *b,
-                          int l = -1, int c = -1,
-                          octave_value::binary_op t
-                          = octave_value::unknown_binary_op)
-    : tree_expression (l, c), m_lhs (a), m_rhs (b), m_etype (t),
-      m_preserve_operands (false)
+  tree_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t = octave_value::unknown_binary_op)
+    : m_lhs (a), m_op_tok (op_tok), m_rhs (b), m_etype (t), m_preserve_operands (false)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_binary_expression)
@@ -73,10 +66,15 @@
       }
   }
 
+  token operator_token () const { return m_op_tok; }
+
   void preserve_operands () { m_preserve_operands = true; }
 
   bool is_binary_expression () const { return true; }
 
+  filepos beg_pos () const { return m_lhs->beg_pos (); }
+  filepos end_pos () const { return m_rhs->end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   std::string oper () const;
@@ -108,10 +106,14 @@
   void matlab_style_short_circuit_warning (const char *op);
 
   virtual bool is_braindead () const { return false; }
+
 protected:
 
-  // The operands for the expression.
+  // The operands and operator for the expression.
   tree_expression *m_lhs;
+
+  token m_op_tok;
+
   tree_expression *m_rhs;
 
 private:
@@ -128,11 +130,8 @@
 {
 public:
 
-  tree_braindead_shortcircuit_binary_expression (tree_expression *a,
-                                                 tree_expression *b,
-                                                 int l, int c,
-                                                 octave_value::binary_op t)
-    : tree_binary_expression (a, b, l, c, t)
+  tree_braindead_shortcircuit_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t)
+    : tree_binary_expression (a, op_tok, b, t)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_braindead_shortcircuit_binary_expression)
@@ -161,12 +160,11 @@
     bool_or
   };
 
-  tree_boolean_expression (int l = -1, int c = -1, type t = unknown)
-    : tree_binary_expression (l, c), m_etype (t) { }
+  tree_boolean_expression (type t = unknown) : m_etype (t) { }
 
-  tree_boolean_expression (tree_expression *a, tree_expression *b,
-                           int l = -1, int c = -1, type t = unknown)
-    : tree_binary_expression (a, b, l, c), m_etype (t) { }
+  tree_boolean_expression (tree_expression *a, const token& op_tok, tree_expression *b, type t = unknown)
+    : tree_binary_expression (a, op_tok, b), m_etype (t)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_boolean_expression)
 
--- a/libinterp/parse-tree/pt-bp.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-bp.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -33,6 +33,12 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+OCTAVE_NORETURN static void
+error_unexpected (const char *name)
+{
+  error ("unexpected call to %s - please report this bug", name);
+}
+
 void
 tree_breakpoint::visit_while_command (tree_while_command& cmd)
 {
@@ -69,7 +75,7 @@
 void
 tree_breakpoint::visit_argument_list (tree_argument_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_argument_list");
 }
 
 void
@@ -81,37 +87,37 @@
 void
 tree_breakpoint::visit_args_block_attribute_list (tree_args_block_attribute_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_args_block_attribute_list");
 }
 
 void
 tree_breakpoint::visit_args_block_validation_list (tree_args_block_validation_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_args_block_validation_list");
 }
 
 void
 tree_breakpoint::visit_arg_validation (tree_arg_validation&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_arg_validation");
 }
 
 void
 tree_breakpoint::visit_arg_size_spec (tree_arg_size_spec&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_arg_size_spec");
 }
 
 void
 tree_breakpoint::visit_arg_validation_fcns (tree_arg_validation_fcns&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_arg_validation_fcns");
 }
 
 void
 tree_breakpoint::visit_binary_expression (tree_binary_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_binary_expression");
 }
 
 void
@@ -124,7 +130,7 @@
 void
 tree_breakpoint::visit_colon_expression (tree_colon_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_colon_expression");
 }
 
 void
@@ -144,13 +150,13 @@
 void
 tree_breakpoint::visit_decl_init_list (tree_decl_init_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_decl_init_list");
 }
 
 void
 tree_breakpoint::visit_decl_elt (tree_decl_elt&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_decl_elt");
 }
 
 void
@@ -186,25 +192,25 @@
 void
 tree_breakpoint::visit_octave_user_function_header (octave_user_function&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_octave_user_function_header");
 }
 
 void
 tree_breakpoint::visit_octave_user_function_trailer (octave_user_function&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_octave_user_function_trailer");
 }
 
 void
 tree_breakpoint::visit_identifier (tree_identifier&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_identifier");
 }
 
 void
 tree_breakpoint::visit_if_clause (tree_if_clause&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_if_clause");
 }
 
 void
@@ -231,25 +237,25 @@
 void
 tree_breakpoint::visit_index_expression (tree_index_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_index_expression");
 }
 
 void
 tree_breakpoint::visit_matrix (tree_matrix&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_matrix");
 }
 
 void
 tree_breakpoint::visit_cell (tree_cell&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_cell");
 }
 
 void
 tree_breakpoint::visit_multi_assignment (tree_multi_assignment&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_multi_assignment");
 }
 
 void
@@ -262,37 +268,37 @@
 void
 tree_breakpoint::visit_anon_fcn_handle (tree_anon_fcn_handle&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_anon_fcn_handle");
 }
 
 void
 tree_breakpoint::visit_constant (tree_constant&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_constant");
 }
 
 void
 tree_breakpoint::visit_fcn_handle (tree_fcn_handle&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_fcn_handle");
 }
 
 void
 tree_breakpoint::visit_parameter_list (tree_parameter_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_parameter_list");
 }
 
 void
 tree_breakpoint::visit_postfix_expression (tree_postfix_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_postfix_expression");
 }
 
 void
 tree_breakpoint::visit_prefix_expression (tree_prefix_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_prefix_expression");
 }
 
 void
@@ -305,7 +311,7 @@
 void
 tree_breakpoint::visit_simple_assignment (tree_simple_assignment&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_simple_assignment");
 }
 
 void
@@ -345,7 +351,7 @@
 void
 tree_breakpoint::visit_switch_case (tree_switch_case&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_breakpoint::visit_switch_case");
 }
 
 void
@@ -421,30 +427,34 @@
 void
 tree_breakpoint::take_action (tree& tr)
 {
-  if (m_action == set)
+  switch (m_action)
     {
+    case set:
       tr.set_breakpoint (m_condition);
       m_line = tr.line ();
       m_found = true;
-    }
-  else if (m_action == clear)
-    {
+      break;
+
+    case clear:
       if (tr.is_breakpoint ())
         {
           tr.delete_breakpoint ();
           m_found = true;
         }
-    }
-  else if (m_action == list)
-    {
+      break;
+
+    case list:
       if (tr.is_breakpoint ())
         {
           m_bp_list.append (octave_value (tr.line ()));
           m_bp_cond_list.append (octave_value (tr.bp_cond ()));
         }
+      break;
+
+      // We should have handled all possible enum values above.  Rely on
+      // compiler diagnostics to warn if we haven't.  For example, GCC's
+      // -Wswitch option, enabled by -Wall, will provide a warning.
     }
-  else
-    panic_impossible ();
 }
 
 void
@@ -452,30 +462,34 @@
 {
   int lineno = stmt.line ();
 
-  if (m_action == set)
+  switch (m_action)
     {
+    case set:
       stmt.set_breakpoint (m_condition);
       m_line = lineno;
       m_found = true;
-    }
-  else if (m_action == clear)
-    {
+      break;
+
+    case clear:
       if (stmt.is_breakpoint ())
         {
           stmt.delete_breakpoint ();
           m_found = true;
         }
-    }
-  else if (m_action == list)
-    {
+      break;
+
+    case list:
       if (stmt.is_breakpoint ())
         {
           m_bp_list.append (octave_value (lineno));
           m_bp_cond_list.append (octave_value (stmt.bp_cond ()));
         }
+      break;
+
+      // We should have handled all possible enum values above.  Rely on
+      // compiler diagnostics to warn if we haven't.  For example, GCC's
+      // -Wswitch option, enabled by -Wall, will provide a warning.
     }
-  else
-    panic_impossible ();
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-cbinop.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-cbinop.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -140,8 +140,7 @@
 // Possibly contract and/or with negation.
 
 tree_binary_expression *
-maybe_compound_binary_expression (tree_expression *a, tree_expression *b,
-                                  int l, int c, octave_value::binary_op t)
+maybe_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t)
 {
   tree_expression *ca = a;
   tree_expression *cb = b;
@@ -164,8 +163,8 @@
 
   tree_binary_expression *ret
     = (ct == octave_value::unknown_compound_binary_op
-       ? new tree_binary_expression (a, b, l, c, t)
-       : new tree_compound_binary_expression (a, b, l, c, t, ca, cb, ct));
+       ? new tree_binary_expression (a, op_tok, b, t)
+       : new tree_compound_binary_expression (a, op_tok, b, t, ca, cb, ct));
 
   return ret;
 }
--- a/libinterp/parse-tree/pt-cbinop.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-cbinop.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,13 +45,9 @@
 {
 public:
 
-  tree_compound_binary_expression (tree_expression *a, tree_expression *b,
-                                   int l, int c,
-                                   octave_value::binary_op t,
-                                   tree_expression *ca, tree_expression *cb,
-                                   octave_value::compound_binary_op ct)
-    : tree_binary_expression (a, b, l, c, t), m_lhs (ca), m_rhs (cb),
-      m_etype (ct)
+  tree_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t,
+                                   tree_expression *ca, tree_expression *cb, octave_value::compound_binary_op ct)
+    : tree_binary_expression (a, op_tok, b, t), m_lhs (ca), m_rhs (cb), m_etype (ct)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_compound_binary_expression)
@@ -89,10 +85,7 @@
 // a "virtual constructor"
 
 tree_binary_expression *
-maybe_compound_binary_expression (tree_expression *a, tree_expression *b,
-                                  int l = -1, int c = -1,
-                                  octave_value::binary_op t
-                                  = octave_value::unknown_binary_op);
+maybe_compound_binary_expression (tree_expression *a, const token& op_tok, tree_expression *b, octave_value::binary_op t = octave_value::unknown_binary_op);
 
 OCTAVE_END_NAMESPACE(octave)
 
--- a/libinterp/parse-tree/pt-cell.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-cell.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -41,7 +41,7 @@
 tree_expression *
 tree_cell::dup (symbol_scope& scope) const
 {
-  tree_cell *new_cell = new tree_cell (nullptr, line (), column ());
+  tree_cell *new_cell = new tree_cell (nullptr);
 
   new_cell->copy_base (*this, scope);
 
@@ -57,7 +57,7 @@
   }, tw.lvalue_list ());
   tw.set_lvalue_list (nullptr);
 
-  octave_idx_type nr = length ();
+  octave_idx_type nr = size ();
   octave_idx_type nc = -1;
 
   Cell val;
--- a/libinterp/parse-tree/pt-cell.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-cell.h	Fri Apr 12 15:10:26 2024 +0200
@@ -47,8 +47,8 @@
 {
 public:
 
-  tree_cell (tree_argument_list *row = nullptr, int l = -1, int c = -1)
-    : tree_array_list (row, l, c)
+  tree_cell (tree_argument_list *row = nullptr)
+    : tree_array_list (row)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_cell)
--- a/libinterp/parse-tree/pt-check.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-check.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -85,7 +85,7 @@
 
   if (lhs)
     {
-      int len = lhs->length ();
+      int len = lhs->size ();
 
       if (len == 0 || len > 2)
         errmsg ("invalid number of output arguments in for command",
--- a/libinterp/parse-tree/pt-classdef.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-classdef.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -29,6 +29,7 @@
 
 #include <iostream>
 
+#include "comment-list.h"
 #include "ov.h"
 #include "ov-classdef.h"
 #include "pt-args-block.h"
@@ -40,9 +41,7 @@
 tree_superclass_ref *
 tree_superclass_ref::dup (symbol_scope&) const
 {
-  tree_superclass_ref *new_scr
-    = new tree_superclass_ref (m_method_name, m_class_name,
-                               line (), column ());
+  tree_superclass_ref *new_scr = new tree_superclass_ref (m_method_name, m_class_name, m_token);
 
   new_scr->copy_base (*this);
 
@@ -52,8 +51,7 @@
 octave_value_list
 tree_superclass_ref::evaluate_n (tree_evaluator& tw, int nargout)
 {
-  octave_value tmp
-    = octave_classdef::superclass_ref (m_method_name, m_class_name);
+  octave_value tmp = octave_classdef::superclass_ref (m_method_name, m_class_name);
 
   if (! is_postfix_indexed ())
     {
@@ -77,8 +75,7 @@
 tree_metaclass_query *
 tree_metaclass_query::dup (symbol_scope&) const
 {
-  tree_metaclass_query *new_mcq
-    = new tree_metaclass_query (m_class_name, line (), column ());
+  tree_metaclass_query *new_mcq = new tree_metaclass_query (m_class_name, m_token);
 
   new_mcq->copy_base (*this);
 
@@ -121,33 +118,39 @@
 
 // Classdef property
 
-std::string
-check_for_doc_string (comment_list *comments)
+static std::string
+check_for_doc_string (const comment_list& comments)
 {
-  // If the comment list ends in a block comment or full-line comment,
-  // then it is the doc string for this property.
+  if (! comments.empty ())
+    {
+      // If the comment list ends in a block comment or full-line
+      // comment, then it is the doc string for this property.
 
-  if (comments)
-    {
-      comment_elt last_elt = comments->back ();
+      comment_elt last_elt = comments.back ();
 
-      if (last_elt.is_block () || last_elt.is_full_line ())
+      if (! last_elt.is_copyright ()
+          && (last_elt.is_block () || last_elt.is_full_line ()))
         return last_elt.text ();
     }
 
   return "";
 }
 
-tree_classdef_property::tree_classdef_property (tree_arg_validation *av,
-    comment_list *comments)
-  : m_av (av), m_comments (comments),
-    m_doc_string (check_for_doc_string (m_comments))
+tree_classdef_property::tree_classdef_property (tree_arg_validation *av)
+  : m_av (av), m_doc_string (check_for_doc_string (leading_comments ()))
 { }
 
 tree_classdef_property::~tree_classdef_property ()
 {
   delete m_av;
-  delete m_comments;
+}
+
+comment_list
+tree_classdef_property::leading_comments ()
+{
+  tree_identifier *id = ident ();
+
+  return id->leading_comments ();
 }
 
 tree_identifier *
@@ -178,21 +181,19 @@
 
 // Classdef properties_block
 
-// Classdef methods_list
+// Classdef method_list
 
 // Classdef methods_block
 
 // Classdef event
 
-tree_classdef_event::tree_classdef_event (tree_identifier *i,
-    comment_list *comments)
-  : m_id (i), m_comments (comments),
-    m_doc_string (check_for_doc_string (m_comments))
+tree_classdef_event::tree_classdef_event (tree_identifier *i)
+  : m_id (i)
 { }
 
-// Classdef events_list
+// Classdef event_list
 
-tree_classdef_events_list::~tree_classdef_events_list ()
+tree_classdef_event_list::~tree_classdef_event_list ()
 {
   while (! empty ())
     {
@@ -206,11 +207,8 @@
 
 // Classdef enum
 
-tree_classdef_enum::tree_classdef_enum (tree_identifier *i,
-                                        tree_expression *e,
-                                        comment_list *comments)
-  : m_id (i), m_expr (e), m_comments (comments),
-    m_doc_string (check_for_doc_string (m_comments))
+tree_classdef_enum::tree_classdef_enum (tree_identifier *i, const token& open_paren, tree_expression *e, const token& close_paren)
+  : m_id (i), m_open_paren (open_paren), m_expr (e), m_close_paren (close_paren)
 { }
 
 // Classdef enum_list
@@ -230,82 +228,55 @@
 // Classdef body
 
 tree_classdef_body::tree_classdef_body ()
-  : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst ()
+  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()
 { }
 
 tree_classdef_body::tree_classdef_body (tree_classdef_properties_block *pb)
-  : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (),
-    m_doc_string (pb ? get_doc_string (pb->leading_comment ()) : "")
+  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()
 {
   append (pb);
 }
 
 tree_classdef_body::tree_classdef_body (tree_classdef_methods_block *mb)
-  : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (),
-    m_doc_string (mb ? get_doc_string (mb->leading_comment ()) : "")
+  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()
 {
   append (mb);
 }
 
 tree_classdef_body::tree_classdef_body (tree_classdef_events_block *evb)
-  : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (),
-    m_doc_string (evb ? get_doc_string (evb->leading_comment ()) : "")
+  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()
 {
   append (evb);
 }
 
 tree_classdef_body::tree_classdef_body (tree_classdef_enum_block *enb)
-  : m_properties_lst (), m_methods_lst (), m_events_lst (), m_enum_lst (),
-    m_doc_string (enb ? get_doc_string (enb->leading_comment ()) : "")
+  : m_property_lst (), m_method_lst (), m_event_lst (), m_enum_lst ()
 {
   append (enb);
 }
 
+comment_list
+tree_classdef_body::leading_comments () const
+{
+  if (! m_all_elements.empty ())
+    {
+      tree_base_classdef_block *element = m_all_elements.front ();
+
+      if (element)
+        return element->leading_comments ();
+    }
+
+  return comment_list ();
+}
+
 tree_classdef_body::~tree_classdef_body ()
 {
-  while (! m_properties_lst.empty ())
-    {
-      auto p = m_properties_lst.begin ();
-      delete *p;
-      m_properties_lst.erase (p);
-    }
-
-  while (! m_methods_lst.empty ())
+  while (! m_all_elements.empty ())
     {
-      auto p = m_methods_lst.begin ();
+      auto p = m_all_elements.begin ();
       delete *p;
-      m_methods_lst.erase (p);
-    }
-
-  while (! m_events_lst.empty ())
-    {
-      auto p = m_events_lst.begin ();
-      delete *p;
-      m_events_lst.erase (p);
+      m_all_elements.erase (p);
     }
-
-  while (! m_enum_lst.empty ())
-    {
-      auto p = m_enum_lst.begin ();
-      delete *p;
-      m_enum_lst.erase (p);
-    }
-}
-
-std::string
-tree_classdef_body::get_doc_string (comment_list *comments) const
-{
-  // Grab the first comment from the list and use it as the doc string
-  // for this classdef body.
-
-  if (comments)
-    {
-      comment_elt first_elt = comments->front ();
-
-      return first_elt.text ();
-    }
-
-  return "";
 }
 
 // Classdef
--- a/libinterp/parse-tree/pt-classdef.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-classdef.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,35 +30,36 @@
 
 class octave_value;
 
-#include "comment-list.h"
 #include "pt-cmd.h"
+#include "pt-delimiter-list.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
 #include "pt-id.h"
-
-#include "base-list.h"
+#include "token.h"
 
 #include <list>
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class coment_list;
 class interpreter;
-
 class tree_arg_validation;
 
 class tree_superclass_ref : public tree_expression
 {
 public:
 
-  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)
+  tree_superclass_ref (const std::string& meth, const std::string& cls, const token& tok)
+    : m_method_name (meth), m_class_name (cls), m_token (tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_superclass_ref)
 
   ~tree_superclass_ref () = default;
 
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
   std::string method_name () const
   {
     return m_method_name;
@@ -91,20 +92,25 @@
   // The name of the superclass.  This is the text after the "@"
   // and may be of the form "object.method".
   std::string m_class_name;
+
+  token m_token;
 };
 
 class tree_metaclass_query : public tree_expression
 {
 public:
 
-  tree_metaclass_query (const std::string& cls, int l = -1, int c = -1)
-    : tree_expression (l, c), m_class_name (cls)
+  tree_metaclass_query (const std::string& cls, const token& tok)
+    : m_class_name (cls), m_token (tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_metaclass_query)
 
   ~tree_metaclass_query () = default;
 
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
   std::string class_name () const { return m_class_name; }
 
   tree_metaclass_query * dup (symbol_scope& scope) const;
@@ -124,19 +130,24 @@
 private:
 
   std::string m_class_name;
+
+  token m_token;
 };
 
 class tree_classdef_attribute
 {
 public:
 
-  tree_classdef_attribute (tree_identifier *i = nullptr,
-                           tree_expression *e = nullptr)
-    : m_id (i), m_expr (e), m_neg (false)
+  tree_classdef_attribute (tree_identifier *i)
+    : m_id (i)
   { }
 
-  tree_classdef_attribute (tree_identifier *i, bool b)
-    : m_id (i), m_expr (nullptr), m_neg (b)
+  tree_classdef_attribute (tree_identifier *i, const token eq_tok, tree_expression *e)
+    : m_id (i), m_eq_tok (eq_tok), m_expr (e)
+  { }
+
+  tree_classdef_attribute (const token& not_tok, tree_identifier *i, bool b)
+    : m_not_tok (not_tok), m_id (i), m_neg (b)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute)
@@ -147,6 +158,9 @@
     delete m_expr;
   }
 
+  filepos beg_pos () const { return m_not_tok ? m_not_tok.beg_pos () : m_id->beg_pos (); }
+  filepos end_pos () const { return m_expr ? m_expr->end_pos () : m_id->end_pos (); }
+
   tree_identifier * ident () { return m_id; }
 
   tree_expression * expression () { return m_expr; }
@@ -160,46 +174,60 @@
 
 private:
 
+  token m_not_tok;
   tree_identifier *m_id;
-  tree_expression *m_expr;
-  bool m_neg;
+  token m_eq_tok;
+  tree_expression *m_expr {nullptr};
+  bool m_neg {false};
 };
 
-class tree_classdef_attribute_list : public base_list<tree_classdef_attribute *>
+class tree_classdef_attribute_list : public std::list<tree_classdef_attribute *>
 {
 public:
 
   tree_classdef_attribute_list () { }
 
-  tree_classdef_attribute_list (tree_classdef_attribute *a) { append (a); }
+  tree_classdef_attribute_list (tree_classdef_attribute *a) { push_back (a); }
 
-  tree_classdef_attribute_list (const base_list<tree_classdef_attribute *>& a)
-    : base_list<tree_classdef_attribute *> (a)
+  tree_classdef_attribute_list (const std::list<tree_classdef_attribute *>& a)
+    : std::list<tree_classdef_attribute *> (a)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_attribute_list)
 
   ~tree_classdef_attribute_list ();
 
+  tree_classdef_attribute_list * mark_in_delims (const token& open_delim, token& close_delim)
+  {
+    m_delims.push (open_delim, close_delim);
+    return this;
+  }
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_attribute_list (*this);
   }
+
+private:
+
+  tree_delimiter_list m_delims;
 };
 
 class tree_classdef_superclass
 {
 public:
 
-  tree_classdef_superclass (const std::string& cname)
-    : m_cls_name (cname)
+  tree_classdef_superclass (const token& fqident)
+    : m_fqident (fqident)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_superclass)
 
   ~tree_classdef_superclass () = default;
 
-  std::string class_name () { return m_cls_name; }
+  void set_separator (const token& sep_tok) { m_sep_tok = sep_tok; }
+
+  std::string class_name () { return m_fqident.text (); }
 
   void accept (tree_walker& tw)
   {
@@ -208,11 +236,17 @@
 
 private:
 
-  std::string m_cls_name;
+  // The '<' or '&&' token introducing an element of a superclass list
+  // element.  Is there a better name for it?
+
+  token m_sep_tok;
+
+  // The fully-qualified identifier token for this superclass element.
+  token m_fqident;
 };
 
 class tree_classdef_superclass_list
-  : public base_list<tree_classdef_superclass *>
+  : public std::list<tree_classdef_superclass *>
 {
 public:
 
@@ -220,11 +254,11 @@
 
   tree_classdef_superclass_list (tree_classdef_superclass *sc)
   {
-    append (sc);
+    push_back (sc);
   }
 
-  tree_classdef_superclass_list (const base_list<tree_classdef_superclass *>& a)
-    : base_list<tree_classdef_superclass *> (a)
+  tree_classdef_superclass_list (const std::list<tree_classdef_superclass *>& a)
+    : std::list<tree_classdef_superclass *> (a)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_superclass_list)
@@ -237,76 +271,87 @@
   }
 };
 
-template <typename T>
-class tree_classdef_element : public tree
+class tree_base_classdef_block : public tree
 {
 public:
 
-  tree_classdef_element (tree_classdef_attribute_list *a, T *elt_list,
-                         comment_list *lc, comment_list *tc,
-                         int l = -1, int c = -1)
-    : tree (l, c), m_attr_list (a), m_elt_list (elt_list),
-      m_lead_comm (lc), m_trail_comm (tc)
+  tree_base_classdef_block (const token& block_tok, tree_classdef_attribute_list *a, const token& end_tok)
+    : m_block_tok (block_tok), m_attr_list (a), m_end_tok (end_tok)
   { }
 
-  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_element)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_base_classdef_block)
 
-  ~tree_classdef_element ()
+  ~tree_base_classdef_block ()
   {
     delete m_attr_list;
-    delete m_elt_list;
-    delete m_lead_comm;
-    delete m_trail_comm;
   }
 
+  comment_list leading_comments () const { return m_block_tok.leading_comments (); }
+
   tree_classdef_attribute_list * attribute_list () { return m_attr_list; }
 
-  T * element_list () { return m_elt_list; }
-
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
-
   void accept (tree_walker&) { }
 
-private:
+protected:
+
+  token m_block_tok;
 
   // List of attributes that apply to this class.
   tree_classdef_attribute_list *m_attr_list;
 
-  // The list of objects contained in this block.
-  T *m_elt_list;
+  token m_end_tok;
+};
+
+template <typename T>
+class tree_classdef_block : public tree_base_classdef_block
+{
+public:
+
+  tree_classdef_block (const token& block_tok, tree_classdef_attribute_list *a, T *elt_list, const token& end_tok)
+    : tree_base_classdef_block (block_tok, a, end_tok), m_elt_list (elt_list)
+  { }
+
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_block)
 
-  // Comments preceding the token marking the beginning of the block.
-  comment_list *m_lead_comm;
+  ~tree_classdef_block ()
+  {
+    delete m_elt_list;
+  }
+
+  filepos beg_pos () const { return m_block_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
 
-  // Comments preceding the END token marking the end of the block.
-  comment_list *m_trail_comm;
+  T * element_list () { return m_elt_list; }
+
+private:
+
+  T *m_elt_list;
 };
 
+// FIXME: should this class be derived from tree?
+
 class tree_classdef_property
 {
 public:
 
-  tree_classdef_property (tree_arg_validation *av,
-                          comment_list *comments = nullptr);
+  tree_classdef_property (tree_arg_validation *av);
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_property)
 
   ~tree_classdef_property ();
 
-  tree_identifier * ident ();
-
-  tree_expression * expression ();
+  comment_list leading_comments ();
 
-  comment_list * comments () const { return m_comments; }
-
-  void doc_string (const std::string& txt) { m_doc_string = txt; }
+  void doc_string (const std::string& s) { m_doc_string = s; }
 
   std::string doc_string () const { return m_doc_string; }
 
   bool have_doc_string () const { return ! m_doc_string.empty (); }
 
+  tree_identifier * ident ();
+
+  tree_expression * expression ();
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_property (*this);
@@ -315,20 +360,20 @@
 private:
 
   tree_arg_validation *m_av;
-  comment_list *m_comments;
+
   std::string m_doc_string;
 };
 
-class tree_classdef_property_list : public base_list<tree_classdef_property *>
+class tree_classdef_property_list : public std::list<tree_classdef_property *>
 {
 public:
 
   tree_classdef_property_list () { }
 
-  tree_classdef_property_list (tree_classdef_property *p) { append (p); }
+  tree_classdef_property_list (tree_classdef_property *p) { push_back (p); }
 
-  tree_classdef_property_list (const base_list<tree_classdef_property *>& a)
-    : base_list<tree_classdef_property *> (a) { }
+  tree_classdef_property_list (const std::list<tree_classdef_property *>& a)
+    : std::list<tree_classdef_property *> (a) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_property_list)
 
@@ -340,65 +385,61 @@
   }
 };
 
-class tree_classdef_properties_block
-  : public tree_classdef_element<tree_classdef_property_list>
+class tree_classdef_properties_block : public tree_classdef_block<tree_classdef_property_list>
 {
 public:
 
-  tree_classdef_properties_block (tree_classdef_attribute_list *a,
-                                  tree_classdef_property_list *plist,
-                                  comment_list *lc, comment_list *tc,
-                                  int l = -1, int c = -1)
-    : tree_classdef_element<tree_classdef_property_list> (a, plist, lc, tc, l, c)
+  tree_classdef_properties_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_property_list *plist, const token& end_tok)
+    : tree_classdef_block<tree_classdef_property_list> (block_tok, a, plist, end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_properties_block)
 
   ~tree_classdef_properties_block () = default;
 
+  tree_classdef_property_list * property_list () { return element_list (); }
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_properties_block (*this);
   }
 };
 
-class tree_classdef_methods_list : public base_list<octave_value>
+class tree_classdef_method_list : public std::list<octave_value>
 {
 public:
 
-  tree_classdef_methods_list () { }
+  tree_classdef_method_list () { }
 
-  tree_classdef_methods_list (const octave_value& f) { append (f); }
+  tree_classdef_method_list (const octave_value& f) { push_back (f); }
 
-  tree_classdef_methods_list (const base_list<octave_value>& a)
-    : base_list<octave_value> (a) { }
+  tree_classdef_method_list (const std::list<octave_value>& a)
+    : std::list<octave_value> (a) { }
 
-  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_methods_list)
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_method_list)
 
-  ~tree_classdef_methods_list () = default;
+  ~tree_classdef_method_list () = default;
 
   void accept (tree_walker& tw)
   {
-    tw.visit_classdef_methods_list (*this);
+    tw.visit_classdef_method_list (*this);
   }
 };
 
-class tree_classdef_methods_block
-  : public tree_classdef_element<tree_classdef_methods_list>
+class tree_classdef_methods_block : public tree_classdef_block<tree_classdef_method_list>
 {
 public:
 
-  tree_classdef_methods_block (tree_classdef_attribute_list *a,
-                               tree_classdef_methods_list *mlist,
-                               comment_list *lc, comment_list *tc,
-                               int l = -1, int c = -1)
-    : tree_classdef_element<tree_classdef_methods_list> (a, mlist, lc, tc, l, c)
+  tree_classdef_methods_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_method_list *mlist, const token& end_tok)
+    : tree_classdef_block<tree_classdef_method_list> (block_tok, a, mlist, end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_methods_block)
 
   ~tree_classdef_methods_block () = default;
 
+  tree_classdef_method_list * method_list () { return element_list (); }
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_methods_block (*this);
@@ -409,27 +450,17 @@
 {
 public:
 
-  tree_classdef_event (tree_identifier *i = nullptr,
-                       comment_list *comments = nullptr);
+  tree_classdef_event (tree_identifier *i = nullptr);
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_event)
 
   ~tree_classdef_event ()
   {
     delete m_id;
-    delete m_comments;
   }
 
   tree_identifier * ident () { return m_id; }
 
-  comment_list * comments () const { return m_comments; }
-
-  void doc_string (const std::string& txt) { m_doc_string = txt; }
-
-  std::string doc_string () const { return m_doc_string; }
-
-  bool have_doc_string () const { return ! m_doc_string.empty (); }
-
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_event (*this);
@@ -438,48 +469,44 @@
 private:
 
   tree_identifier *m_id;
-  comment_list *m_comments;
-  std::string m_doc_string;
 };
 
-class tree_classdef_events_list : public base_list<tree_classdef_event *>
+class tree_classdef_event_list : public std::list<tree_classdef_event *>
 {
 public:
 
-  tree_classdef_events_list () { }
+  tree_classdef_event_list () { }
 
-  tree_classdef_events_list (tree_classdef_event *e) { append (e); }
+  tree_classdef_event_list (tree_classdef_event *e) { push_back (e); }
 
-  tree_classdef_events_list (const base_list<tree_classdef_event *>& a)
-    : base_list<tree_classdef_event *> (a)
+  tree_classdef_event_list (const std::list<tree_classdef_event *>& a)
+    : std::list<tree_classdef_event *> (a)
   { }
 
-  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_events_list)
+  OCTAVE_DISABLE_COPY_MOVE (tree_classdef_event_list)
 
-  ~tree_classdef_events_list ();
+  ~tree_classdef_event_list ();
 
   void accept (tree_walker& tw)
   {
-    tw.visit_classdef_events_list (*this);
+    tw.visit_classdef_event_list (*this);
   }
 };
 
-class tree_classdef_events_block
-  : public tree_classdef_element<tree_classdef_events_list>
+class tree_classdef_events_block : public tree_classdef_block<tree_classdef_event_list>
 {
 public:
 
-  tree_classdef_events_block (tree_classdef_attribute_list *a,
-                              tree_classdef_events_list *elist,
-                              comment_list *lc, comment_list *tc,
-                              int l = -1, int c = -1)
-    : tree_classdef_element<tree_classdef_events_list> (a, elist, lc, tc, l, c)
+  tree_classdef_events_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_event_list *elist, const token& end_tok)
+    : tree_classdef_block<tree_classdef_event_list> (block_tok, a, elist, end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_events_block)
 
   ~tree_classdef_events_block () = default;
 
+  tree_classdef_event_list * event_list () { return element_list (); }
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_events_block (*this);
@@ -490,8 +517,7 @@
 {
 public:
 
-  tree_classdef_enum (tree_identifier *i, tree_expression *e,
-                      comment_list *comments);
+  tree_classdef_enum (tree_identifier *i, const token& open_paren, tree_expression *e, const token& close_paren);
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum)
 
@@ -499,20 +525,15 @@
   {
     delete m_id;
     delete m_expr;
-    delete m_comments;
   }
 
   tree_identifier * ident () { return m_id; }
 
+  token open_paren () const { return m_open_paren; }
+
   tree_expression * expression () { return m_expr; }
 
-  comment_list * comments () const { return m_comments; }
-
-  void doc_string (const std::string& txt) { m_doc_string = txt; }
-
-  std::string doc_string () const { return m_doc_string; }
-
-  bool have_doc_string () const { return ! m_doc_string.empty (); }
+  token close_paren () const { return m_close_paren; }
 
   void accept (tree_walker& tw)
   {
@@ -522,21 +543,21 @@
 private:
 
   tree_identifier *m_id;
+  token m_open_paren;
   tree_expression *m_expr;
-  comment_list *m_comments;
-  std::string m_doc_string;
+  token m_close_paren;
 };
 
-class tree_classdef_enum_list : public base_list<tree_classdef_enum *>
+class tree_classdef_enum_list : public std::list<tree_classdef_enum *>
 {
 public:
 
   tree_classdef_enum_list () { }
 
-  tree_classdef_enum_list (tree_classdef_enum *e) { append (e); }
+  tree_classdef_enum_list (tree_classdef_enum *e) { push_back (e); }
 
-  tree_classdef_enum_list (const base_list<tree_classdef_enum *>& a)
-    : base_list<tree_classdef_enum *> (a)
+  tree_classdef_enum_list (const std::list<tree_classdef_enum *>& a)
+    : std::list<tree_classdef_enum *> (a)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_classdef_enum_list)
@@ -549,49 +570,43 @@
   }
 };
 
-class tree_classdef_enum_block
-  : public tree_classdef_element<tree_classdef_enum_list>
+class tree_classdef_enum_block : public tree_classdef_block<tree_classdef_enum_list>
 {
 public:
 
-  tree_classdef_enum_block (tree_classdef_attribute_list *a,
-                            tree_classdef_enum_list *elist,
-                            comment_list *lc, comment_list *tc,
-                            int l = -1, int c = -1)
-    : tree_classdef_element<tree_classdef_enum_list> (a, elist, lc, tc, l, c)
+  tree_classdef_enum_block (const token& block_tok, tree_classdef_attribute_list *a, tree_classdef_enum_list *elist, const token& end_tok)
+    : tree_classdef_block<tree_classdef_enum_list> (block_tok, a, elist, end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef_enum_block)
 
   ~tree_classdef_enum_block () = default;
 
+  tree_classdef_enum_list * enum_list () { return element_list (); }
+
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_enum_block (*this);
   }
 };
 
+// FIXME: should this class be derived from tree?
+
 class tree_classdef_body
 {
 public:
 
-  typedef std::list<tree_classdef_properties_block *>::iterator
-    properties_list_iterator;
-  typedef std::list<tree_classdef_properties_block *>::const_iterator
-    properties_list_const_iterator;
+  typedef std::list<tree_classdef_properties_block *>::iterator property_list_iterator;
+  typedef std::list<tree_classdef_properties_block *>::const_iterator property_list_const_iterator;
 
-  typedef std::list<tree_classdef_methods_block *>::iterator
-    methods_list_iterator;
-  typedef std::list<tree_classdef_methods_block *>::const_iterator
-    methods_list_const_iterator;
+  typedef std::list<tree_classdef_methods_block *>::iterator method_list_iterator;
+  typedef std::list<tree_classdef_methods_block *>::const_iterator method_list_const_iterator;
 
-  typedef std::list<tree_classdef_events_block *>::iterator events_list_iterator;
-  typedef std::list<tree_classdef_events_block *>::const_iterator
-    events_list_const_iterator;
+  typedef std::list<tree_classdef_events_block *>::iterator event_list_iterator;
+  typedef std::list<tree_classdef_events_block *>::const_iterator event_list_const_iterator;
 
   typedef std::list<tree_classdef_enum_block *>::iterator enum_list_iterator;
-  typedef std::list<tree_classdef_enum_block *>::const_iterator
-    enum_list_const_iterator;
+  typedef std::list<tree_classdef_enum_block *>::const_iterator enum_list_const_iterator;
 
   tree_classdef_body ();
 
@@ -607,39 +622,49 @@
 
   ~tree_classdef_body ();
 
-  void append (tree_classdef_properties_block *pb)
+  comment_list leading_comments () const;
+
+  tree_classdef_body * append (tree_classdef_properties_block *pb)
   {
-    m_properties_lst.push_back (pb);
+    m_property_lst.push_back (pb);
+    m_all_elements.push_back (pb);
+    return this;
   }
 
-  void append (tree_classdef_methods_block *mb)
+  tree_classdef_body * append (tree_classdef_methods_block *mb)
   {
-    m_methods_lst.push_back (mb);
-  }
-
-  void append (tree_classdef_events_block *evb)
-  {
-    m_events_lst.push_back (evb);
+    m_method_lst.push_back (mb);
+    m_all_elements.push_back (mb);
+    return this;
   }
 
-  void append (tree_classdef_enum_block *enb)
+  tree_classdef_body * append (tree_classdef_events_block *evb)
+  {
+    m_event_lst.push_back (evb);
+    m_all_elements.push_back (evb);
+    return this;
+  }
+
+  tree_classdef_body * append (tree_classdef_enum_block *enb)
   {
     m_enum_lst.push_back (enb);
+    m_all_elements.push_back (enb);
+    return this;
   }
 
-  std::list<tree_classdef_properties_block *> properties_list ()
+  std::list<tree_classdef_properties_block *> property_list ()
   {
-    return m_properties_lst;
+    return m_property_lst;
   }
 
-  std::list<tree_classdef_methods_block *> methods_list ()
+  std::list<tree_classdef_methods_block *> method_list ()
   {
-    return m_methods_lst;
+    return m_method_lst;
   }
 
-  std::list<tree_classdef_events_block *> events_list ()
+  std::list<tree_classdef_events_block *> event_list ()
   {
-    return m_events_lst;
+    return m_event_lst;
   }
 
   std::list<tree_classdef_enum_block *> enum_list ()
@@ -647,12 +672,6 @@
     return m_enum_lst;
   }
 
-  void doc_string (const std::string& txt) { m_doc_string = txt; }
-
-  std::string doc_string () const { return m_doc_string; }
-
-  bool have_doc_string () const { return ! m_doc_string.empty (); }
-
   void accept (tree_walker& tw)
   {
     tw.visit_classdef_body (*this);
@@ -660,17 +679,15 @@
 
 private:
 
-  std::string get_doc_string (comment_list *comment) const;
-
-  std::list<tree_classdef_properties_block *> m_properties_lst;
+  std::list<tree_classdef_properties_block *> m_property_lst;
 
-  std::list<tree_classdef_methods_block *> m_methods_lst;
+  std::list<tree_classdef_methods_block *> m_method_lst;
 
-  std::list<tree_classdef_events_block *> m_events_lst;
+  std::list<tree_classdef_events_block *> m_event_lst;
 
   std::list<tree_classdef_enum_block *> m_enum_lst;
 
-  std::string m_doc_string;
+  std::list<tree_base_classdef_block *> m_all_elements;
 };
 
 // Classdef definition.
@@ -679,17 +696,11 @@
 {
 public:
 
-  tree_classdef (const symbol_scope& scope, const std::string& help_text,
-                 tree_classdef_attribute_list *a, tree_identifier *i,
-                 tree_classdef_superclass_list *sc,
-                 tree_classdef_body *b, comment_list *lc,
-                 comment_list *tc, const std::string& pn = "",
-                 const std::string& fn = "", int l = -1, int c = -1)
-    : tree_command (l, c), m_scope (scope), m_help_text (help_text),
-      m_attr_list (a), m_id (i),
-      m_supclass_list (sc), m_element_list (b), m_lead_comm (lc),
-      m_trail_comm (tc), m_pack_name (pn), m_file_name (fn)
-  { }
+  tree_classdef (const symbol_scope& scope, const token& cdef_tok, tree_classdef_attribute_list *a, tree_identifier *i, tree_classdef_superclass_list *sc, tree_classdef_body *b, const token& end_tok, const std::string& pn = "", const std::string& fn = "")
+    : m_scope (scope), m_cdef_tok (cdef_tok), m_attr_list (a), m_id (i), m_supclass_list (sc), m_body (b), m_end_tok (end_tok), m_pack_name (pn), m_file_name (fn)
+  {
+    cache_doc_string ();
+  }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_classdef)
 
@@ -698,11 +709,12 @@
     delete m_attr_list;
     delete m_id;
     delete m_supclass_list;
-    delete m_element_list;
-    delete m_lead_comm;
-    delete m_trail_comm;
+    delete m_body;
   }
 
+  filepos beg_pos () const { return m_cdef_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   symbol_scope scope () { return m_scope; }
 
   tree_classdef_attribute_list *
@@ -713,10 +725,9 @@
   tree_classdef_superclass_list *
   superclass_list () { return m_supclass_list; }
 
-  tree_classdef_body * body () { return m_element_list; }
+  tree_classdef_body * body () { return m_body; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-  comment_list * trailing_comment () { return m_trail_comm; }
+  comment_list leading_comments () const { return m_cdef_tok.leading_comments (); }
 
   std::string package_name () const { return m_pack_name; }
 
@@ -725,10 +736,7 @@
   octave_value make_meta_class (interpreter& interp,
                                 bool is_at_folder = false);
 
-  std::string doc_string () const
-  {
-    return m_help_text;
-  }
+  std::string doc_string () const { return m_doc_string; }
 
   void accept (tree_walker& tw)
   {
@@ -737,13 +745,31 @@
 
 private:
 
+  void cache_doc_string ()
+  {
+    // First non-copyright comments found above and below classdef
+    // keyword are candidates for the documentation string.  Use the
+    // first one that is not empty.
+
+    comment_list comments = m_cdef_tok.leading_comments ();
+
+    m_doc_string = comments.find_doc_string ();
+
+    if (m_doc_string.empty ())
+      {
+        comments = m_body->leading_comments ();
+
+        m_doc_string = comments.find_doc_string ();
+      }
+  }
+
   // The scope that was used when parsing the classdef object and that
   // corresponds to any identifiers that were found in attribute lists
   // (for example).  Used again when computing the meta class object.
 
   symbol_scope m_scope;
 
-  std::string m_help_text;
+  token m_cdef_tok;
 
   tree_classdef_attribute_list *m_attr_list;
 
@@ -751,10 +777,11 @@
 
   tree_classdef_superclass_list *m_supclass_list;
 
-  tree_classdef_body *m_element_list;
+  tree_classdef_body *m_body;
 
-  comment_list *m_lead_comm;
-  comment_list *m_trail_comm;
+  token m_end_tok;
+
+  std::string m_doc_string;
 
   std::string m_pack_name;
   std::string m_file_name;
@@ -763,3 +790,4 @@
 OCTAVE_END_NAMESPACE(octave)
 
 #endif
+
--- a/libinterp/parse-tree/pt-cmd.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-cmd.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,10 +30,13 @@
 
 #include <string>
 
+#include "comment-list.h"
 #include "ov-fcn.h"
 #include "pt.h"
 #include "pt-bp.h"
 #include "pt-walk.h"
+#include "panic.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -43,12 +46,13 @@
 {
 public:
 
-  tree_command (int l = -1, int c = -1)
-    : tree (l, c) { }
+  tree_command () = default;
 
   OCTAVE_DISABLE_COPY_MOVE (tree_command)
 
   virtual ~tree_command () = default;
+
+  virtual void update_end_pos (const filepos&) { panic_impossible (); }
 };
 
 // No-op.
@@ -57,14 +61,37 @@
 {
 public:
 
-  tree_no_op_command (const std::string& cmd = "no_op", bool e = false,
-                      int l = -1, int c = -1)
-    : tree_command (l, c), m_eof (e), m_orig_cmd (cmd) { }
+  tree_no_op_command (const std::string& cmd, bool eof, const token& tok)
+    : m_eof (eof), m_tok (tok), m_orig_cmd (cmd)
+  { }
 
-  OCTAVE_DISABLE_COPY_MOVE (tree_no_op_command)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_no_op_command)
 
   ~tree_no_op_command () = default;
 
+  filepos beg_pos () const { return m_tok.beg_pos (); }
+  filepos end_pos () const { return m_tok.end_pos (); }
+
+  void update_end_pos (const filepos& pos)
+  {
+    if (is_end_of_fcn_or_script () || is_end_of_file ())
+      m_tok.end_pos (pos);
+    else
+      panic_impossible ();
+  }
+
+  comment_list leading_comments () const { return m_tok.leading_comments (); }
+
+  void attach_trailing_comments (const comment_list& lst)
+  {
+    m_tok.trailing_comments (lst);
+  }
+
+  comment_list trailing_comments () const
+  {
+    return m_tok.trailing_comments ();
+  }
+
   void accept (tree_walker& tw)
   {
     tw.visit_no_op_command (*this);
@@ -83,6 +110,9 @@
 
   bool m_eof;
 
+  // If defined, may be END token or EOF.
+  token m_tok;
+
   std::string m_orig_cmd;
 };
 
@@ -92,13 +122,24 @@
 {
 public:
 
-  tree_function_def (octave_function *f, int l = -1, int c = -1)
-    : tree_command (l, c), m_fcn (f) { }
+  tree_function_def (octave_function *f) : m_fcn (f) { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_function_def)
 
   ~tree_function_def () = default;
 
+  filepos beg_pos () const
+  {
+    octave_function *f = m_fcn.function_value ();
+    return f->beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    octave_function *f = m_fcn.function_value ();
+    return f->end_pos ();
+  }
+
   void accept (tree_walker& tw)
   {
     tw.visit_function_def (*this);
@@ -110,8 +151,7 @@
 
   octave_value m_fcn;
 
-  tree_function_def (const octave_value& v, int l = -1, int c = -1)
-    : tree_command (l, c), m_fcn (v) { }
+  tree_function_def (const octave_value& v) : m_fcn (v) { }
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-colon.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-colon.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -41,10 +41,10 @@
 {
   tree_colon_expression *new_ce
     = new tree_colon_expression (m_base ? m_base->dup (scope) : nullptr,
-                                 m_limit ? m_limit->dup (scope) : nullptr,
-                                 m_increment ? m_increment->dup (scope)
-                                 : nullptr,
-                                 line (), column ());
+                                 m_colon_1_tok,
+                                 m_increment ? m_increment->dup (scope) : nullptr,
+                                 m_colon_2_tok,
+                                 m_limit ? m_limit->dup (scope) : nullptr);
 
   new_ce->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-colon.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-colon.h	Fri Apr 12 15:10:26 2024 +0200
@@ -46,19 +46,13 @@
 {
 public:
 
-  tree_colon_expression (int l = -1, int c = -1)
-    : tree_expression (l, c), m_base (nullptr), m_limit (nullptr),
-      m_increment (nullptr), m_save_base (false) { }
+  tree_colon_expression (tree_expression *base, const token& colon_1_tok, tree_expression *limit)
+    : m_base (base), m_colon_1_tok (colon_1_tok), m_limit (limit)
+  { }
 
-  tree_colon_expression (tree_expression *bas, tree_expression *lim,
-                         int l = -1, int c = -1)
-    : tree_expression (l, c), m_base (bas), m_limit (lim),
-      m_increment (nullptr), m_save_base (false) { }
-
-  tree_colon_expression (tree_expression *bas, tree_expression *lim,
-                         tree_expression *inc, int l = -1, int c = -1)
-    : tree_expression (l, c), m_base (bas), m_limit (lim),
-      m_increment (inc), m_save_base (false) { }
+  tree_colon_expression (tree_expression *base, const token& colon_1_tok, tree_expression *increment, const token& colon_2_tok, tree_expression *limit)
+    : m_base (base), m_colon_1_tok (colon_1_tok), m_increment (increment), m_colon_2_tok (colon_2_tok), m_limit (limit)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_colon_expression)
 
@@ -71,6 +65,9 @@
     delete m_increment;
   }
 
+  filepos beg_pos () const { return m_base->beg_pos (); }
+  filepos end_pos () const { return m_limit->end_pos (); }
+
   void preserve_base () { m_save_base = true; }
 
   bool rvalue_ok () const { return true; }
@@ -103,10 +100,12 @@
 
   // The components of the expression.
   tree_expression *m_base;
+  token m_colon_1_tok;
+  tree_expression *m_increment {nullptr};
+  token m_colon_2_tok;
   tree_expression *m_limit;
-  tree_expression *m_increment;
 
-  bool m_save_base;
+  bool m_save_base {false};
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-const.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-const.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -63,8 +63,7 @@
 tree_expression *
 tree_constant::dup (symbol_scope&) const
 {
-  tree_constant *new_tc
-    = new tree_constant (m_value, m_orig_text, line (), column ());
+  tree_constant *new_tc = new tree_constant (m_value, m_orig_text, m_token);
 
   new_tc->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-const.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-const.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,6 +38,7 @@
 #include "pt-bp.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -48,17 +49,12 @@
 {
 public:
 
-  tree_constant (int l = -1, int c = -1)
-    : tree_expression (l, c), m_value (), m_orig_text ()
+  tree_constant (const octave_value& v, const token& tok)
+    : m_value (v), m_token (tok)
   { }
 
-  tree_constant (const octave_value& v, int l = -1, int c = -1)
-    : tree_expression (l, c), m_value (v), m_orig_text ()
-  { }
-
-  tree_constant (const octave_value& v, const std::string& ot,
-                 int l = -1, int c = -1)
-    : tree_expression (l, c), m_value (v), m_orig_text (ot)
+  tree_constant (const octave_value& v, const std::string& ot, const token& tok)
+    : m_value (v), m_orig_text (ot), m_token (tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_constant)
@@ -69,6 +65,9 @@
 
   bool is_constant () const { return true; }
 
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
   void maybe_mutate () { m_value.maybe_mutate (); }
 
   void print (std::ostream& os, bool pr_as_read_syntax = false,
@@ -115,6 +114,8 @@
 
   // The original text form of this constant.
   std::string m_orig_text;
+
+  token m_token;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-decl.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-decl.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -68,9 +68,8 @@
 
 // Declaration commands (global, static).
 
-tree_decl_command::tree_decl_command (const std::string& n,
-                                      tree_decl_init_list *t, int l, int c)
-  : tree_command (l, c), m_cmd_name (n), m_init_list (t)
+tree_decl_command::tree_decl_command (const std::string& n, const token& tok, tree_decl_init_list *t)
+  : m_cmd_name (n), m_token (tok), m_init_list (t)
 {
   if (t)
     {
--- a/libinterp/parse-tree/pt-decl.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-decl.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,7 +31,6 @@
 #include <list>
 #include <string>
 
-#include "base-list.h"
 #include "oct-lvalue.h"
 #include "pt-cmd.h"
 #include "pt-id.h"
@@ -63,6 +62,9 @@
 
   ~tree_decl_elt ();
 
+  filepos beg_pos () const { return m_id->beg_pos (); }
+  filepos end_pos () const { return m_expr ? m_expr->end_pos () : m_id->end_pos (); }
+
   void mark_as_formal_parameter ()
   {
     m_id->mark_as_formal_parameter ();
@@ -105,13 +107,13 @@
   tree_expression *m_expr;
 };
 
-class tree_decl_init_list : public base_list<tree_decl_elt *>
+class tree_decl_init_list : public std::list<tree_decl_elt *>
 {
 public:
 
   tree_decl_init_list () { }
 
-  tree_decl_init_list (tree_decl_elt *t) { append (t); }
+  tree_decl_init_list (tree_decl_elt *t) { push_back (t); }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_decl_init_list)
 
@@ -125,6 +127,24 @@
       }
   }
 
+  filepos beg_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_decl_elt *elt = front ();
+    return elt->beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_decl_elt *elt = back ();
+    return elt->end_pos ();
+  }
+
   void mark_global ()
   {
     for (tree_decl_elt *elt : *this)
@@ -164,16 +184,15 @@
 {
 public:
 
-  tree_decl_command (const std::string& n, int l = -1, int c = -1)
-    : tree_command (l, c), m_cmd_name (n), m_init_list (nullptr) { }
-
-  tree_decl_command (const std::string& n, tree_decl_init_list *t,
-                     int l = -1, int c = -1);
+  tree_decl_command (const std::string& n, const token& tok, tree_decl_init_list *t);
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_decl_command)
 
   ~tree_decl_command ();
 
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_init_list->end_pos (); }
+
   void mark_global ()
   {
     if (m_init_list)
@@ -200,6 +219,8 @@
   // The name of this command -- global, static, etc.
   std::string m_cmd_name;
 
+  token m_token;
+
   // The list of variables or initializers in this declaration command.
   tree_decl_init_list *m_init_list;
 };
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/parse-tree/pt-delimiter-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,80 @@
+////////////////////////////////////////////////////////////////////////
+//
+// Copyright (C) 2024 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_tree_delimiter_list_h)
+#define octave_tree_delimiter_list_h 1
+
+#include "octave-config.h"
+
+#include <stack>
+
+#include "filepos.h"
+#include "token.h"
+
+OCTAVE_BEGIN_NAMESPACE(octave)
+
+class tree_delimiter_list
+{
+public:
+
+  typedef std::pair<token, token> element_type;
+
+  OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (tree_delimiter_list)
+
+  size_t count () const { return m_delimiters.size (); }
+
+  bool empty () const { return m_delimiters.empty (); }
+
+  void push (const token& open_delim, const token& close_delim)
+  {
+    m_delimiters.push (element_type (open_delim, close_delim));
+  }
+
+  filepos beg_pos () const
+  {
+    if (m_delimiters.empty ())
+      return filepos ();
+
+    const element_type& elt = m_delimiters.top ();
+    return elt.first.beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (m_delimiters.empty ())
+      return filepos ();
+
+    const element_type& elt = m_delimiters.top ();
+    return elt.second.end_pos ();
+  }
+
+private:
+
+  std::stack<element_type> m_delimiters;
+};
+
+OCTAVE_END_NAMESPACE(octave)
+
+#endif
--- a/libinterp/parse-tree/pt-eval.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-eval.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -75,6 +75,12 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+OCTAVE_NORETURN static void
+error_unexpected (const char *name)
+{
+  error ("unexpected call to %s - please report this bug", name);
+}
+
 // Normal evaluator.
 
 class quit_debug_exception
@@ -675,7 +681,7 @@
       exiting = false;
 
       evmgr.post_event
-        ([&] (interpreter& interp)
+        ([this, input, &mtx, &incomplete_parse, &evaluation_pending, &cv, &exiting] (interpreter& interp)
          {
            // INTERPRETER THREAD
 
@@ -694,14 +700,14 @@
              }
            catch (const execution_exception& ee)
              {
-               error_system& es = m_interpreter.get_error_system ();
+               error_system& es = interp.get_error_system ();
 
                es.save_exception (ee);
                es.display_exception (ee);
 
-               if (m_interpreter.interactive ())
+               if (interp.interactive ())
                  {
-                   m_interpreter.recover_from_exception ();
+                   interp.recover_from_exception ();
                    m_parser->reset ();
                    evaluation_pending = false;
                    cv.notify_all ();
@@ -727,7 +733,7 @@
       // Wait until evaluation is finished before prompting for input
       // again.
 
-      cv.wait (lock, [&] { return ! evaluation_pending; });
+      cv.wait (lock, [&evaluation_pending] { return ! evaluation_pending; });
 
       if (exiting)
         break;
@@ -1050,7 +1056,7 @@
             {
               tree_statement *stmt = nullptr;
 
-              if (stmt_list->length () == 1
+              if (stmt_list->size () == 1
                   && (stmt = stmt_list->front ())
                   && stmt->is_expression ())
                 {
@@ -1177,7 +1183,7 @@
                         const std::string& try_code,
                         int nargout)
 {
-  unwind_action act ([=] (std::size_t frm)
+  unwind_action act ([this] (std::size_t frm)
                      {
                        m_call_stack.restore_frame (frm);
                      }, m_call_stack.current_frame ());
@@ -1202,7 +1208,7 @@
 {
   octave_value_list retval;
 
-  unwind_action act1 ([=] (std::size_t frm)
+  unwind_action act1 ([this] (std::size_t frm)
                       {
                         m_call_stack.restore_frame (frm);
                       }, m_call_stack.current_frame ());
@@ -1258,13 +1264,13 @@
 void
 tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_anon_fcn_handle");
 }
 
 void
 tree_evaluator::visit_argument_list (tree_argument_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_argument_list");
 }
 
 void
@@ -1276,49 +1282,49 @@
 void
 tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_args_block_attribute_list");
 }
 
 void
 tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_args_block_validation_list");
 }
 
 void
 tree_evaluator::visit_arg_validation (tree_arg_validation&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_arg_validation");
 }
 
 void
 tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_arg_size_spec");
 }
 
 void
 tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_arg_validation_fcns");
 }
 
 void
 tree_evaluator::visit_binary_expression (tree_binary_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_binary_expression");
 }
 
 void
 tree_evaluator::visit_boolean_expression (tree_boolean_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_boolean_expression");
 }
 
 void
 tree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_compound_binary_expression");
 }
 
 void
@@ -1345,7 +1351,7 @@
 void
 tree_evaluator::visit_colon_expression (tree_colon_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_colon_expression");
 }
 
 void
@@ -1417,6 +1423,14 @@
 
   // Go up to the nearest user code frame.
 
+  tree_evaluator& tw = m_interpreter.get_evaluator ();
+
+  frame.add ([&tw, saved_frame = m_debug_frame] ()
+  {
+    if (! tw.dbstep_flag ())
+      tw.debug_frame (saved_frame);
+  });
+
   m_debug_frame = m_call_stack.dbupdown (0);
 
   // FIXME: probably we just want to print one line, not the
@@ -1429,7 +1443,7 @@
 
   m_debugger_stack.push (dbgr);
 
-  frame.add ([=] ()
+  frame.add ([this] ()
              {
                delete m_debugger_stack.top ();
                m_debugger_stack.pop ();
@@ -1451,6 +1465,13 @@
   m_debug_frame = m_call_stack.dbupdown (n, verbose);
 }
 
+std::string tree_evaluator::inputname (int n, bool ids_only) const
+{
+  std::shared_ptr<stack_frame> frame = m_call_stack.current_user_frame ();
+
+  return frame->inputname (n, ids_only);
+}
+
 Matrix
 tree_evaluator::ignored_fcn_outputs () const
 {
@@ -2010,7 +2031,7 @@
   // by getting a reference to the caller or base stack frame and
   // calling assign on that?
 
-  unwind_action act ([=] (std::size_t frm)
+  unwind_action act ([this] (std::size_t frm)
                      {
                        m_call_stack.restore_frame (frm);
                      }, m_call_stack.current_frame ());
@@ -2187,7 +2208,10 @@
   code->call (*this, 0, octave_value_list ());
 
   if (verbose)
-    octave_stdout << "done." << std::endl;
+    {
+      octave_stdout << "done." << std::endl;
+      octave_stdout.flush ();
+    }
 }
 
 void
@@ -2358,7 +2382,7 @@
 (tree_parameter_list *ret_list, int nargout, const Cell& varargout)
 {
   octave_idx_type vlen = varargout.numel ();
-  int len = ret_list->length ();
+  int len = ret_list->size ();
 
   // Special case.  Will do a shallow copy.
   if (len == 0)
@@ -2539,6 +2563,28 @@
   frm->display_stopped_in_message (os);
 }
 
+void
+tree_evaluator::debug_list (std::ostream& os, int num_lines) const
+{
+  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();
+
+  if (! (frm->is_user_script_frame () || frm->is_user_fcn_frame ()))
+    error ("dblist: must be inside a user function or script to use dblist\n");
+
+  frm->debug_list (os, num_lines);
+}
+
+void
+tree_evaluator::debug_type (std::ostream& os, int start_line, int end_line) const
+{
+  std::shared_ptr<stack_frame> frm = m_call_stack.current_user_frame ();
+
+  if (! (frm->is_user_script_frame () || frm->is_user_fcn_frame ()))
+    error ("dbtype: must be inside a user function or script to use dbtype\n");
+
+  frm->debug_type (os, start_line, end_line);
+}
+
 octave_user_code *
 tree_evaluator::current_user_code () const
 {
@@ -3202,7 +3248,7 @@
       // A matrix or cell is reshaped to 2 dimensions and iterated by
       // columns.
 
-      dim_vector dv = rhs.dims ().redim (2);
+      const dim_vector& dv = rhs.dims ().redim (2);
 
       octave_idx_type nrows = dv(0);
       octave_idx_type steps = dv(1);
@@ -3211,7 +3257,7 @@
       if (rhs.ndims () > 2)
         arg = arg.reshape (dv);
 
-      if (nrows > 0 && steps > 0)
+      if (steps > 0)
         {
           octave_value_list idx;
           octave_idx_type iidx;
@@ -3373,7 +3419,7 @@
   if (expr)
     {
       tree_expression *expr_dup = expr->dup (new_scope);
-      tree_statement *stmt = new tree_statement (expr_dup, nullptr);
+      tree_statement *stmt = new tree_statement (expr_dup);
       stmt_list = new tree_statement_list (stmt);
     }
 
@@ -3394,9 +3440,7 @@
         local_vars[name] = val;
     }
 
-  octave_user_function *af
-    = new octave_user_function (new_scope, param_list_dup, ret_list,
-                                stmt_list);
+  octave_user_function *af = new octave_user_function (new_scope, nullptr, param_list_dup, ret_list, stmt_list);
 
   octave_function *curr_fcn = m_call_stack.current_function ();
 
@@ -3560,7 +3604,7 @@
 tree_evaluator::visit_octave_user_script (octave_user_script&)
 {
   // ??
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_octave_user_script");
 }
 
 octave_value_list
@@ -3615,7 +3659,7 @@
   if (param_list)
     {
       takes_varargs = param_list->takes_varargs ();
-      max_inputs = param_list->length ();
+      max_inputs = param_list->size ();
     }
 
   if (! takes_varargs && nargin > max_inputs)
@@ -3636,7 +3680,7 @@
 
   if (ret_list && ! ret_list->takes_varargs ())
     {
-      int max_outputs = ret_list->length ();
+      int max_outputs = ret_list->size ();
 
       if (nargout > max_outputs)
         {
@@ -3691,7 +3735,7 @@
 
       if (user_function.is_special_expr ())
         {
-          panic_if (cmd_list->length () != 1);
+          panic_if (cmd_list->size () != 1);
 
           tree_statement *stmt = cmd_list->front ();
 
@@ -3743,19 +3787,19 @@
 tree_evaluator::visit_octave_user_function (octave_user_function&)
 {
   // ??
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_octave_user_function");
 }
 
 void
 tree_evaluator::visit_octave_user_function_header (octave_user_function&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_octave_user_function_header");
 }
 
 void
 tree_evaluator::visit_octave_user_function_trailer (octave_user_function&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_octave_user_function_trailer");
 }
 
 void
@@ -3783,13 +3827,13 @@
 void
 tree_evaluator::visit_identifier (tree_identifier&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_identifier");
 }
 
 void
 tree_evaluator::visit_if_clause (tree_if_clause&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_if_clause");
 }
 
 void
@@ -3842,25 +3886,25 @@
 void
 tree_evaluator::visit_index_expression (tree_index_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_index_expression");
 }
 
 void
 tree_evaluator::visit_matrix (tree_matrix&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_matrix");
 }
 
 void
 tree_evaluator::visit_cell (tree_cell&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_cell");
 }
 
 void
 tree_evaluator::visit_multi_assignment (tree_multi_assignment&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_multi_assignment");
 }
 
 void
@@ -3882,31 +3926,31 @@
 void
 tree_evaluator::visit_constant (tree_constant&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_constant");
 }
 
 void
 tree_evaluator::visit_fcn_handle (tree_fcn_handle&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_fcn_handle");
 }
 
 void
 tree_evaluator::visit_parameter_list (tree_parameter_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_parameter_list");
 }
 
 void
 tree_evaluator::visit_postfix_expression (tree_postfix_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_postfix_expression");
 }
 
 void
 tree_evaluator::visit_prefix_expression (tree_prefix_expression&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_prefix_expression");
 }
 
 void
@@ -3937,7 +3981,7 @@
 void
 tree_evaluator::visit_simple_assignment (tree_simple_assignment&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_simple_assignment");
 }
 
 void
@@ -4103,13 +4147,13 @@
 void
 tree_evaluator::visit_switch_case (tree_switch_case&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_switch_case");
 }
 
 void
 tree_evaluator::visit_switch_case_list (tree_switch_case_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_switch_case_list");
 }
 
 void
@@ -4451,13 +4495,13 @@
 void
 tree_evaluator::visit_superclass_ref (tree_superclass_ref&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_superclass_ref");
 }
 
 void
 tree_evaluator::visit_metaclass_query (tree_metaclass_query&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_evaluator::visit_metaclass_query");
 }
 
 void
@@ -4784,7 +4828,7 @@
       unwind_protect_var<const std::list<octave_lvalue> *>
         upv (m_lvalue_list, nullptr);
 
-      int len = args->length ();
+      int len = args->size ();
 
       unwind_protect_var<int> upv2 (m_index_position);
       unwind_protect_var<int> upv3 (m_num_indices);
@@ -5086,13 +5130,13 @@
   if (nargin == 3)
     {
       octave_idx_type index_position
-        = args(1).xidx_type_value ("end: K must be integer value");
+        = args(1).yidx_type_value ("end: K must be integer value");
 
       if (index_position < 1)
         error ("end: K must be greater than zero");
 
       octave_idx_type num_indices
-        = args(2).xidx_type_value ("end: N must be integer value");
+        = args(2).yidx_type_value ("end: N must be integer value");
 
       if (num_indices < 1)
         error ("end: N must be greater than zero");
@@ -5124,7 +5168,7 @@
           // evaluate the partial expression that the special "end"
           // token applies to in the calling stack frame.
 
-          unwind_action act ([=] (std::size_t frm)
+          unwind_action act ([this] (std::size_t frm)
                              {
                                m_call_stack.restore_frame (frm);
                              }, m_call_stack.current_frame ());
@@ -5583,4 +5627,116 @@
 %!error echo ("on", "all", "all")
 */
 
+/*
+FIXME: Actually, it probably *isn't* worth fixing, but there is one small
+difference between Octave and Matlab.
+
+If inputname is not called from a function, Matlab walks up the stack until it
+finds some valid code and then works from there.  This could be relevant for
+mex files or anonymous functions.
+
+fcn = @(x) inputname (x);
+a = 1:4;
+arrayfun (fcn, a, 'uniformoutput', false)
+% output is {'fcn', 'a', '', ''}
+*/
+DEFMETHOD (inputname, interp, args, ,
+           doc: /* -*- texinfo -*-
+@deftypefn  {} {@var{namestr} =} inputname (@var{n})
+@deftypefnx {} {@var{namestr} =} inputname (@var{n}, @var{ids_only})
+Return the name of the @var{n}-th argument to the calling function.
+
+If the argument is not a simple variable name, return an empty string.
+Examples which will return @qcode{""} are numbers (@code{5.1}), expressions
+(@code{@var{y}/2}), and cell or structure indexing (@code{@var{c}@{1@}} or
+@code{@var{s}.@var{field}}).
+
+@code{inputname} is only useful within a function.  When used at the command
+line or within a script it always returns an empty string.
+
+By default, return an empty string if the @var{n}-th argument is not a valid
+variable name.  If the optional argument @var{ids_only} is false, return the
+text of the argument even if it is not a valid variable name.  This is an
+Octave extension that allows the programmer to view exactly how the function
+was invoked even when the inputs are complex expressions.
+@seealso{nargin, narginchk}
+@end deftypefn */)
+{
+  int nargin = args.length ();
+
+  if (nargin < 1)
+    print_usage ();
+
+  dim_vector dims = args(0).dims ();
+  if (! dims.all_ones ())
+    error ("inputname: N must be a scalar index");
+
+  int n = args(0).yint_value ("inputname: N must be a scalar index");
+
+  if (n < 1)
+    error ("inputname: N must be a scalar index");
+
+  bool ids_only = true;
+
+  if (nargin == 2)
+    ids_only = args(1).ybool_value ("inputname: IDS_ONLY must be a logical value");
+
+  // Use zero-based indexing internally.
+  return ovl (interp.inputname (n-1, ids_only));
+}
+
+/*
+%!function name = __iname1__ (arg1, arg2, arg3)
+%!  name = inputname (1);
+%!endfunction
+
+%!function name = __iname1_ID__ (arg1, arg2, arg3)
+%!  name = inputname (1, false);
+%!endfunction
+
+%!function name = __iname2__ (arg1, arg2, arg3)
+%!  name = inputname (2);
+%!endfunction
+
+%!function names = __iname3__ (arg1, arg2, arg3)
+%!  names = cell (1, 3);
+%!  for i = 1:3
+%!    names{i} = inputname (i);
+%!  endfor
+%!endfunction
+
+%!test
+%! assert (__iname1__ ('xvar'), "");
+%! xvar = 1;
+%! assert (__iname1__ (xvar), "xvar");
+
+%!test
+%! xvar = 1;  yvar = 2;
+%! assert (__iname2__ (xvar), "");
+%! assert (__iname2__ (xvar, yvar), "yvar");
+
+%!test
+%! xvar = 1;  yvar = 2;
+%! assert (__iname3__ (xvar), {"xvar", "", ""});
+%! assert (__iname3__ (xvar, yvar), {"xvar", "yvar", ""});
+%! assert (__iname3__ (xvar, 3, yvar), {"xvar", "", "yvar"});
+
+## Test numbers, expressions, indexing operations
+%!test
+%! assert (__iname1__ (1.0), "");
+%! x = 1;
+%! assert (__iname1__ (x / 2), "");
+%! assert (__iname1__ (Inf), "");
+
+%!test
+%! assert (__iname1_ID__ (1.0), "1.0");
+%! x = 1;
+%! assert (__iname1_ID__ (x / 2), "x / 2");
+%! assert (__iname1_ID__ (Inf), "Inf");
+
+%!error <Invalid call> inputname ()
+%!error <N must be a scalar> inputname (ones (2,2))
+%!error <N must be a scalar index> inputname (-1)
+*/
+
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-eval.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-eval.h	Fri Apr 12 15:10:26 2024 +0200
@@ -346,6 +346,8 @@
 
   Matrix ignored_fcn_outputs () const;
 
+  std::string inputname (int n, bool ids_only = true) const;
+
   octave_value make_fcn_handle (const std::string& nm);
 
   octave_value evaluate (tree_decl_elt *);
@@ -464,6 +466,10 @@
 
   void debug_where (std::ostream& os) const;
 
+  void debug_list (std::ostream& os, int num_lines) const;
+
+  void debug_type (std::ostream& os, int start_line, int end_line) const;
+
   octave_user_code * current_user_code () const;
 
   unwind_protect * curr_fcn_unwind_protect_frame ();
--- a/libinterp/parse-tree/pt-except.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-except.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -52,9 +52,6 @@
   delete m_expr_id;
   delete m_try_code;
   delete m_catch_code;
-  delete m_lead_comm;
-  delete m_mid_comm;
-  delete m_trail_comm;
 }
 
 // Simple exception handling.
@@ -63,9 +60,6 @@
 {
   delete m_unwind_protect_code;
   delete m_cleanup_code;
-  delete m_lead_comm;
-  delete m_mid_comm;
-  delete m_trail_comm;
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-except.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-except.h	Fri Apr 12 15:10:26 2024 +0200
@@ -43,38 +43,23 @@
 {
 public:
 
-  tree_try_catch_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_try_code (nullptr), m_catch_code (nullptr),
-      m_expr_id (nullptr), m_lead_comm (nullptr), m_mid_comm (nullptr),
-      m_trail_comm (nullptr)
-  { }
-
-  tree_try_catch_command (tree_statement_list *tc, tree_statement_list *cc,
-                          tree_identifier *id,
-                          comment_list *cl = nullptr,
-                          comment_list *cm = nullptr,
-                          comment_list *ct = nullptr,
-                          int l = -1, int c = -1)
-    : tree_command (l, c), m_try_code (tc), m_catch_code (cc),
-      m_expr_id (id), m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct)
+  tree_try_catch_command (const token try_tok, tree_statement_list *tc, const token catch_tok, tree_identifier *id, tree_statement_list *cc, const token& end_tok)
+    : m_try_tok (try_tok), m_try_code (tc), m_catch_tok (catch_tok), m_expr_id (id), m_catch_code (cc), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_try_catch_command)
 
   ~tree_try_catch_command ();
 
+  filepos beg_pos () const { return m_try_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_identifier * identifier () { return m_expr_id; }
 
   tree_statement_list * body () { return m_try_code; }
 
   tree_statement_list * cleanup () { return m_catch_code; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * middle_comment () { return m_mid_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
-
   void accept (tree_walker& tw)
   {
     tw.visit_try_catch_command (*this);
@@ -82,23 +67,20 @@
 
 private:
 
+  token m_try_tok;
+
   // The first block of code to attempt to execute.
   tree_statement_list *m_try_code;
 
-  // The code to execute if an error occurs in the first block.
-  tree_statement_list *m_catch_code;
+  token m_catch_tok;
 
   // Identifier to modify.
   tree_identifier *m_expr_id;
 
-  // Comment preceding TRY token.
-  comment_list *m_lead_comm;
+  // The code to execute if an error occurs in the first block.
+  tree_statement_list *m_catch_code;
 
-  // Comment preceding CATCH token.
-  comment_list *m_mid_comm;
-
-  // Comment preceding END_TRY_CATCH token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 // Simple exception handling.
@@ -107,36 +89,21 @@
 {
 public:
 
-  tree_unwind_protect_command (int l = -1, int c = -1)
-    : tree_command (l, c),
-      m_unwind_protect_code (nullptr), m_cleanup_code (nullptr),
-      m_lead_comm (nullptr), m_mid_comm (nullptr), m_trail_comm (nullptr)
-  { }
-
-  tree_unwind_protect_command (tree_statement_list *tc,
-                               tree_statement_list *cc,
-                               comment_list *cl = nullptr,
-                               comment_list *cm = nullptr,
-                               comment_list *ct = nullptr,
-                               int l = -1, int c = -1)
-    : tree_command (l, c), m_unwind_protect_code (tc), m_cleanup_code (cc),
-      m_lead_comm (cl), m_mid_comm (cm), m_trail_comm (ct)
+  tree_unwind_protect_command (const token& unwind_tok, tree_statement_list *tc, const token& cleanup_tok, tree_statement_list *cc, const token& end_tok)
+    : m_unwind_tok (unwind_tok), m_unwind_protect_code (tc), m_cleanup_tok (cleanup_tok), m_cleanup_code (cc), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_unwind_protect_command)
 
   ~tree_unwind_protect_command ();
 
+  filepos beg_pos () const { return m_unwind_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_statement_list * body () { return m_unwind_protect_code; }
 
   tree_statement_list * cleanup () { return m_cleanup_code; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * middle_comment () { return m_mid_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
-
   void accept (tree_walker& tw)
   {
     tw.visit_unwind_protect_command (*this);
@@ -144,21 +111,18 @@
 
 private:
 
+  token m_unwind_tok;
+
   // The first body of code to attempt to execute.
   tree_statement_list *m_unwind_protect_code;
 
+  token m_cleanup_tok;
+
   // The body of code to execute no matter what happens in the first
   // body of code.
   tree_statement_list *m_cleanup_code;
 
-  // Comment preceding UNWIND_PROTECT token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding UNWIND_PROTECT_CLEANUP token.
-  comment_list *m_mid_comm;
-
-  // Comment preceding END_UNWIND_PROTECT token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-exp.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-exp.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,7 +34,9 @@
 class octave_value;
 
 #include "pt.h"
+#include "pt-delimiter-list.h"
 #include "pt-eval.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -47,9 +49,9 @@
 {
 public:
 
-  tree_expression (int l = -1, int c = -1)
-    : tree (l, c), m_num_parens (0), m_postfix_index_type ('\0'),
-      m_for_cmd_expr (false), m_print_flag (false) { }
+  tree_expression ()
+    : m_postfix_index_type ('\0'), m_for_cmd_expr (false), m_print_flag (false)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_expression)
 
@@ -85,7 +87,14 @@
 
   virtual octave_lvalue lvalue (tree_evaluator&);
 
-  int paren_count () const { return m_num_parens; }
+  // The number of times this expression appears directly inside a set
+  // of delimiters.
+  //
+  //   (([e1]) + e2)  ==> 2 for expression e1
+  //                  ==> 1 for expression ([e1]) + e2
+  //                  ==> 0 for expression e2
+
+  size_t delim_count () const { return m_delims.count (); }
 
   bool is_postfix_indexed () const
   { return (m_postfix_index_type != '\0'); }
@@ -107,9 +116,9 @@
 
   bool is_for_cmd_expr () const { return m_for_cmd_expr; }
 
-  tree_expression * mark_in_parens ()
+  tree_expression * mark_in_delims (const token& open_delim, const token& close_delim)
   {
-    m_num_parens++;
+    m_delims.push (open_delim, close_delim);
     return this;
   }
 
@@ -127,9 +136,9 @@
 
   virtual void copy_base (const tree_expression& e)
   {
-    m_num_parens = e.m_num_parens;
     m_postfix_index_type = e.m_postfix_index_type;
     m_print_flag = e.m_print_flag;
+    m_delims = e.m_delims;
   }
 
   virtual octave_value evaluate (tree_evaluator& tw, int nargout = 1) = 0;
@@ -139,14 +148,6 @@
 
 protected:
 
-  // A count of the number of times this expression appears directly
-  // inside a set of parentheses.
-  //
-  //   (((e1)) + e2)  ==> 2 for expression e1
-  //                  ==> 1 for expression ((e1)) + e2
-  //                  ==> 0 for expression e2
-  int m_num_parens;
-
   // The first index type associated with this expression.  This field
   // is 0 (character '\0') if the expression has no associated index.
   // See the code in tree_identifier::rvalue for the rationale.
@@ -158,6 +159,9 @@
 
   // Print result of rvalue for this expression?
   bool m_print_flag;
+
+  // Tokens for any delimiters surrounding this expression.
+  tree_delimiter_list m_delims;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-fcn-handle.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -53,7 +53,7 @@
 tree_expression *
 tree_fcn_handle::dup (symbol_scope&) const
 {
-  tree_fcn_handle *new_fh = new tree_fcn_handle (m_name, line (), column ());
+  tree_fcn_handle *new_fh = new tree_fcn_handle (m_token);
 
   new_fh->copy_base (*this);
 
@@ -85,10 +85,10 @@
 
   // FIXME: if new scope is nullptr, then we are in big trouble here...
 
-  tree_anon_fcn_handle *new_afh = new
-  tree_anon_fcn_handle (param_list ? param_list->dup (new_scope) : nullptr,
-                        expr ? expr->dup (new_scope) : nullptr,
-                        new_scope, af_parent_scope, line (), column ());
+  tree_anon_fcn_handle *new_afh
+    = new tree_anon_fcn_handle (m_at_tok, param_list ? param_list->dup (new_scope) : nullptr,
+                                expr ? expr->dup (new_scope) : nullptr,
+                                new_scope, af_parent_scope);
 
   new_afh->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-fcn-handle.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-fcn-handle.h	Fri Apr 12 15:10:26 2024 +0200
@@ -49,16 +49,15 @@
 {
 public:
 
-  tree_fcn_handle (int l = -1, int c = -1)
-    : tree_expression (l, c), m_name () { }
-
-  tree_fcn_handle (const std::string& n, int l = -1, int c = -1)
-    : tree_expression (l, c), m_name (n) { }
+  tree_fcn_handle (const token& tok) : m_token (tok), m_name (m_token.text ()) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_fcn_handle)
 
   ~tree_fcn_handle () = default;
 
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
   void print (std::ostream& os, bool pr_as_read_syntax = false,
               bool pr_orig_txt = true);
 
@@ -85,6 +84,8 @@
 
 private:
 
+  token m_token;
+
   // The name of this function handle.
   std::string m_name;
 };
@@ -93,24 +94,17 @@
 {
 public:
 
-  tree_anon_fcn_handle (int l = -1, int c = -1)
-    : tree_expression (l, c), m_parameter_list (nullptr),
-      m_expression (nullptr), m_scope (symbol_scope::anonymous ()),
-      m_parent_scope (symbol_scope::invalid ()), m_file_name ()
-  { }
-
-  tree_anon_fcn_handle (tree_parameter_list *pl, tree_expression *ex,
-                        const symbol_scope& scope,
-                        const symbol_scope& parent_scope,
-                        int l = -1, int c = -1)
-    : tree_expression (l, c), m_parameter_list (pl), m_expression (ex),
-      m_scope (scope), m_parent_scope (parent_scope), m_file_name ()
+  tree_anon_fcn_handle (const token& at_tok, tree_parameter_list *pl, tree_expression *ex, const symbol_scope& scope, const symbol_scope& parent_scope)
+    : m_at_tok (at_tok), m_parameter_list (pl), m_expression (ex), m_scope (scope), m_parent_scope (parent_scope)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_anon_fcn_handle)
 
   ~tree_anon_fcn_handle ();
 
+  filepos beg_pos () const { return m_at_tok.beg_pos (); }
+  filepos end_pos () const { return m_expression->end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   tree_parameter_list * parameter_list () const
@@ -143,6 +137,8 @@
 
 private:
 
+  token m_at_tok;
+
   // Inputs parameters.
   tree_parameter_list *m_parameter_list;
 
--- a/libinterp/parse-tree/pt-id.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-id.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -81,8 +81,7 @@
 
   symbol_record new_sym = scope.find_symbol (name ());
 
-  tree_identifier *new_id
-    = new tree_identifier (new_sym, line (), column ());
+  tree_identifier *new_id = new tree_identifier (new_sym, m_token);
 
   new_id->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-id.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-id.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,11 +35,13 @@
 class octave_value_list;
 class octave_function;
 
+#include "comment-list.h"
 #include "oct-lvalue.h"
 #include "pt-bp.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
 #include "symscope.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -53,12 +55,12 @@
 
 public:
 
-  tree_identifier (int l = -1, int c = -1)
-    : tree_expression (l, c), m_sym () { }
+  tree_identifier (const token& tok) : m_token (tok) { }
 
-  tree_identifier (const symbol_record& s,
-                   int l = -1, int c = -1)
-    : tree_expression (l, c), m_sym (s) { }
+  tree_identifier (symbol_scope& scope, const token& tok)
+    : m_sym (scope ? scope.insert (tok.text ()) : symbol_record (tok.text ())),
+      m_token (tok)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_identifier)
 
@@ -68,6 +70,11 @@
 
   std::string name () const { return m_sym.name (); }
 
+  comment_list leading_comments () const { return m_token.leading_comments (); }
+
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
   virtual bool is_black_hole () const { return false; }
 
   void mark_as_formal_parameter () { m_sym.mark_formal (); }
@@ -105,18 +112,38 @@
 
   symbol_record symbol () const { return m_sym; }
 
+  tree_identifier * mark_get_set (const token& get_set_tok, const token& dot_tok)
+  {
+    m_get_set_tok = get_set_tok;
+    m_dot_tok = dot_tok;
+
+    return this;
+  }
+
 protected:
 
+  tree_identifier (symbol_record& sym, const token& tok)
+    : m_sym (sym), m_token (tok)
+  { }
+
   // The symbol record that this identifier references.
   symbol_record m_sym;
+
+  // These will be defined for get.ID or set.ID function names.
+  token m_get_set_tok;
+  token m_dot_tok;
+
+  // The IDENT token from the lexer.
+  token m_token;
 };
 
 class tree_black_hole : public tree_identifier
 {
 public:
 
-  tree_black_hole (int l = -1, int c = -1)
-    : tree_identifier (l, c) { }
+  tree_black_hole (const token& token)
+    : tree_identifier (token)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_black_hole)
 
@@ -128,7 +155,7 @@
 
   tree_black_hole * dup (symbol_scope&) const
   {
-    return new tree_black_hole;
+    return new tree_black_hole (m_token);
   }
 
   octave_lvalue lvalue (tree_evaluator& tw);
--- a/libinterp/parse-tree/pt-idx.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-idx.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,42 +46,31 @@
 
 // Index expressions.
 
-tree_index_expression::tree_index_expression (int l, int c)
-  : tree_expression (l, c), m_expr (nullptr), m_args (0), m_type (),
-    m_arg_nm (), m_dyn_field (), m_word_list_cmd (false) { }
-
-tree_index_expression::tree_index_expression (tree_expression *e,
-    tree_argument_list *lst,
-    int l, int c, char t)
-  : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-    m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
+tree_index_expression::tree_index_expression (tree_expression *e, const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)
+  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
 {
-  append (lst, t);
+  append (open_delim, lst, close_delim, t);
 }
 
-tree_index_expression::tree_index_expression (tree_expression *e,
-    const std::string& n,
-    int l, int c)
-  : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-    m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
+tree_index_expression::tree_index_expression (tree_expression *e, const token& dot_tok, const token& struct_elt_tok)
+  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
 {
-  append (n);
+  append (dot_tok, struct_elt_tok);
 }
 
-tree_index_expression::tree_index_expression (tree_expression *e,
-    tree_expression *df,
-    int l, int c)
-  : tree_expression (l, c), m_expr (e), m_args (0), m_type (),
-    m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
+tree_index_expression::tree_index_expression (tree_expression *e, const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)
+  : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
 {
-  append (df);
+  append (dot_tok, open_paren, df, close_paren);
 }
 
 tree_index_expression *
-tree_index_expression::append (tree_argument_list *lst, char t)
+tree_index_expression::append (const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)
 {
+  lst->mark_in_delims (open_delim, close_delim);
   m_args.push_back (lst);
   m_type.append (1, t);
+  m_dot_tok.push_back (token ());
   m_arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
   m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));
 
@@ -92,22 +81,25 @@
 }
 
 tree_index_expression *
-tree_index_expression::append (const std::string& n)
+tree_index_expression::append (const token& dot_tok, const token& struct_elt_tok)
 {
   m_args.push_back (static_cast<tree_argument_list *> (nullptr));
   m_type += '.';
-  m_arg_nm.push_back (n);
+  m_dot_tok.push_back (dot_tok);
+  m_arg_nm.push_back (struct_elt_tok.text ());
   m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));
 
   return this;
 }
 
 tree_index_expression *
-tree_index_expression::append (tree_expression *df)
+tree_index_expression::append (const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)
 {
   m_args.push_back (static_cast<tree_argument_list *> (nullptr));
   m_type += '.';
+  m_dot_tok.push_back (dot_tok);
   m_arg_nm.push_back ("");
+  df->mark_in_delims (open_paren, close_paren);
   m_dyn_field.push_back (df);
 
   return this;
@@ -141,6 +133,36 @@
   return m_expr->name ();
 }
 
+filepos
+tree_index_expression::end_pos () const
+{
+  int n = m_args.size ();
+
+  if (n == 0)
+    return m_expr->end_pos ();
+
+  switch (m_type[n-1])
+    {
+    case '(':
+    case '{':
+      {
+        tree_argument_list *args = m_args.back ();
+        return args->end_pos ();
+      }
+      break;
+
+    case '.':
+      {
+        tree_expression *dyn_field = m_dyn_field.back ();
+        return dyn_field->end_pos ();
+      }
+
+    default:
+      error ("unexpected: index not '(', '{', or '.' in tree_index_expression::end_pos - please report this bug");
+      break;
+    }
+}
+
 std::string
 tree_index_expression::get_struct_index
 (tree_evaluator& tw,
@@ -242,8 +264,7 @@
 tree_index_expression *
 tree_index_expression::dup (symbol_scope& scope) const
 {
-  tree_index_expression *new_idx_expr
-    = new tree_index_expression (line (), column ());
+  tree_index_expression *new_idx_expr = new tree_index_expression ();
 
   new_idx_expr->m_expr = (m_expr ? m_expr->dup (scope) : nullptr);
 
@@ -368,7 +389,7 @@
       if (is_var && is_word_list_cmd ())
         {
           bool maybe_binary_op = false;
-          if ((*p_args) && (*p_args)->length () > 0)
+          if ((*p_args) && (*p_args)->size () > 0)
             {
               // check if first character of first argument might be (the
               // start of) a binary operator
@@ -393,7 +414,7 @@
 
           tree_argument_list *al = *p_args;
 
-          if (al && al->length () > 0)
+          if (al && al->size () > 0)
             {
               unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)
               {
--- a/libinterp/parse-tree/pt-idx.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-idx.h	Fri Apr 12 15:10:26 2024 +0200
@@ -52,31 +52,30 @@
 {
 public:
 
-  tree_index_expression (tree_expression *e = nullptr,
-                         tree_argument_list *lst = nullptr,
-                         int l = -1, int c = -1, char t = '(');
+  tree_index_expression (tree_expression *e, const token& open_delim, tree_argument_list *lst, const token& close_delim, char t);
 
-  tree_index_expression (tree_expression *e, const std::string& n,
-                         int l = -1, int c = -1);
+  tree_index_expression (tree_expression *e, const token& dot_tok, const token& struct_elt_tok);
 
-  tree_index_expression (tree_expression *e, tree_expression *df,
-                         int l = -1, int c = -1);
+  tree_index_expression (tree_expression *e, const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren);
 
   OCTAVE_DISABLE_COPY_MOVE (tree_index_expression)
 
   ~tree_index_expression ();
 
   tree_index_expression *
-  append (tree_argument_list *lst = nullptr, char t = '(');
+  append (const token& open_delim, tree_argument_list *lst, const token& close_delim, char t = '(');
 
-  tree_index_expression * append (const std::string& n);
+  tree_index_expression * append (const token& dot_tok, const token& struct_elt_tok);
 
-  tree_index_expression * append (tree_expression *df);
+  tree_index_expression * append (const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren);
 
   bool is_index_expression () const { return true; }
 
   std::string name () const;
 
+  filepos beg_pos () const { return m_expr->beg_pos (); }
+  filepos end_pos () const;
+
   tree_expression * expression () { return m_expr; }
 
   std::list<tree_argument_list *> arg_lists () { return m_args; }
@@ -121,7 +120,10 @@
 private:
 
   // The LHS of this index expression.
-  tree_expression *m_expr;
+  tree_expression *m_expr {nullptr};
+
+  // FIXME: maybe all the things in the list should be in a struct or
+  // class so we can more easily ensure that they remain synchronized.
 
   // The indices (only valid if type == paren || type == brace).
   std::list<tree_argument_list *> m_args;
@@ -129,6 +131,9 @@
   // The type of this index expression.
   std::string m_type;
 
+  // Record dot tokens for position and possible comment info.
+  std::list<token> m_dot_tok;
+
   // The names of the arguments.  Used for constant struct element
   // references.
   std::list<string_vector> m_arg_nm;
@@ -137,9 +142,9 @@
   std::list<tree_expression *> m_dyn_field;
 
   // TRUE if this expression was parsed as a word list command.
-  bool m_word_list_cmd;
+  bool m_word_list_cmd {false};
 
-  tree_index_expression (int l, int c);
+  tree_index_expression () = default;
 
   octave_map make_arg_struct () const;
 };
--- a/libinterp/parse-tree/pt-jump.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-jump.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,14 +33,33 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-// Break.
+// Base class for jump commands
 
-class tree_break_command : public tree_command
+class tree_jump_command : public tree_command
 {
 public:
 
-  tree_break_command (int l = -1, int c = -1)
-    : tree_command (l, c) { }
+  tree_jump_command (const token& tok) : m_token (tok) { }
+
+  OCTAVE_DISABLE_COPY_MOVE (tree_jump_command)
+
+  ~tree_jump_command () = default;
+
+  filepos beg_pos () const { return m_token.beg_pos (); }
+  filepos end_pos () const { return m_token.end_pos (); }
+
+protected:
+
+  token m_token;
+};
+
+// Break.
+
+class tree_break_command : public tree_jump_command
+{
+public:
+
+  tree_break_command (const token& tok) : tree_jump_command (tok) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_break_command)
 
@@ -54,12 +73,11 @@
 
 // Continue.
 
-class tree_continue_command : public tree_command
+class tree_continue_command : public tree_jump_command
 {
 public:
 
-  tree_continue_command (int l = -1, int c = -1)
-    : tree_command (l, c) { }
+  tree_continue_command (const token& tok) : tree_jump_command (tok) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_continue_command)
 
@@ -73,12 +91,11 @@
 
 // Return.
 
-class tree_return_command : public tree_command
+class tree_return_command : public tree_jump_command
 {
 public:
 
-  tree_return_command (int l = -1, int c = -1)
-    : tree_command (l, c) { }
+  tree_return_command (const token& tok) : tree_jump_command (tok) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_return_command)
 
--- a/libinterp/parse-tree/pt-loop.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-loop.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -39,9 +39,15 @@
 tree_while_command::~tree_while_command ()
 {
   delete m_expr;
-  delete m_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
+  delete m_body;
+}
+
+// Do-until.
+
+tree_do_until_command::~tree_do_until_command ()
+{
+  delete m_body;
+  delete m_expr;
 }
 
 // For.
@@ -51,18 +57,14 @@
   delete m_lhs;
   delete m_expr;
   delete m_maxproc;
-  delete m_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
+  delete m_body;
 }
 
 tree_complex_for_command::~tree_complex_for_command ()
 {
   delete m_lhs;
   delete m_expr;
-  delete m_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
+  delete m_body;
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-loop.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-loop.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,6 +35,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class comment_list;
 class tree_argument_list;
 class tree_expression;
 class tree_statement_list;
@@ -45,91 +46,76 @@
 {
 public:
 
-  tree_while_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_expr (nullptr), m_list (nullptr),
-      m_lead_comm (nullptr), m_trail_comm (nullptr)
-  { }
-
-  tree_while_command (tree_expression *e,
-                      comment_list *lc = nullptr,
-                      comment_list *tc = nullptr,
-                      int l = -1, int c = -1)
-    : tree_command (l, c), m_expr (e), m_list (nullptr),
-      m_lead_comm (lc), m_trail_comm (tc)
-  { }
-
-  tree_while_command (tree_expression *e, tree_statement_list *lst,
-                      comment_list *lc = nullptr,
-                      comment_list *tc = nullptr,
-                      int l = -1, int c = -1)
-    : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc),
-      m_trail_comm (tc)
+  tree_while_command (const token& while_tok, tree_expression *expr, tree_statement_list *body, const token& end_tok)
+    : m_while_tok (while_tok), m_expr (expr), m_body (body), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_while_command)
 
   ~tree_while_command ();
 
+  filepos beg_pos () const { return m_while_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_expression * condition () { return m_expr; }
 
-  tree_statement_list * body () { return m_list; }
-
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  tree_statement_list * body () { return m_body; }
 
   void accept (tree_walker& tw)
   {
     tw.visit_while_command (*this);
   }
 
-protected:
+private:
+
+  token m_while_tok;
 
   // Expression to test.
   tree_expression *m_expr;
 
   // List of commands to execute.
-  tree_statement_list *m_list;
+  tree_statement_list *m_body {nullptr};
 
-  // Comment preceding WHILE token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDWHILE token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 // Do-Until.
 
-class tree_do_until_command : public tree_while_command
+class tree_do_until_command : public tree_command
 {
 public:
 
-  tree_do_until_command (int l = -1, int c = -1)
-    : tree_while_command (l, c)
-  { }
-
-  tree_do_until_command (tree_expression *e,
-                         comment_list *lc = nullptr,
-                         comment_list *tc = nullptr,
-                         int l = -1, int c = -1)
-    : tree_while_command (e, lc, tc, l, c)
-  { }
-
-  tree_do_until_command (tree_expression *e, tree_statement_list *lst,
-                         comment_list *lc = nullptr,
-                         comment_list *tc = nullptr,
-                         int l = -1, int c = -1)
-    : tree_while_command (e, lst, lc, tc, l, c)
+  tree_do_until_command (const token& do_tok, tree_statement_list *body, const token& until_tok, tree_expression *expr)
+    : m_do_tok (do_tok), m_body (body), m_until_tok (until_tok), m_expr (expr)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_do_until_command)
 
-  ~tree_do_until_command () = default;
+  ~tree_do_until_command ();
+
+  filepos beg_pos () const { return m_do_tok.beg_pos (); }
+  filepos end_pos () const { return m_expr->end_pos (); }
+
+  tree_statement_list * body () { return m_body; }
+
+  tree_expression * condition () { return m_expr; }
 
   void accept (tree_walker& tw)
   {
     tw.visit_do_until_command (*this);
   }
+
+private:
+
+  token m_do_tok;
+
+  // List of commands to execute.
+  tree_statement_list *m_body {nullptr};
+
+  token m_until_tok;
+
+  // Expression to test.
+  tree_expression *m_expr;
 };
 
 // For.
@@ -138,29 +124,22 @@
 {
 public:
 
-  tree_simple_for_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_parallel (false), m_lhs (nullptr),
-      m_expr (nullptr), m_maxproc (nullptr), m_list (nullptr),
-      m_lead_comm (nullptr), m_trail_comm (nullptr)
-  { }
-
-  tree_simple_for_command (bool parallel_arg, tree_expression *le,
-                           tree_expression *re,
-                           tree_expression *maxproc_arg,
-                           tree_statement_list *lst,
-                           comment_list *lc = nullptr,
-                           comment_list *tc = nullptr,
-                           int l = -1, int c = -1)
-    : tree_command (l, c), m_parallel (parallel_arg), m_lhs (le),
-      m_expr (re), m_maxproc (maxproc_arg), m_list (lst),
-      m_lead_comm (lc), m_trail_comm (tc)
+  tree_simple_for_command (bool parfor, const token& for_tok, const token& open_paren, tree_expression *le, const token& eq_tok,
+                           tree_expression *re, const token& sep_tok, tree_expression *maxproc_arg, const token& close_paren,
+                           tree_statement_list *body, const token& end_tok)
+    : m_parfor (parfor), m_for_tok (for_tok), m_open_paren (open_paren), m_lhs (le), m_eq_tok (eq_tok),
+      m_expr (re), m_sep_tok (sep_tok), m_maxproc (maxproc_arg), m_close_paren (close_paren),
+      m_body (body), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_simple_for_command)
 
   ~tree_simple_for_command ();
 
-  bool in_parallel () { return m_parallel; }
+  bool in_parallel () { return m_parfor; }
+
+  filepos beg_pos () const { return m_for_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
 
   tree_expression * left_hand_side () { return m_lhs; }
 
@@ -168,11 +147,7 @@
 
   tree_expression * maxproc_expr () { return m_maxproc; }
 
-  tree_statement_list * body () { return m_list; }
-
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  tree_statement_list * body () { return m_body; }
 
   void accept (tree_walker& tw)
   {
@@ -180,61 +155,57 @@
   }
 
 private:
-  // TRUE means operate in parallel (subject to the value of the
-  // maxproc expression).
-  bool m_parallel;
+
+  // FIXME: it would be better to get this info from FOR_TOK.
+  bool m_parfor {false};
+
+  token m_for_tok;
+
+  token m_open_paren;
 
   // Expression to modify.
   tree_expression *m_lhs;
 
+  token m_eq_tok;
+
   // Expression to evaluate.
   tree_expression *m_expr;
 
+  token m_sep_tok;
+
   // Expression to tell how many processors should be used (only valid
   // if parallel is TRUE).
-  tree_expression *m_maxproc;
+  tree_expression *m_maxproc {nullptr};
+
+  token m_close_paren;
 
   // List of commands to execute.
-  tree_statement_list *m_list;
+  tree_statement_list *m_body;
 
-  // Comment preceding FOR token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDFOR token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 class tree_complex_for_command : public tree_command
 {
 public:
 
-  tree_complex_for_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_lhs (nullptr), m_expr (nullptr),
-      m_list (nullptr), m_lead_comm (nullptr), m_trail_comm (nullptr)
-  { }
-
-  tree_complex_for_command (tree_argument_list *le, tree_expression *re,
-                            tree_statement_list *lst,
-                            comment_list *lc = nullptr,
-                            comment_list *tc = nullptr,
-                            int l = -1, int c = -1)
-    : tree_command (l, c), m_lhs (le), m_expr (re), m_list (lst),
-      m_lead_comm (lc), m_trail_comm (tc)
+  tree_complex_for_command (const token& for_tok, tree_argument_list *le, const token& eq_tok, tree_expression *re,
+                            tree_statement_list *body, const token& end_tok)
+    : m_for_tok (for_tok), m_lhs (le), m_eq_tok (eq_tok), m_expr (re), m_body (body), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_complex_for_command)
 
   ~tree_complex_for_command ();
 
+  filepos beg_pos () const { return m_for_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_argument_list * left_hand_side () { return m_lhs; }
 
   tree_expression * control_expr () { return m_expr; }
 
-  tree_statement_list * body () { return m_list; }
-
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  tree_statement_list * body () { return m_body; }
 
   void accept (tree_walker& tw)
   {
@@ -243,20 +214,20 @@
 
 private:
 
+  token m_for_tok;
+
   // Expression to modify.
   tree_argument_list *m_lhs;
 
+  token m_eq_tok;
+
   // Expression to evaluate.
   tree_expression *m_expr;
 
   // List of commands to execute.
-  tree_statement_list *m_list;
+  tree_statement_list *m_body;
 
-  // Comment preceding FOR token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDFOR token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-mat.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-mat.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -141,7 +141,7 @@
 tree_expression *
 tree_matrix::dup (symbol_scope& scope) const
 {
-  tree_matrix *new_matrix = new tree_matrix (nullptr, line (), column ());
+  tree_matrix *new_matrix = new tree_matrix (nullptr);
 
   new_matrix->copy_base (*this, scope);
 
--- a/libinterp/parse-tree/pt-mat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-mat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,6 @@
 class octave_value;
 class octave_value_list;
 
-#include "base-list.h"
 #include "pt-array-list.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
@@ -50,8 +49,8 @@
 {
 public:
 
-  tree_matrix (tree_argument_list *row = nullptr, int l = -1, int c = -1)
-    : tree_array_list (row, l, c)
+  tree_matrix (tree_argument_list *row = nullptr)
+    : tree_array_list (row)
   { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_matrix)
--- a/libinterp/parse-tree/pt-misc.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-misc.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -73,7 +73,7 @@
   new_list->m_marked_for_varargs = m_marked_for_varargs;
 
   for (const tree_decl_elt *elt : *this)
-    new_list->append (elt->dup (scope));
+    new_list->push_back (elt->dup (scope));
 
   return new_list;
 }
--- a/libinterp/parse-tree/pt-misc.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-misc.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,8 @@
 
 #include "octave-config.h"
 
-#include "base-list.h"
+#include <list>
+
 #include "pt-decl.h"
 #include "pt-walk.h"
 
@@ -42,7 +43,7 @@
 // parameters in a function definition.  Elements are identifiers
 // only.
 
-class tree_parameter_list : public base_list<tree_decl_elt *>
+class tree_parameter_list : public std::list<tree_decl_elt *>
 {
 public:
 
@@ -59,19 +60,30 @@
   tree_parameter_list (in_or_out io, tree_decl_elt *t)
     : m_in_or_out (io), m_marked_for_varargs (0)
   {
-    append (t);
+    push_back (t);
   }
 
   tree_parameter_list (in_or_out io, tree_identifier *id)
     : m_in_or_out (io), m_marked_for_varargs (0)
   {
-    append (new tree_decl_elt (id));
+    push_back (new tree_decl_elt (id));
   }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_parameter_list)
 
   ~tree_parameter_list ();
 
+  tree_parameter_list * mark_in_delims (const token& open_delim, const token& close_delim)
+  {
+    m_open_delim = open_delim;
+    m_close_delim = close_delim;
+
+    return this;
+  }
+
+  filepos beg_pos () const { return m_open_delim.beg_pos (); }
+  filepos end_pos () const { return m_close_delim.end_pos (); }
+
   void mark_as_formal_parameters ();
 
   void mark_varargs () { m_marked_for_varargs = 1; }
@@ -108,6 +120,9 @@
   // -1: takes varargs only
   // 0: does not take varargs.
   int m_marked_for_varargs;
+
+  token m_open_delim;
+  token m_close_delim;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-pr-code.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-pr-code.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -37,6 +37,12 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+OCTAVE_NORETURN static void
+error_unexpected (const char *name)
+{
+  error ("unexpected call to %s - please report this bug", name);
+}
+
 void
 tree_print_code::visit_anon_fcn_handle (tree_anon_fcn_handle& afh)
 {
@@ -87,31 +93,31 @@
 void
 tree_print_code::visit_args_block_attribute_list (tree_args_block_attribute_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_print_code::visit_args_block_attribute_list");
 }
 
 void
 tree_print_code::visit_args_block_validation_list (tree_args_block_validation_list&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_print_code::visit_args_block_validation_list");
 }
 
 void
 tree_print_code::visit_arg_validation (tree_arg_validation&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_print_code::visit_arg_validation");
 }
 
 void
 tree_print_code::visit_arg_size_spec (tree_arg_size_spec&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_print_code::visit_arg_size_spec");
 }
 
 void
 tree_print_code::visit_arg_validation_fcns (tree_arg_validation_fcns&)
 {
-  panic_impossible ();
+  error_unexpected ("tree_print_code::visit_arg_validation_fcns");
 }
 
 void
@@ -238,7 +244,7 @@
 void
 tree_print_code::visit_simple_for_command (tree_simple_for_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -281,8 +287,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << (cmd.in_parallel () ? "endparfor" : "endfor");
@@ -291,7 +295,7 @@
 void
 tree_print_code::visit_complex_for_command (tree_complex_for_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -324,8 +328,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "endfor";
@@ -334,7 +336,7 @@
 void
 tree_print_code::visit_spmd_command (tree_spmd_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -353,8 +355,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "endspmd";
@@ -395,11 +395,11 @@
 void
 tree_print_code::visit_octave_user_function_header (octave_user_function& fcn)
 {
-  comment_list *leading_comment = fcn.leading_comment ();
+  comment_list leading_comments = fcn.leading_comments ();
 
-  if (leading_comment)
+  if (! leading_comments.empty ())
     {
-      print_comment_list (leading_comment);
+      print_comment_list (leading_comments);
       newline ();
     }
 
@@ -430,7 +430,7 @@
 void
 tree_print_code::visit_octave_user_function_trailer (octave_user_function& fcn)
 {
-  print_indented_comment (fcn.trailing_comment ());
+  print_indented_comment (fcn.trailing_comments ());
 
   newline ();
 }
@@ -486,7 +486,7 @@
 void
 tree_print_code::visit_if_command (tree_if_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -497,8 +497,6 @@
   if (list)
     list->accept (*this);
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "endif";
@@ -519,7 +517,7 @@
         {
           if (! first_elt)
             {
-              print_indented_comment (elt->leading_comment ());
+              print_indented_comment (elt->leading_comments ());
 
               indent ();
 
@@ -566,7 +564,7 @@
         case '(':
           {
             char nc = m_nesting.top ();
-            if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
+            if ((nc == '[' || nc == '{') && expr.delim_count () == 0)
               m_os << '(';
             else
               m_os << " (";
@@ -584,7 +582,7 @@
         case '{':
           {
             char nc = m_nesting.top ();
-            if ((nc == '[' || nc == '{') && expr.paren_count () == 0)
+            if ((nc == '[' || nc == '{') && expr.delim_count () == 0)
               m_os << '{';
             else
               m_os << " {";
@@ -623,7 +621,7 @@
           break;
 
         default:
-          panic_impossible ();
+          error ("unexpected: index not '(', '{', or '.' in tree_print_code::visit_index_expression - please report this bug");
         }
 
       p_arg_lists++;
@@ -707,7 +705,7 @@
 
   if (lhs)
     {
-      int len = lhs->length ();
+      int len = lhs->size ();
 
       if (len > 1)
         {
@@ -781,7 +779,7 @@
     }
   else
     {
-      int len = lst.length ();
+      int len = lst.size ();
       if (lst.takes_varargs ())
         len++;
 
@@ -817,7 +815,7 @@
     }
   else
     {
-      int len = lst.length ();
+      int len = lst.size ();
       if (lst.takes_varargs ())
         len++;
 
@@ -896,7 +894,7 @@
 void
 tree_print_code::visit_statement (tree_statement& stmt)
 {
-  print_comment_list (stmt.comment_text ());
+  print_comment_list (stmt.leading_comments ());
 
   tree_command *cmd = stmt.command ();
 
@@ -938,7 +936,7 @@
 void
 tree_print_code::visit_switch_case (tree_switch_case& cs)
 {
-  print_comment_list (cs.leading_comment ());
+  print_comment_list (cs.leading_comments ());
 
   indent ();
 
@@ -971,7 +969,7 @@
 void
 tree_print_code::visit_switch_command (tree_switch_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -995,7 +993,7 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.leading_comment ());
+  print_indented_comment (cmd.leading_comments ());
 
   indent ();
 
@@ -1005,7 +1003,7 @@
 void
 tree_print_code::visit_try_catch_command (tree_try_catch_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -1025,8 +1023,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.middle_comment ());
-
   indent ();
 
   m_os << "catch";
@@ -1050,8 +1046,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "end_try_catch";
@@ -1060,7 +1054,7 @@
 void
 tree_print_code::visit_unwind_protect_command (tree_unwind_protect_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -1079,8 +1073,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.middle_comment ());
-
   indent ();
 
   m_os << "unwind_protect_cleanup";
@@ -1098,8 +1090,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "end_unwind_protect";
@@ -1108,7 +1098,7 @@
 void
 tree_print_code::visit_while_command (tree_while_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -1132,8 +1122,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "endwhile";
@@ -1142,7 +1130,7 @@
 void
 tree_print_code::visit_do_until_command (tree_do_until_command& cmd)
 {
-  print_comment_list (cmd.leading_comment ());
+  print_comment_list (cmd.leading_comments ());
 
   indent ();
 
@@ -1161,8 +1149,6 @@
       decrement_indent_level ();
     }
 
-  print_indented_comment (cmd.trailing_comment ());
-
   indent ();
 
   m_os << "until ";
@@ -1247,7 +1233,7 @@
 void
 tree_print_code::print_parens (const tree_expression& expr, const char *txt)
 {
-  int n = expr.paren_count ();
+  int n = expr.delim_count ();
 
   for (int i = 0; i < n; i++)
     m_os << txt;
@@ -1314,26 +1300,23 @@
 }
 
 void
-tree_print_code::print_comment_list (comment_list *comment_list)
+tree_print_code::print_comment_list (const comment_list& comment_list)
 {
-  if (comment_list)
-    {
-      auto p = comment_list->begin ();
+  auto p = comment_list.begin ();
 
-      while (p != comment_list->end ())
-        {
-          comment_elt elt = *p++;
+  while (p != comment_list.end ())
+    {
+      comment_elt elt = *p++;
 
-          print_comment_elt (elt);
+      print_comment_elt (elt);
 
-          if (p != comment_list->end ())
-            newline ();
-        }
+      if (p != comment_list.end ())
+        newline ();
     }
 }
 
 void
-tree_print_code::print_indented_comment (comment_list *comment_list)
+tree_print_code::print_indented_comment (const comment_list& comment_list)
 {
   increment_indent_level ();
 
--- a/libinterp/parse-tree/pt-pr-code.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-pr-code.h	Fri Apr 12 15:10:26 2024 +0200
@@ -195,11 +195,11 @@
 
   void print_parens (const tree_expression& expr, const char *txt);
 
-  void print_comment_list (comment_list *comment_list);
+  void print_comment_list (const comment_list& comment_list);
 
   void print_comment_elt (const comment_elt& comment_elt);
 
-  void print_indented_comment (comment_list *comment_list);
+  void print_indented_comment (const comment_list& comment_list);
 
   // Must create with an output stream!
 
--- a/libinterp/parse-tree/pt-select.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-select.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -39,7 +39,6 @@
 {
   delete m_expr;
   delete m_list;
-  delete m_lead_comm;
 }
 
 // If.
@@ -47,8 +46,6 @@
 tree_if_command::~tree_if_command ()
 {
   delete m_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
 }
 
 // Switch cases.
@@ -57,7 +54,6 @@
 {
   delete m_label;
   delete m_list;
-  delete m_lead_comm;
 }
 
 // Switch.
@@ -66,8 +62,6 @@
 {
   delete m_expr;
   delete m_list;
-  delete m_lead_comm;
-  delete m_trail_comm;
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-select.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-select.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,13 +28,17 @@
 
 #include "octave-config.h"
 
-#include "base-list.h"
+#include <list>
+
 #include "comment-list.h"
 #include "pt-cmd.h"
+#include "pt-stmt.h"
 #include "pt-walk.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class comment_list;
 class tree_expression;
 class tree_statement_list;
 
@@ -44,30 +48,26 @@
 {
 public:
 
-  tree_if_clause (int l = -1, int c = -1)
-    : tree (l, c), m_expr (nullptr), m_list (nullptr), m_lead_comm (nullptr)
+  tree_if_clause (const token& tok, tree_expression *e, tree_statement_list *sl)
+    : m_tok (tok), m_expr (e), m_list (sl)
   { }
 
-  tree_if_clause (tree_statement_list *sl, comment_list *lc = nullptr,
-                  int l = -1, int c = -1)
-    : tree (l, c), m_expr (nullptr), m_list (sl), m_lead_comm (lc) { }
-
-  tree_if_clause (tree_expression *e, tree_statement_list *sl,
-                  comment_list *lc = nullptr,
-                  int l = -1, int c = -1)
-    : tree (l, c), m_expr (e), m_list (sl), m_lead_comm (lc) { }
-
-  OCTAVE_DISABLE_COPY_MOVE (tree_if_clause)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_if_clause)
 
   ~tree_if_clause ();
 
+  token if_token () const { return m_tok; }
+
   bool is_else_clause () { return ! m_expr; }
 
+  filepos beg_pos () const { return m_tok.beg_pos (); }
+  filepos end_pos () const { return m_list->end_pos (); }
+
   tree_expression * condition () { return m_expr; }
 
   tree_statement_list * commands () { return m_list; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
+  comment_list leading_comments () const { return m_tok.leading_comments (); }
 
   void accept (tree_walker& tw)
   {
@@ -76,23 +76,22 @@
 
 private:
 
+  token m_tok;
+
   // The condition to test.
-  tree_expression *m_expr;
+  tree_expression *m_expr = nullptr;
 
   // The list of statements to evaluate if expr is true.
   tree_statement_list *m_list;
-
-  // Comment preceding ELSE or ELSEIF token.
-  comment_list *m_lead_comm;
 };
 
-class tree_if_command_list : public base_list<tree_if_clause *>
+class tree_if_command_list : public std::list<tree_if_clause *>
 {
 public:
 
   tree_if_command_list () { }
 
-  tree_if_command_list (tree_if_clause *t) { append (t); }
+  tree_if_command_list (tree_if_clause *t) { push_back (t); }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_if_command_list)
 
@@ -106,6 +105,35 @@
       }
   }
 
+  filepos beg_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_if_clause *elt = front ();
+    return elt->beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_if_clause *elt = back ();
+    return elt->end_pos ();
+  }
+
+  token if_token () const
+  {
+    if (! empty ())
+      {
+        tree_if_clause *p = front ();
+        return p->if_token ();
+      }
+
+    return token ();
+  }
+
   void accept (tree_walker& tw)
   {
     tw.visit_if_command_list (*this);
@@ -116,25 +144,24 @@
 {
 public:
 
-  tree_if_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_list (nullptr),
-      m_lead_comm (nullptr), m_trail_comm (nullptr)
+  tree_if_command (const token& if_tok, const token& end_tok)
+    : m_if_tok (if_tok), m_end_tok (end_tok)
   { }
 
-  tree_if_command (tree_if_command_list *lst, comment_list *lc,
-                   comment_list *tc, int l = -1, int c = -1)
-    : tree_command (l, c), m_list (lst), m_lead_comm (lc), m_trail_comm (tc)
+  tree_if_command (const token& if_tok, tree_if_command_list *lst, const token& end_tok)
+    : m_if_tok (if_tok), m_list (lst), m_end_tok (end_tok)
   { }
 
-  OCTAVE_DISABLE_COPY_MOVE (tree_if_command)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_if_command)
 
   ~tree_if_command ();
 
+  filepos beg_pos () const { return m_if_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_if_command_list * cmd_list () { return m_list; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  comment_list leading_comments () const { return m_if_tok.leading_comments (); }
 
   void accept (tree_walker& tw)
   {
@@ -143,14 +170,12 @@
 
 private:
 
-  // List of if commands (if, elseif, elseif, ... else, endif)
-  tree_if_command_list *m_list;
+  token m_if_tok;
 
-  // Comment preceding IF token.
-  comment_list *m_lead_comm;
+  // List of if commands (if, elseif, elseif, ... else, endif)
+  tree_if_command_list *m_list = nullptr;
 
-  // Comment preceding ENDIF token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 // Switch.
@@ -159,30 +184,28 @@
 {
 public:
 
-  tree_switch_case (int l = -1, int c = -1)
-    : tree (l, c), m_label (nullptr), m_list (nullptr), m_lead_comm (nullptr)
+  tree_switch_case (const token& tok, tree_statement_list *sl)
+    : m_tok (tok), m_list (sl)
   { }
 
-  tree_switch_case (tree_statement_list *sl, comment_list *lc = nullptr,
-                    int l = -1, int c = -1)
-    : tree (l, c), m_label (nullptr), m_list (sl), m_lead_comm (lc) { }
+  tree_switch_case (const token& tok, tree_expression *e, tree_statement_list *sl)
+    : m_tok (tok), m_label (e), m_list (sl)
+  { }
 
-  tree_switch_case (tree_expression *e, tree_statement_list *sl,
-                    comment_list *lc = nullptr,
-                    int l = -1, int c = -1)
-    : tree (l, c), m_label (e), m_list (sl), m_lead_comm (lc) { }
-
-  OCTAVE_DISABLE_COPY_MOVE (tree_switch_case)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_switch_case)
 
   ~tree_switch_case ();
 
   bool is_default_case () { return ! m_label; }
 
+  filepos beg_pos () const { return m_tok.beg_pos (); }
+  filepos end_pos () const { return m_list->end_pos (); }
+
   tree_expression * case_label () { return m_label; }
 
   tree_statement_list * commands () { return m_list; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
+  comment_list leading_comments () const { return m_tok.leading_comments (); }
 
   void accept (tree_walker& tw)
   {
@@ -191,23 +214,22 @@
 
 private:
 
+  token m_tok;
+
   // The case label.
-  tree_expression *m_label;
+  tree_expression *m_label = nullptr;
 
   // The list of statements to evaluate if the label matches.
   tree_statement_list *m_list;
-
-  // Comment preceding CASE or OTHERWISE token.
-  comment_list *m_lead_comm;
 };
 
-class tree_switch_case_list : public base_list<tree_switch_case *>
+class tree_switch_case_list : public std::list<tree_switch_case *>
 {
 public:
 
   tree_switch_case_list () { }
 
-  tree_switch_case_list (tree_switch_case *t) { append (t); }
+  tree_switch_case_list (tree_switch_case *t) { push_back (t); }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_switch_case_list)
 
@@ -221,6 +243,24 @@
       }
   }
 
+  filepos beg_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_switch_case *elt = front ();
+    return elt->beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_switch_case *elt = back ();
+    return elt->end_pos ();
+  }
+
   void accept (tree_walker& tw)
   {
     tw.visit_switch_case_list (*this);
@@ -231,27 +271,22 @@
 {
 public:
 
-  tree_switch_command (int l = -1, int c = -1)
-    : tree_command (l, c), m_expr (nullptr), m_list (nullptr),
-      m_lead_comm (nullptr), m_trail_comm (nullptr) { }
+  tree_switch_command (const token& switch_tok, tree_expression *e, tree_switch_case_list *lst, const token& end_tok)
+    : m_switch_tok (switch_tok), m_expr (e), m_list (lst), m_end_tok (end_tok)
+  { }
 
-  tree_switch_command (tree_expression *e, tree_switch_case_list *lst,
-                       comment_list *lc, comment_list *tc,
-                       int l = -1, int c = -1)
-    : tree_command (l, c), m_expr (e), m_list (lst), m_lead_comm (lc),
-      m_trail_comm (tc) { }
-
-  OCTAVE_DISABLE_COPY_MOVE (tree_switch_command)
+  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_switch_command)
 
   ~tree_switch_command ();
 
+  filepos beg_pos () const { return m_switch_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
+
   tree_expression * switch_value () { return m_expr; }
 
   tree_switch_case_list * case_list () { return m_list; }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  comment_list leading_comments () const { return m_switch_tok.leading_comments (); }
 
   void accept (tree_walker& tw)
   {
@@ -260,17 +295,15 @@
 
 private:
 
+  token m_switch_tok;
+
   // Value on which to switch.
   tree_expression *m_expr;
 
   // List of cases (case 1, case 2, ..., default)
   tree_switch_case_list *m_list;
 
-  // Comment preceding SWITCH token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDSWITCH token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-spmd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-spmd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -36,8 +36,6 @@
 tree_spmd_command::~tree_spmd_command ()
 {
   delete m_body;
-  delete m_lead_comm;
-  delete m_trail_comm;
 }
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-spmd.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-spmd.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,13 +28,12 @@
 
 #include "octave-config.h"
 
-#include "base-list.h"
 #include "pt-cmd.h"
 #include "pt-walk.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class tree_comment_list;
+class comment_list;
 class tree_statement_list;
 
 // Spmd.
@@ -43,20 +42,18 @@
 {
 public:
 
-  tree_spmd_command (tree_statement_list *body, comment_list *lc,
-                     comment_list *tc, int l = -1, int c = -1)
-    : tree_command (l, c), m_body (body), m_lead_comm (lc), m_trail_comm (tc)
+  tree_spmd_command (const token& spmd_tok, tree_statement_list *body, const token& end_tok)
+    : m_spmd_tok (spmd_tok), m_body (body), m_end_tok (end_tok)
   { }
 
   OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (tree_spmd_command)
 
   ~tree_spmd_command ();
 
-  tree_statement_list * body () { return m_body; }
+  filepos beg_pos () const { return m_spmd_tok.beg_pos (); }
+  filepos end_pos () const { return m_end_tok.end_pos (); }
 
-  comment_list * leading_comment () { return m_lead_comm; }
-
-  comment_list * trailing_comment () { return m_trail_comm; }
+  tree_statement_list * body () { return m_body; }
 
   void accept (tree_walker& tw)
   {
@@ -65,14 +62,12 @@
 
 private:
 
+  token m_spmd_tok;
+
   // List of commands.
   tree_statement_list *m_body;
 
-  // Comment preceding SPMD token.
-  comment_list *m_lead_comm;
-
-  // Comment preceding ENDSPMD token.
-  comment_list *m_trail_comm;
+  token m_end_tok;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/pt-stmt.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-stmt.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,6 @@
 {
   delete m_command;
   delete m_expression;
-  delete m_comment_list;
 }
 
 void
@@ -107,6 +106,35 @@
             : false);
 }
 
+comment_list
+tree_statement::leading_comments () const
+{
+  return (m_command
+          ? m_command->leading_comments ()
+          : m_expression->leading_comments ());
+}
+
+filepos
+tree_statement::beg_pos () const
+{
+  return (m_command ? m_command->beg_pos () : m_expression->beg_pos ());
+}
+
+filepos
+tree_statement::end_pos () const
+{
+  return (m_command ? m_command->end_pos () : m_expression->end_pos ());
+}
+
+void
+tree_statement::update_end_pos (const filepos& pos)
+{
+  if (m_command)
+    m_command->update_end_pos (pos);
+  else
+    panic_impossible ();
+}
+
 std::string
 tree_statement::bp_cond () const
 {
@@ -132,15 +160,6 @@
 }
 
 void
-tree_statement::set_location (int l, int c)
-{
-  if (m_command)
-    m_command->set_location (l, c);
-  else if (m_expression)
-    m_expression->set_location (l, c);
-}
-
-void
 tree_statement::echo_code (const std::string& prefix)
 {
   tree_print_code tpc (octave_stdout, prefix);
@@ -182,6 +201,20 @@
   return retval;
 }
 
+comment_list
+tree_statement_list::leading_comments () const
+{
+  if (! empty ())
+    {
+      tree_statement *elt = front ();
+
+      if (elt)
+        return elt->leading_comments ();
+    }
+
+  return comment_list ();
+}
+
 // Create a "breakpoint" tree-walker, and get it to "walk" this
 // statement list
 // (FIXME: What does that do???)
--- a/libinterp/parse-tree/pt-stmt.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-stmt.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,8 +31,8 @@
 class octave_value_list;
 
 #include <deque>
+#include <list>
 
-#include "base-list.h"
 #include "bp-table.h"
 #include "pt.h"
 #include "pt-walk.h"
@@ -54,14 +54,16 @@
 public:
 
   tree_statement ()
-    : m_command (nullptr), m_expression (nullptr),
-      m_comment_list (nullptr) { }
+    : m_command (nullptr), m_expression (nullptr)
+  { }
 
-  tree_statement (tree_command *c, comment_list *cl)
-    : m_command (c), m_expression (nullptr), m_comment_list (cl) { }
+  tree_statement (tree_command *c)
+    : m_command (c), m_expression (nullptr)
+  { }
 
-  tree_statement (tree_expression *e, comment_list *cl)
-    : m_command (nullptr), m_expression (e), m_comment_list (cl) { }
+  tree_statement (tree_expression *e)
+    : m_command (nullptr), m_expression (e)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_statement)
 
@@ -83,24 +85,27 @@
 
   bool is_active_breakpoint (tree_evaluator& tw) const;
 
+  comment_list leading_comments () const;
+
+  filepos beg_pos () const;
+  filepos end_pos () const;
+
+  virtual void update_end_pos (const filepos& pos);
+
   std::string bp_cond () const;
 
   int line () const;
   int column () const;
 
-  void set_location (int l, int c);
-
   void echo_code (const std::string& prefix);
 
   tree_command * command () { return m_command; }
 
   tree_expression * expression () { return m_expression; }
 
-  comment_list * comment_text () { return m_comment_list; }
-
   bool is_null_statement () const
   {
-    return ! (m_command || m_expression || m_comment_list);
+    return ! (m_command || m_expression);
   }
 
   bool is_end_of_fcn_or_script () const;
@@ -129,14 +134,11 @@
 
   // Expression to evaluate.
   tree_expression *m_expression;
-
-  // Comment associated with this statement.
-  comment_list *m_comment_list;
 };
 
 // A list of statements to evaluate.
 
-class tree_statement_list : public base_list<tree_statement *>
+class tree_statement_list : public std::list<tree_statement *>
 {
 public:
 
@@ -146,7 +148,7 @@
 
   tree_statement_list (tree_statement *s)
     : m_function_body (false), m_anon_function_body (false),
-      m_script_body (false) { append (s); }
+      m_script_body (false) { push_back (s); }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_statement_list)
 
@@ -160,6 +162,24 @@
       }
   }
 
+  filepos beg_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_statement *elt = front ();
+    return elt->beg_pos ();
+  }
+
+  filepos end_pos () const
+  {
+    if (empty ())
+      return filepos ();
+
+    tree_statement *elt = back ();
+    return elt->end_pos ();
+  }
+
   void mark_as_function_body () { m_function_body = true; }
 
   void mark_as_anon_function_body () { m_anon_function_body = true; }
@@ -172,6 +192,8 @@
 
   bool is_script_body () const { return m_script_body; }
 
+  comment_list leading_comments () const;
+
   int set_breakpoint (int line, const std::string& condition);
 
   void delete_breakpoint (int line);
--- a/libinterp/parse-tree/pt-tm-const.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-tm-const.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -88,7 +88,7 @@
     {
       octave_quit ();
 
-      dim_vector this_elt_dv = val.dims ();
+      const dim_vector& this_elt_dv = val.dims ();
 
       if (! this_elt_dv.zero_by_zero ())
         {
@@ -111,7 +111,7 @@
 
   m_class_name = get_concat_class (m_class_name, this_elt_class_name);
 
-  dim_vector this_elt_dv = val.dims ();
+  const dim_vector& this_elt_dv = val.dims ();
 
   if (! this_elt_dv.zero_by_zero ())
     {
@@ -207,7 +207,7 @@
     {
       octave_quit ();
 
-      dim_vector this_elt_dv = val.dims ();
+      const dim_vector& this_elt_dv = val.dims ();
 
       if (! this_elt_dv.zero_by_zero ())
         {
@@ -399,7 +399,7 @@
       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 ();
+      const dim_vector& this_elt_dv = elt.dims ();
 
       m_all_empty = false;
 
--- a/libinterp/parse-tree/pt-unop.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-unop.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -48,8 +48,7 @@
 tree_prefix_expression::dup (symbol_scope& scope) const
 {
   tree_prefix_expression *new_pe
-    = new tree_prefix_expression (m_op ? m_op->dup (scope) : nullptr,
-                                  line (), column (), m_etype);
+    = new tree_prefix_expression (m_op_tok, m_op ? m_op->dup (scope) : nullptr, m_etype);
 
   new_pe->copy_base (*this);
 
@@ -110,8 +109,7 @@
 tree_postfix_expression::dup (symbol_scope& scope) const
 {
   tree_postfix_expression *new_pe
-    = new tree_postfix_expression (m_op ? m_op->dup (scope) : nullptr,
-                                   line (), column (), m_etype);
+    = new tree_postfix_expression (m_op ? m_op->dup (scope) : nullptr, m_op_tok, m_etype);
 
   new_pe->copy_base (*this);
 
--- a/libinterp/parse-tree/pt-unop.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-unop.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,6 +36,7 @@
 #include "ov.h"
 #include "pt-exp.h"
 #include "pt-walk.h"
+#include "token.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -47,15 +48,12 @@
 {
 protected:
 
-  tree_unary_expression (int l = -1, int c = -1,
-                         octave_value::unary_op t
-                         = octave_value::unknown_unary_op)
-    : tree_expression (l, c), m_op (nullptr), m_etype (t)  { }
+  tree_unary_expression (octave_value::unary_op t = octave_value::unknown_unary_op)
+    : m_op (nullptr), m_etype (t)  { }
 
-  tree_unary_expression (tree_expression *e, int l = -1, int c = -1,
-                         octave_value::unary_op t
-                         = octave_value::unknown_unary_op)
-    : tree_expression (l, c), m_op (e), m_etype (t) { }
+  tree_unary_expression (const token& op_tok, tree_expression *e, octave_value::unary_op t = octave_value::unknown_unary_op)
+    : m_op_tok (op_tok), m_op (e), m_etype (t)
+  { }
 
 public:
 
@@ -73,6 +71,9 @@
 
 protected:
 
+  // The operator token.
+  token m_op_tok;
+
   // The operand for the expression.
   tree_expression *m_op;
 
@@ -86,18 +87,17 @@
 {
 public:
 
-  tree_prefix_expression (int l = -1, int c = -1)
-    : tree_unary_expression (l, c, octave_value::unknown_unary_op) { }
-
-  tree_prefix_expression (tree_expression *e, int l = -1, int c = -1,
-                          octave_value::unary_op t
-                          = octave_value::unknown_unary_op)
-    : tree_unary_expression (e, l, c, t) { }
+  tree_prefix_expression (const token& op_tok, tree_expression *e, octave_value::unary_op t = octave_value::unknown_unary_op)
+    : tree_unary_expression (op_tok, e, t)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_prefix_expression)
 
   ~tree_prefix_expression () = default;
 
+  filepos beg_pos () const { return m_op_tok.beg_pos (); }
+  filepos end_pos () const { return m_op->end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
@@ -123,18 +123,17 @@
 {
 public:
 
-  tree_postfix_expression (int l = -1, int c = -1)
-    : tree_unary_expression (l, c, octave_value::unknown_unary_op) { }
-
-  tree_postfix_expression (tree_expression *e, int l = -1, int c = -1,
-                           octave_value::unary_op t
-                           = octave_value::unknown_unary_op)
-    : tree_unary_expression (e, l, c, t) { }
+  tree_postfix_expression (tree_expression *e, const token& op_tok, octave_value::unary_op t = octave_value::unknown_unary_op)
+    : tree_unary_expression (op_tok, e, t)
+  { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree_postfix_expression)
 
   ~tree_postfix_expression () = default;
 
+  filepos beg_pos () const { return m_op->beg_pos (); }
+  filepos end_pos () const { return m_op_tok.end_pos (); }
+
   bool rvalue_ok () const { return true; }
 
   tree_expression * dup (symbol_scope& scope) const;
--- a/libinterp/parse-tree/pt-walk.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-walk.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -722,14 +722,14 @@
 void
 tree_walker::visit_classdef_properties_block (tree_classdef_properties_block& blk)
 {
-  tree_classdef_property_list *property_list = blk.element_list ();
+  tree_classdef_property_list *property_list = blk.property_list ();
 
   if (property_list)
     property_list->accept (*this);
 }
 
 void
-tree_walker::visit_classdef_methods_list (tree_classdef_methods_list& lst)
+tree_walker::visit_classdef_method_list (tree_classdef_method_list& lst)
 {
   for (auto ov_meth : lst)
     {
@@ -743,10 +743,10 @@
 void
 tree_walker::visit_classdef_methods_block (tree_classdef_methods_block& blk)
 {
-  tree_classdef_methods_list *methods_list = blk.element_list ();
+  tree_classdef_method_list *method_list = blk.method_list ();
 
-  if (methods_list)
-    methods_list->accept (*this);
+  if (method_list)
+    method_list->accept (*this);
 }
 
 void
@@ -756,7 +756,7 @@
 }
 
 void
-tree_walker::visit_classdef_events_list (tree_classdef_events_list& lst)
+tree_walker::visit_classdef_event_list (tree_classdef_event_list& lst)
 {
   for (auto *elt : lst)
     {
@@ -768,10 +768,10 @@
 void
 tree_walker::visit_classdef_events_block (tree_classdef_events_block& blk)
 {
-  tree_classdef_events_list *events_list = blk.element_list ();
+  tree_classdef_event_list *event_list = blk.event_list ();
 
-  if (events_list)
-    events_list->accept (*this);
+  if (event_list)
+    event_list->accept (*this);
 }
 
 void
@@ -793,7 +793,7 @@
 void
 tree_walker::visit_classdef_enum_block (tree_classdef_enum_block& blk)
 {
-  tree_classdef_enum_list *enum_list = blk.element_list ();
+  tree_classdef_enum_list *enum_list = blk.enum_list ();
 
   if (enum_list)
     enum_list->accept (*this);
@@ -802,20 +802,20 @@
 void
 tree_walker::visit_classdef_body (tree_classdef_body& body)
 {
-  for (auto *elt : body.properties_list ())
+  for (auto *elt : body.property_list ())
     {
       if (elt)
         elt->accept (*this);
     }
 
-  for (auto *elt : body.methods_list ())
+  for (auto *elt : body.method_list ())
     {
       if (elt)
         elt->accept (*this);
     }
 
 
-  for (auto *elt : body.events_list ())
+  for (auto *elt : body.event_list ())
     {
       if (elt)
         elt->accept (*this);
--- a/libinterp/parse-tree/pt-walk.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt-walk.h	Fri Apr 12 15:10:26 2024 +0200
@@ -96,10 +96,10 @@
 class tree_classdef_property;
 class tree_classdef_property_list;
 class tree_classdef_properties_block;
-class tree_classdef_methods_list;
+class tree_classdef_method_list;
 class tree_classdef_methods_block;
 class tree_classdef_event;
-class tree_classdef_events_list;
+class tree_classdef_event_list;
 class tree_classdef_events_block;
 class tree_classdef_enum;
 class tree_classdef_enum_list;
@@ -233,13 +233,13 @@
 
   virtual void visit_classdef_properties_block (tree_classdef_properties_block&);
 
-  virtual void visit_classdef_methods_list (tree_classdef_methods_list&);
+  virtual void visit_classdef_method_list (tree_classdef_method_list&);
 
   virtual void visit_classdef_methods_block (tree_classdef_methods_block&);
 
   virtual void visit_classdef_event (tree_classdef_event&);
 
-  virtual void visit_classdef_events_list (tree_classdef_events_list&);
+  virtual void visit_classdef_event_list (tree_classdef_event_list&);
 
   virtual void visit_classdef_events_block (tree_classdef_events_block&);
 
--- a/libinterp/parse-tree/pt.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -30,6 +30,8 @@
 #include <sstream>
 #include <string>
 
+#include "comment-list.h"
+#include "filepos.h"
 #include "interpreter.h"
 #include "ov-fcn.h"
 #include "pt.h"
@@ -39,6 +41,24 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+int
+tree::line () const
+{
+  return beg_pos().line ();
+}
+
+int
+tree::column () const
+{
+  return beg_pos().column ();
+}
+
+comment_list
+tree::leading_comments () const
+{
+  return comment_list ();
+}
+
 // Hide the details of the string buffer so that we are less likely to
 // create a memory leak.
 
--- a/libinterp/parse-tree/pt.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/pt.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,6 +36,8 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
+class comment_list;
+class filepos;
 class tree_evaluator;
 class tree_walker;
 
@@ -45,27 +47,20 @@
 {
 public:
 
-  tree (int l = -1, int c = -1)
-    : m_line_num (l), m_column_num (c), m_bp_cond (nullptr)
-  { }
+  tree () : m_bp_cond (nullptr) { }
 
   OCTAVE_DISABLE_COPY_MOVE (tree)
 
   virtual ~tree () = default;
 
-  virtual int line () const { return m_line_num; }
-
-  virtual int column () const { return m_column_num; }
-
-  void line (int l) { m_line_num = l; }
+  virtual int line () const;
+  virtual int column () const;
 
-  void column (int c) { m_column_num = c; }
+  virtual filepos beg_pos () const = 0;
+  virtual filepos end_pos () const = 0;
 
-  void set_location (int l, int c)
-  {
-    m_line_num = l;
-    m_column_num = c;
-  }
+  // FIXME: maybe make this a pure virtual function?
+  virtual comment_list leading_comments () const;
 
   virtual void set_breakpoint (const std::string& condition)
   {
@@ -107,11 +102,6 @@
 
 private:
 
-  // The input line and column where we found the text that was
-  // eventually converted to this tree node.
-  int m_line_num;
-  int m_column_num;
-
   // NULL if no breakpoint, or a breakpoint condition if there is one.
   std::string *m_bp_cond;
 };
--- a/libinterp/parse-tree/token.cc	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 1993-2024 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 <cassert>
-
-#include "error.h"
-#include "token.h"
-
-OCTAVE_BEGIN_NAMESPACE(octave)
-
-token::token (int tv, const filepos& beg_pos, const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (generic_token),
-    m_tok_info (), m_orig_text ()
-{ }
-
-token::token (int tv, bool is_kw, const filepos& beg_pos,
-              const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv),
-    m_type_tag (is_kw ? keyword_token : generic_token), m_tok_info (),
-    m_orig_text ()
-{ }
-
-token::token (int tv, const char *s, const filepos& beg_pos,
-              const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token),
-    m_tok_info (s), m_orig_text ()
-{ }
-
-token::token (int tv, const std::string& s, const filepos& beg_pos,
-              const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (string_token),
-    m_tok_info (s), m_orig_text ()
-{ }
-
-token::token (int tv, const octave_value& val, const std::string& s,
-              const filepos& beg_pos, const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (numeric_token),
-    m_tok_info (val), m_orig_text (s)
-{ }
-
-token::token (int tv, end_tok_type t, const filepos& beg_pos,
-              const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (ettype_token),
-    m_tok_info (t), m_orig_text ()
-{ }
-
-token::token (int tv, const std::string& meth, const std::string& cls,
-              const filepos& beg_pos, const filepos& end_pos)
-  : m_maybe_cmd (false), m_tspc (false), m_beg_pos (beg_pos),
-    m_end_pos (end_pos), m_tok_val (tv), m_type_tag (scls_name_token),
-    m_tok_info (meth, cls), m_orig_text ()
-{ }
-
-token::~token ()
-{
-  if (m_type_tag == string_token)
-    delete m_tok_info.m_str;
-  else if (m_type_tag == numeric_token)
-    delete m_tok_info.m_num;
-  else if (m_type_tag == scls_name_token)
-    delete m_tok_info.m_superclass_info;
-}
-
-std::string
-token::text () const
-{
-  panic_if (m_type_tag != string_token);
-  return *m_tok_info.m_str;
-}
-
-octave_value
-token::number () const
-{
-  panic_if (m_type_tag != numeric_token);
-  return *m_tok_info.m_num;
-}
-
-token::token_type
-token::ttype () const
-{
-  return m_type_tag;
-}
-
-token::end_tok_type
-token::ettype () const
-{
-  panic_if (m_type_tag != ettype_token);
-  return m_tok_info.m_et;
-}
-
-std::string
-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 () const
-{
-  panic_if (m_type_tag != scls_name_token);
-  return m_tok_info.m_superclass_info->m_class_name;
-}
-
-std::string
-token::text_rep () const
-{
-  return m_orig_text;
-}
-
-OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/parse-tree/token.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/parse-tree/token.h	Fri Apr 12 15:10:26 2024 +0200
@@ -29,7 +29,10 @@
 #include "octave-config.h"
 
 #include <string>
+#include <variant>
 
+#include "comment-list.h"
+#include "error.h"
 #include "filepos.h"
 #include "ov.h"
 
@@ -41,6 +44,7 @@
 
   enum token_type
   {
+    invalid_token,
     generic_token,
     keyword_token,
     string_token,
@@ -69,29 +73,41 @@
     while_end,
   };
 
-  token (int tv, const filepos& beg_pos, const filepos& end_pos);
+public:
 
-  token (int tv, bool is_keyword, const filepos& beg_pos
-         , const filepos& end_pos);
+  token ()
+    : m_type_tag (invalid_token)
+  { }
 
-  token (int tv, const char *s, const filepos& beg_pos,
-         const filepos& end_pos);
+  token (int id, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_leading_comments (lst)
+  { }
 
-  token (int tv, const std::string& s, const filepos& beg_pos,
-         const filepos& end_pos);
+  token (int id, bool is_kw, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (is_kw ? keyword_token : generic_token), m_leading_comments (lst)
+  { }
+
+  token (int id, const char *s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (string_token), m_tok_info (s), m_leading_comments (lst)
+  { }
 
-  token (int tv, const octave_value& val, const std::string& s,
-         const filepos& beg_pos, const filepos& end_pos);
+  token (int id, const std::string& s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (string_token), m_tok_info (s), m_leading_comments (lst)
+  { }
 
-  token (int tv, end_tok_type t, const filepos& beg_pos,
-         const filepos& end_pos);
+  token (int id, const octave_value& val, const std::string& s, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (numeric_token), m_tok_info (val), m_orig_text (s), m_leading_comments (lst)
+  { }
 
-  token (int tv, const std::string& mth, const std::string& cls,
-         const filepos& beg_pos, const filepos& end_pos);
+  token (int id, end_tok_type t, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (ettype_token), m_tok_info (t), m_leading_comments (lst)
+  { }
 
-  OCTAVE_DISABLE_CONSTRUCT_COPY_MOVE (token)
+  token (int id, const std::string& meth, const std::string& cls, const filepos& beg_pos, const filepos& end_pos, const comment_list& lst = comment_list ())
+    : m_beg_pos (beg_pos), m_end_pos (end_pos), m_tok_id (id), m_type_tag (scls_name_token), m_tok_info (meth, cls), m_leading_comments (lst)
+  { }
 
-  ~token ();
+  OCTAVE_DEFAULT_COPY_MOVE_DELETE (token)
 
   void mark_may_be_command () { m_maybe_cmd = true; }
   bool may_be_command () const { return m_maybe_cmd; }
@@ -99,8 +115,15 @@
   void mark_trailing_space () { m_tspc = true; }
   bool space_follows_token () const { return m_tspc; }
 
-  int token_value () const { return m_tok_val; }
-  bool token_value_is (int tv) const { return tv == m_tok_val; }
+  operator bool () const { return m_type_tag != invalid_token; }
+
+  int token_id () const { return m_tok_id; }
+
+  bool token_is (int id) const { return m_tok_id == id; }
+  bool token_is (const token *tok) const
+  {
+    return tok ? token_is (tok->token_id ()) : false;
+  }
 
   filepos beg_pos () const { return m_beg_pos; }
   filepos end_pos () const { return m_end_pos; }
@@ -108,6 +131,12 @@
   void beg_pos (const filepos& pos) { m_beg_pos = pos; }
   void end_pos (const filepos& pos) { m_end_pos = pos; }
 
+  comment_list leading_comments () const { return m_leading_comments; }
+  comment_list trailing_comments () const { return m_trailing_comments; }
+
+  void leading_comments (const comment_list& lst) { m_leading_comments = lst; }
+  void trailing_comments (const comment_list& lst) { m_trailing_comments = lst; }
+
   // These will probably be removed.
   int line () const { return m_beg_pos.line (); }
   int column () const { return m_beg_pos.column (); }
@@ -119,85 +148,119 @@
 
   bool isstring () const { return m_type_tag == string_token; }
 
-  std::string text () const;
-  octave_value number () const;
-  token_type ttype () const;
-  end_tok_type ettype () const;
+  std::string text () const { return m_tok_info.text (); }
+  octave_value number () const { return m_tok_info.number (); }
+  token_type ttype () const { return m_type_tag; }
+  end_tok_type ettype () const { return m_tok_info.ettype (); }
 
-  std::string superclass_method_name () const;
-  std::string superclass_class_name () const;
+  std::string superclass_method_name () const { return m_tok_info.superclass_method_name (); }
+  std::string superclass_class_name () const { return m_tok_info.superclass_class_name (); }
 
-  std::string text_rep () const;
+  std::string text_rep () const { return m_orig_text; }
 
 private:
 
-  bool m_maybe_cmd;
+  bool m_maybe_cmd {false};
 
-  bool m_tspc;
+  bool m_tspc {false};
 
   filepos m_beg_pos;
   filepos m_end_pos;
 
-  int m_tok_val;
-
-  token_type m_type_tag;
+  int m_tok_id {-1};
 
-  union tok_info
-  {
-    tok_info () { }
+  token_type m_type_tag {generic_token};
 
-    tok_info (const char *s) : m_str (new std::string (s)) { }
-
-    tok_info (const std::string& str) : m_str (new std::string (str)) { }
+  class superclass_info
+  {
+  public:
 
-    tok_info (const octave_value& num) : m_num (new octave_value (num)) { }
-
-    tok_info (end_tok_type et) : m_et (et) { }
-
-    tok_info (const std::string& meth, const std::string& cls)
-      : m_superclass_info (new superclass_info (meth, cls))
+    superclass_info (const std::string& meth, const std::string& cls)
+      : m_method_name (meth), m_class_name (cls)
     { }
 
-    OCTAVE_DISABLE_COPY_MOVE (tok_info)
+    OCTAVE_DEFAULT_COPY_MOVE_DELETE (superclass_info)
 
-    ~tok_info () { }
+    std::string method_name () const { return m_method_name; }
+
+    std::string class_name () const { return m_class_name; }
 
-    std::string *m_str;
+  private:
+
+    //--------
 
-    octave_value *m_num;
+    // The name of the method to call.  This is the text before the
+    // "@" and may be of the form "object.method".
+    std::string m_method_name;
 
-    end_tok_type m_et;
+    // The name of the superclass.  This is the text after the "@"
+    // and may be of the form "object.method".
+    std::string m_class_name;
+  };
+
+  class tok_info
+  {
+  public:
 
-    struct superclass_info
-    {
-    public:
-      superclass_info (const std::string& meth, const std::string& cls)
-        : m_method_name (meth), m_class_name (cls)
-      { }
+    tok_info (const char *s) : m_value (std::string (s)) { }
+
+    tok_info (const std::string& str) : m_value (str) { }
+
+    tok_info (const octave_value& num) : m_value (octave_value (num)) { }
+
+    tok_info (end_tok_type et) : m_value (et) { }
+
+    tok_info (const std::string& meth, const std::string& cls) : m_value (superclass_info (meth, cls)) { }
+
+    OCTAVE_DEFAULT_CONSTRUCT_COPY_MOVE_DELETE (tok_info)
 
-      superclass_info () = delete;
-
-      OCTAVE_DISABLE_COPY_MOVE (superclass_info)
+    std::string text () const
+    {
+      panic_unless (std::holds_alternative<std::string> (m_value));
+      return std::get<std::string> (m_value);
+    }
 
-      ~superclass_info () = default;
+    octave_value number () const
+    {
+      panic_unless (std::holds_alternative<octave_value> (m_value));
+      return std::get<octave_value> (m_value);
+    }
 
-      //--------
+    token::end_tok_type ettype () const
+    {
+      panic_unless (std::holds_alternative<end_tok_type> (m_value));
+      return std::get<end_tok_type> (m_value);
+    }
 
-      // The name of the method to call.  This is the text before the
-      // "@" and may be of the form "object.method".
-      std::string m_method_name;
+    std::string
+    superclass_method_name () const
+    {
+      panic_unless (std::holds_alternative<superclass_info> (m_value));
+      return std::get<superclass_info> (m_value).method_name ();
+    }
 
-      // The name of the superclass.  This is the text after the "@"
-      // and may be of the form "object.method".
-      std::string m_class_name;
-    };
+    std::string
+    superclass_class_name () const
+    {
+      panic_unless (std::holds_alternative<superclass_info> (m_value));
+      return std::get<superclass_info> (m_value).class_name ();
+    }
 
-    superclass_info *m_superclass_info;
+  private:
+
+    std::variant<std::string, octave_value, end_tok_type, superclass_info> m_value;
   };
 
   tok_info m_tok_info;
 
   std::string m_orig_text;
+
+  // Comments that appear prior to the token.
+  comment_list m_leading_comments;
+
+  // Comments that appear after the token.  This list is only used to
+  // hold comments that appear after the last token in a file.
+  comment_list m_trailing_comments;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/libinterp/usage.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/libinterp/usage.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,14 +34,12 @@
 
 // Usage message
 static const char *usage_string =
-  "octave [-HVWdfhiqvx] [--debug] [--doc-cache-file file] [--echo-commands]\n\
-       [--eval CODE] [--exec-path path] [--experimental-terminal-widget]\n\
-       [--gui] [--help] [--image-path path] [--info-file file]\n\
-       [--info-program prog] [--interactive] [--line-editing] [--no-gui]\n\
-       [--no-history] [--no-init-file] [--no-init-path] [--no-line-editing]\n\
-       [--no-site-file] [--no-window-system] [--norc] [-p path]\n\
-       [--path path] [--persist] [--server] [--silent] [--traditional]\n\
-       [--verbose] [--version] [file]";
+  "octave [-GHVWefghiqvx] [--echo-commands] [--eval CODE]\n\
+       [--experimental-terminal-widget] [--gui] [--help] [--interactive]\n\
+       [--line-editing] [--no-gui] [--no-history] [--no-init-all]\n\
+       [--no-init-path] [--no-init-site] [--no-init-user]\n\
+       [--no-line-editing] [--no-window-system] [--path path] [--persist]\n\
+       [--quiet] [--server] [--traditional] [--version] [file]";
 
 // Usage message with extra help.
 
@@ -54,37 +52,34 @@
 Usage: octave [options] [FILE]\n\
 \n\
 Options:\n\
-\n\
-  --built-in-docstrings-file FILE Use docs for built-ins from FILE.\n\
-  --debug, -d             Enter parser debugging mode.\n\
-  --doc-cache-file FILE   Use doc cache file FILE.\n\
+\n"
+// FIXME: Disabled debug option for parser 2023-12-29.
+// Uncomment and restore code if Octave adds capability to
+// immediately enter debug mode for a script.
+//--debug, -d             Enter debugging mode.\n\ //
+"\
   --echo-commands, -x     Echo commands as they are executed.\n\
-  --eval CODE             Evaluate CODE.  Exit when done unless --persist.\n\
-  --exec-path PATH        Set path for executing subprograms.\n\
+  --eval, -e CODE         Evaluate CODE.  Exit when done unless --persist.\n\
   --experimental-terminal-widget\n\
                           Use new experimental terminal widget in the GUI.\n\
-  --gui                   Start the graphical user interface.\n\
+  --gui, -g               Start the graphical user interface.\n\
   --help, -h,             Print short help message and exit.\n\
-  --image-path PATH       Add PATH to head of image search path.\n\
-  --info-file FILE        Use top-level info file FILE.\n\
-  --info-program PROGRAM  Use PROGRAM for reading info files.\n\
   --interactive, -i       Force interactive behavior.\n\
   --line-editing          Force readline use for command-line editing.\n\
-  --no-gui                Disable the graphical user interface.\n\
+  --no-gui, -G            Disable the graphical user interface.\n\
   --no-history, -H        Don't save commands to the history list\n\
-  --no-init-file          Don't read the ~/.octaverc or .octaverc files.\n\
+  --no-init-all, --norc, -f\n\
+                          Don't read any initialization files.\n\
   --no-init-path          Don't initialize function search path.\n\
+  --no-init-site          Don't read the site-wide octaverc files.\n\
+  --no-init-user          Don't read the ~/.octaverc or .octaverc files.\n\
   --no-line-editing       Don't use readline for command-line editing.\n\
-  --no-site-file          Don't read the site-wide octaverc file.\n\
   --no-window-system, -W  Disable window system, including graphics.\n\
-  --norc, -f              Don't read any initialization files.\n\
   --path PATH, -p PATH    Add PATH to head of function search path.\n\
   --persist               Go interactive after --eval or reading from FILE.\n\
   --server                Enter server mode at startup.\n\
-  --silent, --quiet, -q   Don't print message at startup.\n\
-  --texi-macros-file FILE Use Texinfo macros in FILE for makeinfo command.\n\
+  --quiet, --silent, -q   Don't print message at startup.\n\
   --traditional           Set variables for closer MATLAB compatibility.\n\
-  --verbose, -V           Enable verbose output in some cases.\n\
   --version, -v           Print version number and exit.\n\
 \n\
   FILE                    Execute commands from FILE.  Exit when done\n\
--- a/liboctave/array/Array-base.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Array-base.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -35,6 +35,7 @@
 
 #include "Array-util.h"
 #include "Array.h"
+#include "lo-error.h"
 #include "lo-mappers.h"
 #include "oct-locbuf.h"
 
@@ -210,6 +211,13 @@
 }
 
 template <typename T, typename Alloc>
+octave_idx_type
+Array<T, Alloc>::compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const
+{
+  return m_dimensions.compute_index (ra_idx.data (), ra_idx.numel ());
+}
+
+template <typename T, typename Alloc>
 T&
 Array<T, Alloc>::checkelem (octave_idx_type n)
 {
@@ -318,7 +326,7 @@
     : m_n (dv.ndims ()), m_top (0), m_dim (new octave_idx_type [2*m_n]),
       m_stride (m_dim + m_n), m_use_blk (false)
   {
-    assert (m_n == perm.numel ());
+    liboctave_panic_unless (m_n == perm.numel ());
 
     // Get cumulative dimensions.
     OCTAVE_LOCAL_BUFFER (octave_idx_type, cdim, m_n+1);
@@ -508,7 +516,7 @@
   if (numel () > 0)
     {
       rec_permute_helper rh (dv, perm_vec);
-      rh.permute (data (), retval.fortran_vec ());
+      rh.permute (data (), retval.rwdata ());
     }
 
   return retval;
@@ -528,7 +536,7 @@
     : 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])
   {
-    assert (m_n > 0 && dv.ndims () == std::max (m_n, static_cast<octave_idx_type> (2)));
+    liboctave_panic_unless (m_n > 0 && dv.ndims () == std::max (m_n, static_cast<octave_idx_type> (2)));
 
     m_dim[0] = dv(0);
     m_cdim[0] = 1;
@@ -645,7 +653,7 @@
     : m_cext (nullptr), m_sext (nullptr), m_dext (nullptr), m_n (0)
   {
     int l = ndv.ndims ();
-    assert (odv.ndims () == l);
+    liboctave_panic_unless (odv.ndims () == l);
     octave_idx_type ld = 1;
     int i = 0;
     for (; i < l-1 && ndv(i) == odv(i); i++) ld *= ndv(i);
@@ -749,7 +757,7 @@
           // Indexed object and index are both vectors.  Set result size
           // and orientation as above.
 
-          dim_vector dv = dims ();
+          const dim_vector& dv = dims ();
 
           result_dims = dv.make_nd_vector (idx_len);
         }
@@ -765,7 +773,7 @@
           retval = Array<T, Alloc> (result_dims);
 
           if (idx_len != 0)
-            i.index (data (), n, retval.fortran_vec ());
+            i.index (data (), n, retval.rwdata ());
         }
     }
 
@@ -777,7 +785,7 @@
 Array<T, Alloc>::index (const octave::idx_vector& i, const octave::idx_vector& j) const
 {
   // Get dimensions, allowing Fortran indexing in the 2nd dim.
-  dim_vector dv = m_dimensions.redim (2);
+  const dim_vector& dv = m_dimensions.redim (2);
   octave_idx_type r = dv(0);
   octave_idx_type c = dv(1);
   Array<T, Alloc> retval;
@@ -811,7 +819,7 @@
               // Don't use resize to avoid useless initialization for POD types.
               retval = Array<T, Alloc> (dim_vector (il, jl));
 
-              ii.index (data (), n, retval.fortran_vec ());
+              ii.index (data (), n, retval.rwdata ());
             }
         }
       else
@@ -820,7 +828,7 @@
           retval = Array<T, Alloc> (dim_vector (il, jl));
 
           const T *src = data ();
-          T *dest = retval.fortran_vec ();
+          T *dest = retval.rwdata ();
 
           for (octave_idx_type k = 0; k < jl; k++)
             dest += i.index (src + r * j.xelem (k), r, dest);
@@ -884,7 +892,7 @@
               retval = Array<T, Alloc> (rdv);
 
               // Do it.
-              rh.index (data (), retval.fortran_vec ());
+              rh.index (data (), retval.rwdata ());
             }
         }
     }
@@ -951,10 +959,10 @@
         }
       else
         {
-          static const octave_idx_type max_stack_chunk = 1024;
-          octave_idx_type nn = n + std::min (nx, max_stack_chunk);
+          static const octave_idx_type MAX_STACK_CHUNK = 1024;
+          octave_idx_type nn = n + std::min (nx, MAX_STACK_CHUNK);
           Array<T, Alloc> tmp (Array<T, Alloc> (dim_vector (nn, 1)), dv, 0, n);
-          T *dest = tmp.fortran_vec ();
+          T *dest = tmp.rwdata ();
 
           std::copy_n (data (), nx, dest);
           dest[nx] = rfv;
@@ -965,7 +973,7 @@
   else if (n != nx)
     {
       Array<T, Alloc> tmp = Array<T, Alloc> (dv);
-      T *dest = tmp.fortran_vec ();
+      T *dest = tmp.rwdata ();
 
       octave_idx_type n0 = std::min (n, nx);
       octave_idx_type n1 = n - n0;
@@ -988,7 +996,7 @@
   if (r != rx || c != cx)
     {
       Array<T, Alloc> tmp = Array<T, Alloc> (dim_vector (r, c));
-      T *dest = tmp.fortran_vec ();
+      T *dest = tmp.rwdata ();
 
       octave_idx_type r0 = std::min (r, rx);
       octave_idx_type r1 = r - r0;
@@ -1035,7 +1043,7 @@
       rec_resize_helper rh (dv, m_dimensions.redim (dvl));
 
       // Do it.
-      rh.resize_fill (data (), tmp.fortran_vec (), rfv);
+      rh.resize_fill (data (), tmp.rwdata (), rfv);
       *this = tmp;
     }
 }
@@ -1072,7 +1080,7 @@
   Array<T, Alloc> tmp = *this;
   if (resize_ok)
     {
-      dim_vector dv = m_dimensions.redim (2);
+      const dim_vector& dv = m_dimensions.redim (2);
       octave_idx_type r = dv(0);
       octave_idx_type c = dv(1);
       octave_idx_type rx = i.extent (r);
@@ -1101,7 +1109,7 @@
   if (resize_ok)
     {
       int ial = ia.numel ();
-      dim_vector dv = m_dimensions.redim (ial);
+      const dim_vector& dv = m_dimensions.redim (ial);
       dim_vector dvx = dim_vector::alloc (ial);
       for (int i = 0; i < ial; i++)
         dvx(i) = ia(i).extent (dv(i));
@@ -1124,6 +1132,13 @@
 }
 
 template <typename T, typename Alloc>
+Array<T, Alloc>
+Array<T, Alloc>::index (const Array<octave::idx_vector>& ia, bool resize_ok) const
+{
+  return index (ia, resize_ok, resize_fill_value ());
+}
+
+template <typename T, typename Alloc>
 void
 Array<T, Alloc>::assign (const octave::idx_vector& i, const Array<T, Alloc>& rhs, const T& rfv)
 {
@@ -1163,9 +1178,9 @@
   else
     {
       if (rhl == 1)
-        i.fill (rhs(0), n, fortran_vec ());
+        i.fill (rhs(0), n, rwdata ());
       else
-        i.assign (rhs.data (), n, fortran_vec ());
+        i.assign (rhs.data (), n, rwdata ());
     }
 }
 
@@ -1243,7 +1258,7 @@
           octave::idx_vector ii (i);
 
           const T *src = rhs.data ();
-          T *dest = fortran_vec ();
+          T *dest = rwdata ();
 
           // Try reduction first.
           if (ii.maybe_reduce (r, j, c))
@@ -1367,9 +1382,9 @@
 
               // Do it.
               if (isfill)
-                rh.fill (rhs(0), fortran_vec ());
+                rh.fill (rhs(0), rwdata ());
               else
-                rh.assign (rhs.data (), fortran_vec ());
+                rh.assign (rhs.data (), rwdata ());
             }
         }
       else
@@ -1394,6 +1409,14 @@
     }
 }
 
+template <typename T, typename Alloc>
+void
+Array<T, Alloc>::assign (const Array<octave::idx_vector>& ia,
+                         const Array<T, Alloc>& rhs)
+{
+  assign (ia, rhs, resize_fill_value ());
+}
+
 /*
 %!shared a
 %! a = [1 2; 3 4];
@@ -1429,7 +1452,7 @@
           octave_idx_type m = n + l - u;
           Array<T, Alloc> tmp (dim_vector (col_vec ? m : 1, ! col_vec ? m : 1));
           const T *src = data ();
-          T *dest = tmp.fortran_vec ();
+          T *dest = tmp.rwdata ();
           std::copy_n (src, l, dest);
           std::copy (src + u, src + n, dest + l);
           *this = tmp;
@@ -1482,7 +1505,7 @@
           // Special case deleting a contiguous range.
           Array<T, Alloc> tmp = Array<T, Alloc> (rdv);
           const T *src = data ();
-          T *dest = tmp.fortran_vec ();
+          T *dest = tmp.rwdata ();
           l *= dl; u *= dl; n *= dl;
           for (octave_idx_type k = 0; k < du; k++)
             {
@@ -1622,7 +1645,7 @@
 Array<T, Alloc>
 Array<T, Alloc>::transpose () const
 {
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1633,7 +1656,7 @@
 
       // Reuse the implementation used for permuting.
 
-      rec_permute_helper::blk_trans (data (), result.fortran_vec (), nr, nc);
+      rec_permute_helper::blk_trans (data (), result.rwdata (), nr, nc);
 
       return result;
     }
@@ -1665,7 +1688,7 @@
 Array<T, Alloc>
 Array<T, Alloc>::hermitian (T (*fcn) (const T&)) const
 {
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   if (! fcn)
     fcn = no_op_fcn<T>;
@@ -1761,7 +1784,7 @@
 
 template <typename T, typename Alloc>
 T *
-Array<T, Alloc>::fortran_vec ()
+Array<T, Alloc>::rwdata ()
 {
   make_unique ();
 
@@ -1800,7 +1823,7 @@
   for (int i = 0; i < dim; i++)
     stride *= dv(i);
 
-  T *v = m.fortran_vec ();
+  T *v = m.rwdata ();
   const T *ov = data ();
 
   octave_sort<T> lsort;
@@ -1898,7 +1921,7 @@
 
   Array<T, Alloc> m (dims ());
 
-  dim_vector dv = m.dims ();
+  const dim_vector& dv = m.dims ();
 
   if (m.numel () < 1)
     {
@@ -1913,13 +1936,13 @@
   for (int i = 0; i < dim; i++)
     stride *= dv(i);
 
-  T *v = m.fortran_vec ();
+  T *v = m.rwdata ();
   const T *ov = data ();
 
   octave_sort<T> lsort;
 
   sidx = Array<octave_idx_type> (dv);
-  octave_idx_type *vi = sidx.fortran_vec ();
+  octave_idx_type *vi = sidx.rwdata ();
 
   if (mode != UNSORTED)
     lsort.set_compare (mode);
@@ -2087,7 +2110,7 @@
 
   idx = Array<octave_idx_type> (dim_vector (r, 1));
 
-  lsort.sort_rows (data (), idx.fortran_vec (), r, c);
+  lsort.sort_rows (data (), idx.rwdata (), r, c);
 
   return idx;
 }
@@ -2196,11 +2219,11 @@
 
   // This determines the split ratio between the O(M*log2(N)) and O(M+N)
   // algorithms.
-  static const double ratio = 1.0;
+  static const double RATIO = 1.0;
   sortmode vmode = UNSORTED;
 
   // Attempt the O(M+N) algorithm if M is large enough.
-  if (nval > ratio * n / octave::math::log2 (n + 1.0))
+  if (nval > RATIO * n / octave::math::log2 (n + 1.0))
     {
       vmode = values.issorted ();
       // The table must not contain a NaN.
@@ -2211,9 +2234,9 @@
 
   if (vmode != UNSORTED)
     lsort.lookup_sorted (data (), n, values.data (), nval,
-                         idx.fortran_vec (), vmode != mode);
+                         idx.rwdata (), vmode != mode);
   else
-    lsort.lookup (data (), n, values.data (), nval, idx.fortran_vec ());
+    lsort.lookup (data (), n, values.data (), nval, idx.rwdata ());
 
   return idx;
 }
@@ -2250,7 +2273,7 @@
         cnt += src[i] != zero;
 
       retval.clear (cnt, 1);
-      octave_idx_type *dest = retval.fortran_vec ();
+      octave_idx_type *dest = retval.rwdata ();
       for (octave_idx_type i = 0; i < nel; i++)
         if (src[i] != zero) *dest++ = i;
     }
@@ -2275,7 +2298,7 @@
             }
           if (k < n)
             retval.resize2 (k, 1);
-          octave_idx_type *rdata = retval.fortran_vec ();
+          octave_idx_type *rdata = retval.rwdata ();
           std::reverse (rdata, rdata + k);
         }
       else
@@ -2400,7 +2423,7 @@
   for (int i = 0; i < dim; i++)
     stride *= dv(i);
 
-  T *v = m.fortran_vec ();
+  T *v = m.rwdata ();
   const T *ov = data ();
 
   OCTAVE_LOCAL_BUFFER (T, buf, ns);
@@ -2540,7 +2563,7 @@
 Array<T, Alloc>
 Array<T, Alloc>::diag (octave_idx_type k) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nd = dv.ndims ();
   Array<T, Alloc> d;
 
@@ -2685,7 +2708,7 @@
     {
       for (octave_idx_type i = 0; i < n; i++)
         {
-          dim_vector dv = array_list[i].dims ();
+          const dim_vector& dv = array_list[i].dims ();
 
           if (dv.zero_by_zero ())
             istart++;
@@ -2791,7 +2814,7 @@
 std::ostream&
 operator << (std::ostream& os, const Array<T, Alloc>& a)
 {
-  dim_vector a_dims = a.dims ();
+  const dim_vector& a_dims = a.dims ();
 
   int n_dims = a_dims.ndims ();
 
--- a/liboctave/array/Array-util.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Array-util.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -264,7 +264,7 @@
 
   int n = ra_idx.numel ();
 
-  assert (n == dimensions.ndims ());
+  liboctave_panic_unless (n == dimensions.ndims ());
 
   retval.resize (n);
 
@@ -337,7 +337,9 @@
 
   int n = frozen_lengths.ndims ();
 
-  assert (idx_n == n);
+  if (idx_n != n)
+    (*current_liboctave_error_handler)
+      ("unexpected: idx_n != n in all_colon_equiv - please report this bug");
 
   for (octave_idx_type i = 0; i < n; i++)
     {
@@ -394,7 +396,7 @@
   for (int i = 0; i < n_dims; i++)
     retval(i) = 0;
 
-  assert (idx > 0 || idx < dims.numel ());
+  liboctave_panic_unless (idx > 0 || idx < dims.numel ());
 
   for (octave_idx_type i = 0; i < idx; i++)
     increment_index (retval, dims);
@@ -574,16 +576,10 @@
           // Initialized inside the loop so that each call to
           // idx_vector::loop operates from the beginning of IDX_VEC.
 
-          octave_idx_type *idx_vec = idx.fortran_vec ();
+          octave_idx_type *idx_vec = idx.rwdata ();
 
           if (i < len - 1)
-            {
-              octave_idx_type n = dvx(i);
-
-              idxa(i).loop (clen, [=, &idx_vec] (octave_idx_type k) {
-                (*idx_vec++ *= n) += k;
-              });
-            }
+            idxa(i).loop (clen, [n = dvx(i), &idx_vec] (octave_idx_type k) { (*idx_vec++ *= n) += k; });
           else
             idxa(i).copy_data (idx_vec);
         }
@@ -617,7 +613,7 @@
     {
       OCTAVE_LOCAL_BUFFER (Array<octave_idx_type>, rdata, n);
 
-      dim_vector odv = idx.orig_dimensions ();
+      const dim_vector& odv = idx.orig_dimensions ();
       for (octave_idx_type j = 0; j < n; j++)
         rdata[j] = Array<octave_idx_type> (odv);
 
--- a/liboctave/array/Array.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Array.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,6 @@
 
 #include "octave-config.h"
 
-#include <cassert>
 #include <cstddef>
 
 #include <algorithm>
@@ -123,15 +122,16 @@
 //!   - string_vector: Array<std::string> with 1 column
 //!   - Cell: Array<octave_value>, equivalent to an Octave cell.
 
+// forward declare template with visibility attributes
+template <typename T, typename Alloc> class OCTARRAY_API Array;
+
 template <typename T, typename Alloc>
-class
-OCTARRAY_TEMPLATE_API
-Array
+class OCTARRAY_TEMPLATE_API Array
 {
 protected:
 
   //! The real representation of all arrays.
-  class ArrayRep : public Alloc
+  class OCTARRAY_TEMPLATE_API ArrayRep : public Alloc
   {
   public:
 
@@ -144,6 +144,7 @@
     octave_idx_type m_len;
     octave::refcount<octave_idx_type> m_count;
 
+    OCTARRAY_OVERRIDABLE_FUNC_API
     ArrayRep (pointer d, octave_idx_type len)
       : Alloc (), m_data (allocate (len)), m_len (len), m_count (1)
     {
@@ -157,8 +158,8 @@
       std::copy_n (d, len, m_data);
     }
 
-    // Use new instead of setting data to 0 so that fortran_vec and
-    // data always return valid addresses, even for zero-size arrays.
+    // Use new instead of setting data to 0 so that rwdata() and data()
+    // always return valid addresses, even for zero-size arrays.
 
     ArrayRep ()
       : Alloc (), m_data (allocate (0)), m_len (0), m_count (1) { }
@@ -187,13 +188,16 @@
 
     ~ArrayRep () { deallocate (m_data, m_len); }
 
-    octave_idx_type numel () const { return m_len; }
+    OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type numel () const
+    {
+      return m_len;
+    }
 
     // No assignment!
 
     ArrayRep& operator = (const ArrayRep&) = delete;
 
-    pointer allocate (size_t len)
+    OCTARRAY_OVERRIDABLE_FUNC_API pointer allocate (size_t len)
     {
       pointer data = Alloc_traits::allocate (*this, len);
       for (size_t i = 0; i < len; i++)
@@ -201,7 +205,7 @@
       return data;
     }
 
-    void deallocate (pointer data, size_t len)
+    OCTARRAY_OVERRIDABLE_FUNC_API void deallocate (pointer data, size_t len)
     {
       for (size_t i = 0; i < len; i++)
         T_Alloc_traits::destroy (*this, data+i);
@@ -513,11 +517,8 @@
   OCTARRAY_API octave_idx_type
   compute_index (const Array<octave_idx_type>& ra_idx) const;
 
-  OCTARRAY_OVERRIDABLE_FUNC_API octave_idx_type
-  compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const
-  {
-    return m_dimensions.compute_index (ra_idx.data (), ra_idx.numel ());
-  }
+  OCTARRAY_API octave_idx_type
+  compute_index_unchecked (const Array<octave_idx_type>& ra_idx) const;
 
   // No checking, even for multiple references, ever.
 
@@ -660,10 +661,17 @@
   OCTARRAY_API Array<T, Alloc> transpose () const;
   OCTARRAY_API Array<T, Alloc> hermitian (T (*fcn) (const T&) = nullptr) const;
 
+  // Use for direct read-only access to Array data.
   OCTARRAY_OVERRIDABLE_FUNC_API const T * data () const
   { return m_slice_data; }
 
-  OCTARRAY_API T * fortran_vec ();
+  // Use for direct read-write access to Array data.
+  OCTARRAY_API T * rwdata ();
+
+  // Alias for direct read-write access to Array data.
+  // FIXME: It is recommended to use rwdata() in future code for clarity.
+  inline T * fortran_vec ()
+  { return rwdata (); }
 
   OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared () const
   { return m_rep->m_count > 1; }
@@ -726,11 +734,8 @@
   OCTARRAY_API Array<T, Alloc>
   index (const Array<octave::idx_vector>& ia, bool resize_ok,
          const T& rfv) const;
-  OCTARRAY_OVERRIDABLE_FUNC_API Array<T, Alloc>
-  index (const Array<octave::idx_vector>& ia, bool resize_ok) const
-  {
-    return index (ia, resize_ok, resize_fill_value ());
-  }
+  OCTARRAY_API Array<T, Alloc>
+  index (const Array<octave::idx_vector>& ia, bool resize_ok) const;
   //@}
 
   //@{
@@ -755,11 +760,8 @@
 
   OCTARRAY_API void
   assign (const Array<octave::idx_vector>& ia, const Array<T, Alloc>& rhs, const T& rfv);
-  OCTARRAY_OVERRIDABLE_FUNC_API void
-  assign (const Array<octave::idx_vector>& ia, const Array<T, Alloc>& rhs)
-  {
-    assign (ia, rhs, resize_fill_value ());
-  }
+  OCTARRAY_API void
+  assign (const Array<octave::idx_vector>& ia, const Array<T, Alloc>& rhs);
   //@}
 
   //@{
@@ -863,7 +865,7 @@
     const T *m = data ();
 
     Array<U, A> result (dims ());
-    U *p = result.fortran_vec ();
+    U *p = result.rwdata ();
 
     octave_idx_type i;
     for (i = 0; i < len - 3; i += 4)
--- a/liboctave/array/CColVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CColVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -262,7 +262,7 @@
   if (len == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_add2 (len, d, a.data ());
   return *this;
@@ -281,7 +281,7 @@
   if (len == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_sub2 (len, d, a.data ());
   return *this;
@@ -317,7 +317,7 @@
         retval.fill (0.0);
       else
         {
-          Complex *y = retval.fortran_vec ();
+          Complex *y = retval.rwdata ();
 
           F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("N", 1),
                                    nr, nc, 1.0,
--- a/liboctave/array/CColVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CColVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-ComplexColumnVector : public MArray<Complex>
+class OCTAVE_API ComplexColumnVector : public MArray<Complex>
 {
   friend class ComplexMatrix;
   friend class ComplexRowVector;
--- a/liboctave/array/CDiagMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CDiagMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -345,7 +345,7 @@
   else if (z_count > 0)
     {
       info = -1;
-      element_type *data = retval.fortran_vec ();
+      element_type *data = retval.rwdata ();
       std::fill (data, data + len, octave::numeric_limits<double>::Inf ());
     }
 
@@ -396,7 +396,7 @@
   if (r == 0 || c == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_add2 (length (), d, a.data ());
   return *this;
--- a/liboctave/array/CDiagMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CDiagMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 #include "dRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-ComplexDiagMatrix : public MDiagArray2<Complex>
+class OCTAVE_API ComplexDiagMatrix : public MDiagArray2<Complex>
 {
 public:
 
--- a/liboctave/array/CMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -28,6 +28,7 @@
 #endif
 
 #include <algorithm>
+#include <cmath>
 #include <complex>
 #include <istream>
 #include <limits>
@@ -733,13 +734,21 @@
   return anorm;
 }
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const double rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());
+}
+
 ComplexMatrix
 ComplexMatrix::inverse () const
 {
   octave_idx_type info;
   double rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 ComplexMatrix
@@ -747,7 +756,7 @@
 {
   double rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 ComplexMatrix
@@ -763,14 +772,14 @@
 {
   octave_idx_type info;
   double rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 ComplexMatrix
 ComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const
 {
   double rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 ComplexMatrix
@@ -789,7 +798,7 @@
   char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
   char udiag = 'N';
   retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
+  Complex *tmp_data = retval.rwdata ();
 
   F77_INT tmp_info = 0;
 
@@ -845,10 +854,10 @@
     (*current_liboctave_error_handler) ("inverse requires square matrix");
 
   Array<F77_INT> ipvt (dim_vector (nr, 1));
-  F77_INT *pipvt = ipvt.fortran_vec ();
+  F77_INT *pipvt = ipvt.rwdata ();
 
   retval = *this;
-  Complex *tmp_data = retval.fortran_vec ();
+  Complex *tmp_data = retval.rwdata ();
 
   Array<Complex> z (dim_vector (1, 1));
   F77_INT lwork = -1;
@@ -858,13 +867,13 @@
   F77_INT tmp_info = 0;
 
   F77_XFCN (zgetri, ZGETRI, (nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, pipvt,
-                             F77_DBLE_CMPLX_ARG (z.fortran_vec ()), lwork,
+                             F77_DBLE_CMPLX_ARG (z.rwdata ()), lwork,
                              tmp_info));
 
   lwork = static_cast<F77_INT> (std::real (z(0)));
   lwork = (lwork < 2 * nc ? 2 * nc : lwork);
   z.resize (dim_vector (lwork, 1));
-  Complex *pz = z.fortran_vec ();
+  Complex *pz = z.rwdata ();
 
   info = 0;
   tmp_info = 0;
@@ -899,7 +908,7 @@
           // Now calculate the condition number for non-singular matrix.
           char job = '1';
           Array<double> rz (dim_vector (2 * nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
           F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                      nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,
                                      anorm, rcon, F77_DBLE_CMPLX_ARG (pz), prz,
@@ -1063,7 +1072,7 @@
     }
 
   const Complex *in (data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::fft (in, out, npts, nsamples);
 
@@ -1092,7 +1101,7 @@
     }
 
   const Complex *in (data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifft (in, out, npts, nsamples);
 
@@ -1106,7 +1115,7 @@
 
   ComplexMatrix retval (rows (), cols ());
   const Complex *in (data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, 2, dv);
 
@@ -1120,7 +1129,7 @@
 
   ComplexMatrix retval (rows (), cols ());
   const Complex *in (data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, 2, dv);
 
@@ -1206,7 +1215,7 @@
   if (nr != nc)
     (*current_liboctave_error_handler) ("matrix must be square");
 
-  volatile int typ = mattype.type ();
+  int typ = mattype.type ();
 
   // Even though the matrix is marked as singular (Rectangular), we may
   // still get a useful number from the LU factorization, because it always
@@ -1225,7 +1234,7 @@
   else if (typ == MatrixType::Hermitian)
     {
       ComplexMatrix atmp = *this;
-      Complex *tmp_data = atmp.fortran_vec ();
+      Complex *tmp_data = atmp.rwdata ();
 
       double anorm;
       if (calc_cond)
@@ -1251,9 +1260,9 @@
           if (calc_cond)
             {
               Array<Complex> z (dim_vector (2 * nc, 1));
-              Complex *pz = z.fortran_vec ();
+              Complex *pz = z.rwdata ();
               Array<double> rz (dim_vector (nc, 1));
-              double *prz = rz.fortran_vec ();
+              double *prz = rz.rwdata ();
 
               F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1278,10 +1287,10 @@
   if (typ == MatrixType::Full)
     {
       Array<F77_INT> ipvt (dim_vector (nr, 1));
-      F77_INT *pipvt = ipvt.fortran_vec ();
+      F77_INT *pipvt = ipvt.rwdata ();
 
       ComplexMatrix atmp = *this;
-      Complex *tmp_data = atmp.fortran_vec ();
+      Complex *tmp_data = atmp.rwdata ();
 
       info = 0;
 
@@ -1315,9 +1324,9 @@
               // Now calc the condition number for non-singular matrix.
               char job = '1';
               Array<Complex> z (dim_vector (2 * nc, 1));
-              Complex *pz = z.fortran_vec ();
+              Complex *pz = z.rwdata ();
               Array<double> rz (dim_vector (2 * nc, 1));
-              double *prz = rz.fortran_vec ();
+              double *prz = rz.rwdata ();
 
               F77_XFCN (zgecon, ZGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nc, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1367,7 +1376,7 @@
     rcon = octave::numeric_limits<double>::Inf ();
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Unknown)
         typ = mattype.type (*this);
@@ -1382,9 +1391,9 @@
           char dia = 'N';
 
           Array<Complex> z (dim_vector (2 * nc, 1));
-          Complex *pz = z.fortran_vec ();
+          Complex *pz = z.rwdata ();
           Array<double> rz (dim_vector (nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
 
           F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1410,9 +1419,9 @@
           char dia = 'N';
 
           Array<Complex> z (dim_vector (2 * nc, 1));
-          Complex *pz = z.fortran_vec ();
+          Complex *pz = z.rwdata ();
           Array<double> rz (dim_vector (nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
 
           F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1439,7 +1448,7 @@
               char job = 'L';
 
               ComplexMatrix atmp = *this;
-              Complex *tmp_data = atmp.fortran_vec ();
+              Complex *tmp_data = atmp.rwdata ();
 
               anorm = norm1 (atmp);
 
@@ -1457,9 +1466,9 @@
               else
                 {
                   Array<Complex> z (dim_vector (2 * nc, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> rz (dim_vector (nc, 1));
-                  double *prz = rz.fortran_vec ();
+                  double *prz = rz.rwdata ();
 
                   F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1476,18 +1485,18 @@
               F77_INT info = 0;
 
               ComplexMatrix atmp = *this;
-              Complex *tmp_data = atmp.fortran_vec ();
+              Complex *tmp_data = atmp.rwdata ();
 
               Array<F77_INT> ipvt (dim_vector (nr, 1));
-              F77_INT *pipvt = ipvt.fortran_vec ();
+              F77_INT *pipvt = ipvt.rwdata ();
 
               if (anorm < 0.0)
                 anorm = norm1 (atmp);
 
               Array<Complex> z (dim_vector (2 * nc, 1));
-              Complex *pz = z.fortran_vec ();
+              Complex *pz = z.rwdata ();
               Array<double> rz (dim_vector (2 * nc, 1));
-              double *prz = rz.fortran_vec ();
+              double *prz = rz.rwdata ();
 
               // Work around bug #45577, LAPACK crashes Octave if norm is NaN
               if (octave::math::isnan (anorm))
@@ -1544,7 +1553,7 @@
     retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)
         (*current_liboctave_error_handler) ("incorrect matrix type");
@@ -1559,7 +1568,7 @@
       const Complex *tmp_data = data ();
 
       retval = b;
-      Complex *result = retval.fortran_vec ();
+      Complex *result = retval.rwdata ();
 
       char uplo = 'U';
       char trans = get_blas_char (transt);
@@ -1585,9 +1594,9 @@
           dia = 'N';
 
           Array<Complex> z (dim_vector (2 * nc, 1));
-          Complex *pz = z.fortran_vec ();
+          Complex *pz = z.rwdata ();
           Array<double> rz (dim_vector (nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
 
           F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1603,9 +1612,7 @@
           if (info != 0)
             info = -2;
 
-          volatile double rcond_plus_one = rcon + 1.0;
-
-          if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+          if (is_singular (rcon) || octave::math::isnan (rcon))
             {
               info = -2;
 
@@ -1642,7 +1649,7 @@
     retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)
         (*current_liboctave_error_handler) ("incorrect matrix type");
@@ -1657,7 +1664,7 @@
       const Complex *tmp_data = data ();
 
       retval = b;
-      Complex *result = retval.fortran_vec ();
+      Complex *result = retval.rwdata ();
 
       char uplo = 'L';
       char trans = get_blas_char (transt);
@@ -1683,9 +1690,9 @@
           dia = 'N';
 
           Array<Complex> z (dim_vector (2 * nc, 1));
-          Complex *pz = z.fortran_vec ();
+          Complex *pz = z.rwdata ();
           Array<double> rz (dim_vector (nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
 
           F77_XFCN (ztrcon, ZTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1701,9 +1708,7 @@
           if (info != 0)
             info = -2;
 
-          volatile double rcond_plus_one = rcon + 1.0;
-
-          if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+          if (is_singular (rcon) || octave::math::isnan (rcon))
             {
               info = -2;
 
@@ -1740,7 +1745,7 @@
     retval = ComplexMatrix (nc, b_nc, Complex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       double anorm = -1.0;
@@ -1751,7 +1756,7 @@
           char job = 'L';
 
           ComplexMatrix atmp = *this;
-          Complex *tmp_data = atmp.fortran_vec ();
+          Complex *tmp_data = atmp.rwdata ();
 
           // The norm of the matrix for later use when determining rcon.
           if (calc_cond)
@@ -1779,9 +1784,9 @@
               if (calc_cond)
                 {
                   Array<Complex> z (dim_vector (2 * nc, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> rz (dim_vector (nc, 1));
-                  double *prz = rz.fortran_vec ();
+                  double *prz = rz.rwdata ();
 
                   F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, F77_DBLE_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1793,9 +1798,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile double rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1809,7 +1812,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   F77_XFCN (zpotrs, ZPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, b_nc, F77_DBLE_CMPLX_ARG (tmp_data), nr,
@@ -1831,15 +1834,15 @@
           info = 0;
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           ComplexMatrix atmp = *this;
-          Complex *tmp_data = atmp.fortran_vec ();
+          Complex *tmp_data = atmp.rwdata ();
 
           Array<Complex> z (dim_vector (2 * nc, 1));
-          Complex *pz = z.fortran_vec ();
+          Complex *pz = z.rwdata ();
           Array<double> rz (dim_vector (2 * nc, 1));
-          double *prz = rz.fortran_vec ();
+          double *prz = rz.rwdata ();
 
           // Calculate the norm of the matrix, for later use.
           if (calc_cond && anorm < 0.0)
@@ -1888,9 +1891,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile double rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       if (sing_handler)
                         sing_handler (rcon);
@@ -1902,7 +1903,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   char job = 'N';
                   F77_XFCN (zgetrs, ZGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -2294,7 +2295,7 @@
     retval = ComplexMatrix (n, b_nc, Complex (0.0, 0.0));
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2310,11 +2311,11 @@
         retval = b;
 
       ComplexMatrix atmp = *this;
-      Complex *tmp_data = atmp.fortran_vec ();
-
-      Complex *pretval = retval.fortran_vec ();
+      Complex *tmp_data = atmp.rwdata ();
+
+      Complex *pretval = retval.rwdata ();
       Array<double> s (dim_vector (minmn, 1));
-      double *ps = s.fortran_vec ();
+      double *ps = s.rwdata ();
 
       // Ask ZGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2353,20 +2354,20 @@
       if (lrwork < 1)
         lrwork = 1;
       Array<double> rwork (dim_vector (lrwork, 1));
-      double *prwork = rwork.fortran_vec ();
+      double *prwork = rwork.rwdata ();
 
       F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,
                                  F77_DBLE_CMPLX_ARG (pretval), maxmn,
-                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.fortran_vec ()),
+                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.rwdata ()),
                                  lwork, prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2423,7 +2424,7 @@
           F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data),
                                      m, F77_DBLE_CMPLX_ARG (pretval),
                                      maxmn, ps, rcon, tmp_rank,
-                                     F77_DBLE_CMPLX_ARG (work.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (work.rwdata ()),
                                      lwork, prwork, piwork, tmp_info));
 
           info = tmp_info;
@@ -2521,7 +2522,7 @@
     retval = ComplexColumnVector (n, Complex (0.0, 0.0));
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2536,11 +2537,11 @@
         retval = b;
 
       ComplexMatrix atmp = *this;
-      Complex *tmp_data = atmp.fortran_vec ();
-
-      Complex *pretval = retval.fortran_vec ();
+      Complex *tmp_data = atmp.rwdata ();
+
+      Complex *pretval = retval.rwdata ();
       Array<double> s (dim_vector (minmn, 1));
-      double *ps = s.fortran_vec ();
+      double *ps = s.rwdata ();
 
       // Ask ZGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2570,20 +2571,20 @@
       if (lrwork < 1)
         lrwork = 1;
       Array<double> rwork (dim_vector (lrwork, 1));
-      double *prwork = rwork.fortran_vec ();
+      double *prwork = rwork.rwdata ();
 
       F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,
                                  F77_DBLE_CMPLX_ARG (pretval), maxmn,
-                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.fortran_vec ()),
+                                 ps, rcon, tmp_rank, F77_DBLE_CMPLX_ARG (work.rwdata ()),
                                  lwork, prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2597,7 +2598,7 @@
       F77_XFCN (zgelsd, ZGELSD, (m, n, nrhs, F77_DBLE_CMPLX_ARG (tmp_data), m,
                                  F77_DBLE_CMPLX_ARG (pretval),
                                  maxmn, ps, rcon, tmp_rank,
-                                 F77_DBLE_CMPLX_ARG (work.fortran_vec ()), lwork,
+                                 F77_DBLE_CMPLX_ARG (work.rwdata ()), lwork,
                                  prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2645,7 +2646,7 @@
       F77_INT a_len = octave::to_f77_int (a.numel ());
 
       retval = ComplexMatrix (len, a_len);
-      Complex *c = retval.fortran_vec ();
+      Complex *c = retval.rwdata ();
 
       F77_XFCN (zgemm, ZGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
                                F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2749,7 +2750,7 @@
   if (nr == 0 || nc == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_add2 (numel (), d, a.data ());
   return *this;
@@ -2770,7 +2771,7 @@
   if (nr == 0 || nc == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_sub2 (numel (), d, a.data ());
   return *this;
@@ -3275,9 +3276,9 @@
   double scale;
   F77_INT info;
 
-  Complex *pa = sch_a.fortran_vec ();
-  Complex *pb = sch_b.fortran_vec ();
-  Complex *px = cx.fortran_vec ();
+  Complex *pa = sch_a.rwdata ();
+  Complex *pb = sch_b.rwdata ();
+  Complex *px = cx.rwdata ();
 
   F77_XFCN (ztrsyl, ZTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
                              F77_CONST_CHAR_ARG2 ("N", 1),
@@ -3374,7 +3375,7 @@
       // use the result matrix before zeroing the elements.
 
       retval = ComplexMatrix (a_nr, b_nc, 0.0);
-      Complex *c = retval.fortran_vec ();
+      Complex *c = retval.rwdata ();
 
       const char ctra = get_blas_trans_arg (tra, cja);
       if (cja || cjb)
@@ -3412,7 +3413,7 @@
       F77_INT tdb = octave::to_f77_int (b.cols ());
 
       retval = ComplexMatrix (a_nr, b_nc, 0.0);
-      Complex *c = retval.fortran_vec ();
+      Complex *c = retval.rwdata ();
 
       if (b_nc == 1 && a_nr == 1)
         {
--- a/liboctave/array/CMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 #include "mx-op-decl.h"
 #include "oct-cmplx.h"
 
-class
-OCTAVE_API
-ComplexMatrix : public ComplexNDArray
+class OCTAVE_API ComplexMatrix : public ComplexNDArray
 {
 public:
 
--- a/liboctave/array/CNDArray.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CNDArray.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,7 @@
 ComplexNDArray
 ComplexNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return ComplexNDArray ();
@@ -75,7 +75,7 @@
 
   const Complex *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -88,7 +88,7 @@
 ComplexNDArray
 ComplexNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return ComplexNDArray ();
@@ -106,7 +106,7 @@
 
   const Complex *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -119,14 +119,14 @@
 ComplexNDArray
 ComplexNDArray::fourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return ComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const Complex *in = data ();
   ComplexNDArray retval (dv);
-  Complex *out = retval.fortran_vec ();
+  Complex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -139,14 +139,14 @@
 ComplexNDArray
 ComplexNDArray::ifourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return ComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const Complex *in = data ();
   ComplexNDArray retval (dv);
-  Complex *out = retval.fortran_vec ();
+  Complex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -159,12 +159,12 @@
 ComplexNDArray
 ComplexNDArray::fourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const Complex *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, rank, dv);
 
@@ -174,12 +174,12 @@
 ComplexNDArray
 ComplexNDArray::ifourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const Complex *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, rank, dv);
 
@@ -507,8 +507,8 @@
 ComplexNDArray&
 ComplexNDArray::insert (const NDArray& a, octave_idx_type r, octave_idx_type c)
 {
-  dim_vector a_dv = a.dims ();
-  dim_vector dv = dims ();
+  const dim_vector& a_dv = a.dims ();
+  const dim_vector& dv = dims ();
 
   int n = a_dv.ndims ();
 
--- a/liboctave/array/CNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-ComplexNDArray : public MArray<Complex>
+class OCTAVE_API ComplexNDArray : public MArray<Complex>
 {
 public:
 
--- a/liboctave/array/CRowVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CRowVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -253,7 +253,7 @@
   if (len == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_add2 (len, d, a.data ());
   return *this;
@@ -272,7 +272,7 @@
   if (len == 0)
     return *this;
 
-  Complex *d = fortran_vec (); // Ensures only one reference to my privates!
+  Complex *d = rwdata (); // Ensures only one reference to my privates!
 
   mx_inline_sub2 (len, d, a.data ());
   return *this;
@@ -302,7 +302,7 @@
       F77_INT ld = a_nr;
 
       retval.resize (a_nc);
-      Complex *y = retval.fortran_vec ();
+      Complex *y = retval.rwdata ();
 
       F77_XFCN (zgemv, ZGEMV, (F77_CONST_CHAR_ARG2 ("T", 1),
                                a_nr, a_nc, 1.0, F77_CONST_DBLE_CMPLX_ARG (a.data ()),
--- a/liboctave/array/CRowVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CRowVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,9 +32,7 @@
 #include "dRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-ComplexRowVector : public MArray<Complex>
+class OCTAVE_API ComplexRowVector : public MArray<Complex>
 {
   friend class ComplexColumnVector;
 
--- a/liboctave/array/CSparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CSparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,11 +27,14 @@
 #  include "config.h"
 #endif
 
+#include <cmath>
 #include <complex>
 #include <istream>
+#include <limits>
 #include <ostream>
 
 #include "quit.h"
+#include "lo-error.h"
 #include "lo-ieee.h"
 #include "lo-mappers.h"
 #include "f77-fcn.h"
@@ -63,12 +66,7 @@
 
 #include "Sparse-perm-op-defs.h"
 
-// Define whether to use a basic QR solver or one that uses a Dulmange
-// Mendelsohn factorization to separate the problem into under-determined,
-// well-determined and over-determined parts and solves them separately
-#if ! defined (USE_QRSOLVE)
-#  include "sparse-dmsolve.h"
-#endif
+#include "sparse-dmsolve.h"
 
 SparseComplexMatrix::SparseComplexMatrix (const SparseMatrix& a)
   : MSparse<Complex> (a)
@@ -193,7 +191,7 @@
 SparseComplexMatrix::max (Array<octave_idx_type>& idx_arg, int dim) const
 {
   SparseComplexMatrix result;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nr = dv(0);
   octave_idx_type nc = dv(1);
 
@@ -350,7 +348,7 @@
 SparseComplexMatrix::min (Array<octave_idx_type>& idx_arg, int dim) const
 {
   SparseComplexMatrix result;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nr = dv(0);
   octave_idx_type nc = dv(1);
 
@@ -629,7 +627,7 @@
         retval.xridx (q) = j;
         retval.xdata (q) = conj (data (k));
       }
-  assert (nnz () == retval.xcidx (nr));
+  liboctave_panic_unless (nnz () == retval.xcidx (nr));
   // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)
   // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets
 
@@ -656,6 +654,14 @@
   return retval;
 }
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const double rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());
+}
+
 SparseComplexMatrix
 SparseComplexMatrix::inverse () const
 {
@@ -1103,7 +1109,7 @@
 
       // Setup the control parameters
       Matrix Control (UMFPACK_CONTROL, 1);
-      double *control = Control.fortran_vec ();
+      double *control = Control.rwdata ();
       UMFPACK_ZNAME (defaults) (control);
 
       double tmp = octave::sparse_params::get_key ("spumoni");
@@ -1139,7 +1145,7 @@
 
       void *Symbolic;
       Matrix Info (1, UMFPACK_INFO);
-      double *info = Info.fortran_vec ();
+      double *info = Info.rwdata ();
       int status = UMFPACK_ZNAME (qsymbolic) (nr, nc,
                                               octave::to_suitesparse_intptr (Ap),
                                               octave::to_suitesparse_intptr (Ai),
@@ -1728,9 +1734,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2010,9 +2014,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2239,9 +2241,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2521,9 +2521,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2770,9 +2768,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3071,9 +3067,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3323,9 +3317,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3623,9 +3615,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3666,7 +3656,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Tridiagonal_Hermitian)
@@ -3709,7 +3699,7 @@
           F77_INT b_nc = octave::to_f77_int (b.cols ());
 
           retval = ComplexMatrix (b);
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -3775,7 +3765,7 @@
           F77_INT b_nc = octave::to_f77_int (b.cols ());
 
           retval = ComplexMatrix (b);
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -3847,7 +3837,7 @@
           OCTAVE_LOCAL_BUFFER (Complex, D, nr);
           OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           if (mattype.is_dense ())
             {
@@ -3911,17 +3901,17 @@
           else
             {
               char job = 'N';
-              volatile octave_idx_type x_nz = b.nnz ();
+              octave_idx_type x_nz = b.nnz ();
               F77_INT b_nr = octave::to_f77_int (b.rows ());
               octave_idx_type b_nc = b.cols ();
               retval = SparseComplexMatrix (nr, b_nc, x_nz);
               retval.xcidx (0) = 0;
-              volatile octave_idx_type ii = 0;
+              octave_idx_type ii = 0;
               rcond = 1.0;
 
               OCTAVE_LOCAL_BUFFER (Complex, work, nr);
 
-              for (volatile octave_idx_type j = 0; j < b_nc; j++)
+              for (octave_idx_type j = 0; j < b_nc; j++)
                 {
                   for (octave_idx_type i = 0; i < nr; i++)
                     work[i] = 0.;
@@ -3997,7 +3987,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Tridiagonal_Hermitian)
@@ -4042,7 +4032,7 @@
           rcond = 1.;
 
           retval = ComplexMatrix (b);
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -4108,7 +4098,7 @@
           rcond = 1.;
 
           retval = ComplexMatrix (b);
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -4178,7 +4168,7 @@
           OCTAVE_LOCAL_BUFFER (Complex, D, nr);
           OCTAVE_LOCAL_BUFFER (Complex, DL, nr - 1);
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           if (mattype.is_dense ())
             {
@@ -4249,12 +4239,12 @@
 
               // Take a first guess that the number of nonzero terms
               // will be as many as in b
-              volatile octave_idx_type x_nz = b.nnz ();
-              volatile octave_idx_type ii = 0;
+              octave_idx_type x_nz = b.nnz ();
+              octave_idx_type ii = 0;
               retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
 
               retval.xcidx (0) = 0;
-              for (volatile octave_idx_type j = 0; j < b_nc; j++)
+              for (octave_idx_type j = 0; j < b_nc; j++)
                 {
 
                   for (F77_INT i = 0; i < b_nr; i++)
@@ -4338,7 +4328,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4346,7 +4336,7 @@
           F77_INT n_lower = octave::to_f77_int (mattype.nlower ());
           F77_INT ldm = n_lower + 1;
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4395,9 +4385,9 @@
               if (calc_cond)
                 {
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_XFCN (zpbcon, ZPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -4410,9 +4400,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4431,7 +4419,7 @@
               if (err == 0)
                 {
                   retval = ComplexMatrix (b);
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -4463,7 +4451,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4493,7 +4481,7 @@
             }
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -4526,9 +4514,9 @@
                 {
                   char job = '1';
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -4543,9 +4531,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4564,7 +4550,7 @@
               if (err == 0)
                 {
                   retval = ComplexMatrix (b);
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -4608,7 +4594,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4617,7 +4603,7 @@
           F77_INT ldm = n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4664,9 +4650,9 @@
               if (calc_cond)
                 {
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_XFCN (zpbcon, ZPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -4679,9 +4665,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4705,12 +4689,12 @@
 
                   // Take a first guess that the number of nonzero terms
                   // will be as many as in b
-                  volatile octave_idx_type x_nz = b.nnz ();
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type ii = 0;
                   retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
 
                   retval.xcidx (0) = 0;
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (F77_INT i = 0; i < b_nr; i++)
                         Bx[i] = b.elem (i, j);
@@ -4767,7 +4751,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4797,7 +4781,7 @@
             }
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -4828,9 +4812,9 @@
                 {
                   char job = '1';
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -4845,9 +4829,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4866,16 +4848,16 @@
               if (err == 0)
                 {
                   char job = 'N';
-                  volatile octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type x_nz = b.nnz ();
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   octave_idx_type b_nc = b.cols ();
                   retval = SparseComplexMatrix (nr, b_nc, x_nz);
                   retval.xcidx (0) = 0;
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type ii = 0;
 
                   OCTAVE_LOCAL_BUFFER (Complex, work, nr);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (octave_idx_type i = 0; i < nr; i++)
                         work[i] = 0.;
@@ -4947,7 +4929,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4956,7 +4938,7 @@
           F77_INT ldm = n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5005,9 +4987,9 @@
               if (calc_cond)
                 {
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_XFCN (zpbcon, ZPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -5020,9 +5002,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5043,7 +5023,7 @@
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
                   retval = ComplexMatrix (b);
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   F77_XFCN (zpbtrs, ZPBTRS,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -5072,7 +5052,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5102,7 +5082,7 @@
             }
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -5133,9 +5113,9 @@
                 {
                   char job = '1';
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -5150,9 +5130,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5174,7 +5152,7 @@
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
                   retval = ComplexMatrix (b);
-                  Complex *result = retval.fortran_vec ();
+                  Complex *result = retval.rwdata ();
 
                   F77_XFCN (zgbtrs, ZGBTRS,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -5214,7 +5192,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -5223,7 +5201,7 @@
           F77_INT ldm = n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5273,9 +5251,9 @@
               if (calc_cond)
                 {
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_XFCN (zpbcon, ZPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -5288,9 +5266,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5314,12 +5290,12 @@
 
                   // Take a first guess that the number of nonzero terms
                   // will be as many as in b
-                  volatile octave_idx_type x_nz = b.nnz ();
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type ii = 0;
                   retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
 
                   retval.xcidx (0) = 0;
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
 
                       for (F77_INT i = 0; i < b_nr; i++)
@@ -5380,7 +5356,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           ComplexMatrix m_band (ldm, nc);
-          Complex *tmp_data = m_band.fortran_vec ();
+          Complex *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5410,7 +5386,7 @@
             }
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
@@ -5441,9 +5417,9 @@
                 {
                   char job = '1';
                   Array<Complex> z (dim_vector (2 * nr, 1));
-                  Complex *pz = z.fortran_vec ();
+                  Complex *pz = z.rwdata ();
                   Array<double> iz (dim_vector (nr, 1));
-                  double *piz = iz.fortran_vec ();
+                  double *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -5458,9 +5434,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5479,16 +5453,16 @@
               if (err == 0)
                 {
                   char job = 'N';
-                  volatile octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type x_nz = b.nnz ();
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   octave_idx_type b_nc = b.cols ();
                   retval = SparseComplexMatrix (nr, b_nc, x_nz);
                   retval.xcidx (0) = 0;
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type ii = 0;
 
                   OCTAVE_LOCAL_BUFFER (Complex, Bx, nr);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (octave_idx_type i = 0; i < nr; i++)
                         Bx[i] = 0.;
@@ -5554,7 +5528,7 @@
 
   // Setup the control parameters
   Control = Matrix (UMFPACK_CONTROL, 1);
-  double *control = Control.fortran_vec ();
+  double *control = Control.rwdata ();
   UMFPACK_ZNAME (defaults) (control);
 
   double tmp = octave::sparse_params::get_key ("spumoni");
@@ -5588,7 +5562,7 @@
 
   void *Symbolic;
   Info = Matrix (1, UMFPACK_INFO);
-  double *info = Info.fortran_vec ();
+  double *info = Info.rwdata ();
   int status = UMFPACK_ZNAME (qsymbolic) (nr, nc,
                                           octave::to_suitesparse_intptr (Ap),
                                           octave::to_suitesparse_intptr (Ai),
@@ -5621,10 +5595,9 @@
         rcond = Info (UMFPACK_RCOND);
       else
         rcond = 1.;
-      volatile double rcond_plus_one = rcond + 1.0;
 
       if (status == UMFPACK_WARNING_singular_matrix
-          || rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+          || is_singular (rcond) || octave::math::isnan (rcond))
         {
           UMFPACK_ZNAME (report_numeric) (Numeric, control);
 
@@ -5692,7 +5665,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -5771,9 +5744,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -5829,8 +5800,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const Complex *Ax = data ();
@@ -5843,7 +5814,7 @@
               OCTAVE_LOCAL_BUFFER (Complex, Bz, b_nr);
 #endif
               retval.resize (b_nr, b_nc);
-              Complex *Xx = retval.fortran_vec ();
+              Complex *Xx = retval.rwdata ();
 
               for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)
                 {
@@ -5931,7 +5902,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6020,9 +5991,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6086,8 +6055,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const Complex *Ax = data ();
@@ -6223,7 +6192,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6302,9 +6271,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6360,15 +6327,15 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const Complex *Ax = data ();
               const Complex *Bx = b.data ();
 
               retval.resize (b_nr, b_nc);
-              Complex *Xx = retval.fortran_vec ();
+              Complex *Xx = retval.rwdata ();
 
               for (octave_idx_type j = 0, iidx = 0; j < b_nc; j++, iidx += b_nr)
                 {
@@ -6441,7 +6408,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6530,9 +6497,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6596,8 +6561,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const Complex *Ax = data ();
@@ -6665,10 +6630,8 @@
               retval.maybe_compress ();
 
               rcond = Info (UMFPACK_RCOND);
-              volatile double rcond_plus_one = rcond + 1.0;
-
               if (status == UMFPACK_WARNING_singular_matrix
-                  || rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  || is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6756,12 +6719,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<ComplexMatrix, SparseComplexMatrix, Matrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6821,12 +6780,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix, SparseMatrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6886,12 +6841,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<ComplexMatrix, SparseComplexMatrix, ComplexMatrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6952,12 +6903,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<SparseComplexMatrix, SparseComplexMatrix,
       SparseComplexMatrix> (*this, b, err);
-#endif
     }
 
   return retval;
--- a/liboctave/array/CSparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/CSparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -41,9 +41,7 @@
 #include "oct-cmplx.h"
 #include "mx-fwd.h"
 
-class
-OCTAVE_API
-SparseComplexMatrix : public MSparse<Complex>
+class OCTAVE_API SparseComplexMatrix : public MSparse<Complex>
 {
 public:
 
--- a/liboctave/array/DiagArray2.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/DiagArray2.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <cassert>
-
 #include <algorithm>
 
 #include "DiagArray2.h"
--- a/liboctave/array/DiagArray2.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/DiagArray2.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,6 @@
 
 #include "octave-config.h"
 
-#include <cassert>
 #include <cstdlib>
 
 #include "Array.h"
@@ -37,9 +36,7 @@
 // produce unexpected results.
 
 template <typename T>
-class
-OCTAVE_API
-DiagArray2 : protected Array<T>
+class OCTAVE_API DiagArray2 : protected Array<T>
 {
 protected:
   octave_idx_type m_d1, m_d2;
@@ -168,7 +165,8 @@
 
   const T * data () const { return Array<T>::data (); }
 
-  T * fortran_vec () { return Array<T>::fortran_vec (); }
+  T * rwdata () { return Array<T>::rwdata (); }
+  inline T * fortran_vec () { return rwdata (); }
 
   void print_info (std::ostream& os, const std::string& prefix) const
   { Array<T>::print_info (os, prefix); }
--- a/liboctave/array/MArray.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/MArray.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -74,7 +74,7 @@
   octave_quit ();
 
   octave_idx_type len = idx.length (n);
-  idx.loop (len, _idxadds_helper<T> (this->fortran_vec (), val));
+  idx.loop (len, _idxadds_helper<T> (this->rwdata (), val));
 }
 
 template <typename T>
@@ -92,7 +92,7 @@
   octave_quit ();
 
   octave_idx_type len = std::min (idx.length (n), vals.numel ());
-  idx.loop (len, _idxadda_helper<T> (this->fortran_vec (), vals.data ()));
+  idx.loop (len, _idxadda_helper<T> (this->rwdata (), vals.data ()));
 }
 
 template <typename T, T op (typename ref_param<T>::type,
@@ -125,7 +125,7 @@
   octave_quit ();
 
   octave_idx_type len = std::min (idx.length (n), vals.numel ());
-  idx.loop (len, _idxbinop_helper<T, octave::math::min> (this->fortran_vec (),
+  idx.loop (len, _idxbinop_helper<T, octave::math::min> (this->rwdata (),
                                                          vals.data ()));
 }
 
@@ -144,7 +144,7 @@
   octave_quit ();
 
   octave_idx_type len = std::min (idx.length (n), vals.numel ());
-  idx.loop (len, _idxbinop_helper<T, octave::math::max> (this->fortran_vec (),
+  idx.loop (len, _idxbinop_helper<T, octave::math::max> (this->rwdata (),
                                                          vals.data ()));
 }
 
@@ -180,7 +180,7 @@
   if (ddv != sdv)
     (*current_liboctave_error_handler) ("accumdim: dimension mismatch");
 
-  T *dst = Array<T>::fortran_vec ();
+  T *dst = Array<T>::rwdata ();
   const T *src = vals.data ();
   octave_idx_type len = idx.length (ns);
 
--- a/liboctave/array/MArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/MArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -57,9 +57,7 @@
 
 //! Template for N-dimensional array classes with like-type math operators.
 template <typename T>
-class
-OCTARRAY_API
-MArray : public Array<T>
+class OCTARRAY_API MArray : public Array<T>
 {
 public:
 
--- a/liboctave/array/MDiagArray2.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/MDiagArray2.h	Fri Apr 12 15:10:26 2024 +0200
@@ -50,9 +50,7 @@
 
 //! Template for two dimensional diagonal array with math operators.
 template <typename T>
-class
-OCTAVE_API
-MDiagArray2 : public DiagArray2<T>
+class OCTAVE_API MDiagArray2 : public DiagArray2<T>
 {
 public:
 
--- a/liboctave/array/MSparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/MSparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,9 +40,7 @@
 
 // Two dimensional sparse array with math ops.
 template <typename T>
-class
-OCTAVE_API
-MSparse : public Sparse<T>
+class OCTAVE_API MSparse : public Sparse<T>
 {
 public:
 
--- a/liboctave/array/MatrixType.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/MatrixType.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 
 #include "MSparse.h"
 
-class
-MatrixType
+class MatrixType
 {
 public:
   enum matrix_type
--- a/liboctave/array/PermMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/PermMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -169,7 +169,7 @@
 
   const octave_idx_type *p = data ();
   Array<octave_idx_type> res_pvec (dim_vector (n, 1), -1);
-  octave_idx_type *q = res_pvec.fortran_vec ();
+  octave_idx_type *q = res_pvec.rwdata ();
 
   for (octave_idx_type ics = 0; ics < n; ics++)
     {
--- a/liboctave/array/Range.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Range.h	Fri Apr 12 15:10:26 2024 +0200
@@ -45,8 +45,7 @@
 // in ov.cc.
 
 template <typename T>
-class
-range<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
+class range<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
 {
 public:
 
@@ -250,9 +249,9 @@
         // Loop over all values in IDX, executing the lambda
         // expression for each index value.
 
-        T *array = retval.fortran_vec ();
+        T *array = retval.rwdata ();
 
-        idx.loop (n, [=, &array] (octave_idx_type i)
+        idx.loop (n, [this, &array] (octave_idx_type i)
         {
           if (i == 0)
             // Required for proper NaN handling.
--- a/liboctave/array/Sparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Sparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,6 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <cassert>
 #include <cinttypes>
 
 #include <algorithm>
@@ -150,9 +149,9 @@
   // Always preserve space for 1 element.
   nz = (nz > 0 ? nz : 1);
 
-  // Skip reallocation if we have less than 1/frac extra elements to discard.
-  static const int frac = 5;
-  if (nz > m_nzmax || nz < m_nzmax - m_nzmax/frac)
+  // Skip reallocation if we have less than 1/FRAC extra elements to discard.
+  static const int FRAC = 5;
+  if (nz > m_nzmax || nz < m_nzmax - m_nzmax/FRAC)
     {
       // Reallocate.
       octave_idx_type min_nzmax = std::min (nz, m_nzmax);
@@ -271,7 +270,7 @@
     (*current_liboctave_error_handler)
       ("Sparse::Sparse (const Sparse&, const dim_vector&): dimension mismatch");
 
-  dim_vector old_dims = a.dims ();
+  const dim_vector& old_dims = a.dims ();
   octave_idx_type new_nzmax = a.nnz ();
   octave_idx_type new_nr = dv(0);
   octave_idx_type new_nc = dv(1);
@@ -1139,7 +1138,7 @@
 Sparse<T, Alloc>
 Sparse<T, Alloc>::transpose () const
 {
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = rows ();
   octave_idx_type nc = cols ();
@@ -1165,7 +1164,7 @@
         retval.xridx (q) = j;
         retval.xdata (q) = data (k);
       }
-  assert (nnz () == retval.xcidx (nr));
+  liboctave_panic_unless (nnz () == retval.xcidx (nr));
   // retval.xcidx[1:nr] holds row entry *end* offsets for rows 0:(nr-1)
   // and retval.xcidx[0:(nr-1)] holds their row entry *start* offsets
 
@@ -1199,7 +1198,7 @@
 {
   Sparse<T, Alloc> retval;
 
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1300,7 +1299,7 @@
 Sparse<T, Alloc>::delete_elements (const octave::idx_vector& idx_i,
                                    const octave::idx_vector& idx_j)
 {
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1435,7 +1434,7 @@
 {
   Sparse<T, Alloc> retval;
 
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1638,7 +1637,7 @@
 {
   Sparse<T, Alloc> retval;
 
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1883,7 +1882,7 @@
 {
   Sparse<T, Alloc> retval;
 
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -1998,10 +1997,10 @@
               // Disassembly our matrix...
               Array<octave_idx_type> new_ri (dim_vector (new_nz, 1));
               Array<T> new_data (dim_vector (new_nz, 1));
-              std::copy_n (tmp.ridx (), nz, new_ri.fortran_vec ());
-              std::copy_n (tmp.data (), nz, new_data.fortran_vec ());
+              std::copy_n (tmp.ridx (), nz, new_ri.rwdata ());
+              std::copy_n (tmp.data (), nz, new_data.rwdata ());
               // ... insert new data (densified) ...
-              idx.copy_data (new_ri.fortran_vec () + nz);
+              idx.copy_data (new_ri.rwdata () + nz);
               new_data.assign (octave::idx_vector (nz, new_nz), rhs.array_value ());
               // ... reassembly.
               *this = Sparse<T, Alloc> (new_data, new_ri, 0, nr, nc, false);
@@ -2048,7 +2047,7 @@
 {
   Sparse<T, Alloc> retval;
 
-  assert (ndims () == 2);
+  liboctave_panic_unless (ndims () == 2);
 
   octave_idx_type nr = dim1 ();
   octave_idx_type nc = dim2 ();
@@ -2142,7 +2141,7 @@
                   mx_inline_add (ub - lb, cidx () + lb + 1, rhs.cidx () + 1,
                                  li);
 
-                  assert (nnz () == new_nz);
+                  liboctave_panic_unless (nnz () == new_nz);
                 }
               else
                 {
@@ -2170,7 +2169,7 @@
                   mx_inline_add (nc - ub, cidx () + ub + 1,
                                  tmp.cidx () + ub + 1, new_nz - nz);
 
-                  assert (nnz () == new_nz);
+                  liboctave_panic_unless (nnz () == new_nz);
                 }
             }
           else if (idx_j.is_range () && idx_j.increment () == -1)
@@ -2755,7 +2754,7 @@
         break;
       }
     default:
-      assert (false);
+      liboctave_panic_impossible ();
     }
 
   return retval;
--- a/liboctave/array/Sparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/Sparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,6 @@
 
 #include "octave-config.h"
 
-#include <cassert>
 #include <cstddef>
 
 #include <algorithm>
@@ -43,9 +42,7 @@
 // all the derived classes.
 
 template <typename T, typename Alloc>
-class
-OCTAVE_API
-Sparse
+class OCTAVE_API Sparse
 {
 public:
 
--- a/liboctave/array/boolMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/boolMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-boolMatrix : public boolNDArray
+class OCTAVE_API boolMatrix : public boolNDArray
 {
 public:
 
--- a/liboctave/array/boolNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/boolNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-boolNDArray : public Array<bool>
+class OCTAVE_API boolNDArray : public Array<bool>
 {
 public:
 
--- a/liboctave/array/boolSparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/boolSparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -178,7 +178,7 @@
       else
         {
           Array<octave_idx_type> tmp (dim_vector (nz, 1));
-          std::copy_n (ridx (), nz, tmp.fortran_vec ());
+          std::copy_n (ridx (), nz, tmp.rwdata ());
           retval = Sparse<bool> (Array<bool> (dim_vector (1, 1), true),
                                  octave::idx_vector (tmp),
                                  octave::idx_vector (0), nr, 1, false);
@@ -228,7 +228,7 @@
       else
         {
           Array<octave_idx_type> tmp (dim_vector (nz, 1));
-          std::copy_n (ridx (), nz, tmp.fortran_vec ());
+          std::copy_n (ridx (), nz, tmp.rwdata ());
           retval = Sparse<double> (Array<double> (dim_vector (1, 1), 1.0),
                                    octave::idx_vector (tmp),
                                    octave::idx_vector (0), nr, 1);
--- a/liboctave/array/boolSparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/boolSparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 #include "boolNDArray.h"
 #include "mx-fwd.h"
 
-class
-OCTAVE_API
-SparseBoolMatrix : public Sparse<bool>
+class OCTAVE_API SparseBoolMatrix : public Sparse<bool>
 {
 public:
 
--- a/liboctave/array/chMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/chMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 #include "mx-op-decl.h"
 #include "str-vec.h"
 
-class
-OCTAVE_API
-charMatrix : public charNDArray
+class OCTAVE_API charMatrix : public charNDArray
 {
   friend class ComplexMatrix;
 
--- a/liboctave/array/chNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/chNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 #include "mx-op-decl.h"
 #include "str-vec.h"
 
-class
-OCTAVE_API
-charNDArray : public Array<char>
+class OCTAVE_API charNDArray : public Array<char>
 {
 public:
 
--- a/liboctave/array/dColVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dColVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -196,7 +196,7 @@
         retval.fill (0.0);
       else
         {
-          double *y = retval.fortran_vec ();
+          double *y = retval.rwdata ();
 
           F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 ("N", 1),
                                    nr, nc, 1.0, m.data (), nr,
--- a/liboctave/array/dColVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dColVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-ColumnVector : public MArray<double>
+class OCTAVE_API ColumnVector : public MArray<double>
 {
 public:
 
--- a/liboctave/array/dDiagMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dDiagMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -268,7 +268,7 @@
   else if (z_count > 0)
     {
       info = -1;
-      element_type *data = retval.fortran_vec ();
+      element_type *data = retval.rwdata ();
       std::fill (data, data + len, octave::numeric_limits<double>::Inf ());
     }
 
--- a/liboctave/array/dDiagMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dDiagMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 #include "dRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-DiagMatrix : public MDiagArray2<double>
+class OCTAVE_API DiagMatrix : public MDiagArray2<double>
 {
 public:
 
--- a/liboctave/array/dMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -28,6 +28,7 @@
 #endif
 
 #include <algorithm>
+#include <cmath>
 #include <istream>
 #include <limits>
 #include <ostream>
@@ -447,13 +448,21 @@
   return anorm;
 }
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const double rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());
+}
+
 Matrix
 Matrix::inverse () const
 {
   octave_idx_type info;
   double rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 Matrix
@@ -461,12 +470,12 @@
 {
   double rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 Matrix
-Matrix::inverse (octave_idx_type& info, double& rcon, bool force,
-                 bool calc_cond) const
+Matrix::inverse (octave_idx_type& info, double& rcon,
+                 bool force, bool calc_cond) const
 {
   MatrixType mattype (*this);
   return inverse (mattype, info, rcon, force, calc_cond);
@@ -477,14 +486,14 @@
 {
   octave_idx_type info;
   double rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 Matrix
 Matrix::inverse (MatrixType& mattype, octave_idx_type& info) const
 {
   double rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 Matrix
@@ -503,7 +512,7 @@
   char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
   char udiag = 'N';
   retval = *this;
-  double *tmp_data = retval.fortran_vec ();
+  double *tmp_data = retval.rwdata ();
 
   F77_INT tmp_info = 0;
 
@@ -559,10 +568,10 @@
     (*current_liboctave_error_handler) ("inverse requires square matrix");
 
   Array<F77_INT> ipvt (dim_vector (nr, 1));
-  F77_INT *pipvt = ipvt.fortran_vec ();
+  F77_INT *pipvt = ipvt.rwdata ();
 
   retval = *this;
-  double *tmp_data = retval.fortran_vec ();
+  double *tmp_data = retval.rwdata ();
 
   Array<double> z (dim_vector (1, 1));
   F77_INT lwork = -1;
@@ -571,12 +580,12 @@
 
   // Query the optimum work array size.
   F77_XFCN (dgetri, DGETRI, (nc, tmp_data, nr, pipvt,
-                             z.fortran_vec (), lwork, tmp_info));
+                             z.rwdata (), lwork, tmp_info));
 
   lwork = static_cast<F77_INT> (z(0));
   lwork = (lwork < 4 * nc ? 4 * nc : lwork);
   z.resize (dim_vector (lwork, 1));
-  double *pz = z.fortran_vec ();
+  double *pz = z.rwdata ();
 
   info = 0;
   tmp_info = 0;
@@ -605,7 +614,7 @@
           // Now calculate the condition number for non-singular matrix.
           char job = '1';
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
           F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                      nc, tmp_data, nr, anorm,
                                      rcon, pz, piz, dgecon_info
@@ -752,7 +761,7 @@
     }
 
   const double *in (data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::fft (in, out, npts, nsamples);
 
@@ -782,7 +791,7 @@
 
   ComplexMatrix tmp (*this);
   const Complex *in (tmp.data ());
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifft (in, out, npts, nsamples);
 
@@ -796,7 +805,7 @@
 
   const double *in = data ();
   ComplexMatrix retval (rows (), cols ());
-  octave::fftw::fftNd (in, retval.fortran_vec (), 2, dv);
+  octave::fftw::fftNd (in, retval.rwdata (), 2, dv);
 
   return retval;
 }
@@ -807,7 +816,7 @@
   dim_vector dv (rows (), cols ());
 
   ComplexMatrix retval (*this);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (out, out, 2, dv);
 
@@ -891,7 +900,7 @@
   if (nr != nc)
     (*current_liboctave_error_handler) ("matrix must be square");
 
-  volatile int typ = mattype.type ();
+  int typ = mattype.type ();
 
   // Even though the matrix is marked as singular (Rectangular), we may still
   // get a useful number from the LU factorization, because it always completes.
@@ -909,7 +918,7 @@
   else if (typ == MatrixType::Hermitian)
     {
       Matrix atmp = *this;
-      double *tmp_data = atmp.fortran_vec ();
+      double *tmp_data = atmp.rwdata ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       double anorm;
@@ -936,9 +945,9 @@
           if (calc_cond)
             {
               Array<double> z (dim_vector (3 * nc, 1));
-              double *pz = z.fortran_vec ();
+              double *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nr, tmp_data, nr, anorm,
@@ -963,10 +972,10 @@
   if (typ == MatrixType::Full)
     {
       Array<F77_INT> ipvt (dim_vector (nr, 1));
-      F77_INT *pipvt = ipvt.fortran_vec ();
+      F77_INT *pipvt = ipvt.rwdata ();
 
       Matrix atmp = *this;
-      double *tmp_data = atmp.fortran_vec ();
+      double *tmp_data = atmp.rwdata ();
 
       info = 0;
       F77_INT tmp_info = 0;
@@ -994,9 +1003,9 @@
               // Now calc the condition number for non-singular matrix.
               char job = '1';
               Array<double> z (dim_vector (4 * nc, 1));
-              double *pz = z.fortran_vec ();
+              double *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (dgecon, DGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nc, tmp_data, nr, anorm,
@@ -1046,7 +1055,7 @@
     rcon = octave::numeric_limits<double>::Inf ();
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Unknown)
         typ = mattype.type (*this);
@@ -1061,9 +1070,9 @@
           char dia = 'N';
 
           Array<double> z (dim_vector (3 * nc, 1));
-          double *pz = z.fortran_vec ();
+          double *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1089,9 +1098,9 @@
           char dia = 'N';
 
           Array<double> z (dim_vector (3 * nc, 1));
-          double *pz = z.fortran_vec ();
+          double *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1118,7 +1127,7 @@
               char job = 'L';
 
               Matrix atmp = *this;
-              double *tmp_data = atmp.fortran_vec ();
+              double *tmp_data = atmp.rwdata ();
 
               anorm = norm1 (atmp);
 
@@ -1135,9 +1144,9 @@
               else
                 {
                   Array<double> z (dim_vector (3 * nc, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, tmp_data, nr, anorm,
@@ -1154,18 +1163,18 @@
               F77_INT info = 0;
 
               Matrix atmp = *this;
-              double *tmp_data = atmp.fortran_vec ();
+              double *tmp_data = atmp.rwdata ();
 
               Array<F77_INT> ipvt (dim_vector (nr, 1));
-              F77_INT *pipvt = ipvt.fortran_vec ();
+              F77_INT *pipvt = ipvt.rwdata ();
 
               if (anorm < 0.0)
                 anorm = norm1 (atmp);
 
               Array<double> z (dim_vector (4 * nc, 1));
-              double *pz = z.fortran_vec ();
+              double *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (dgetrf, DGETRF, (nr, nr, tmp_data, nr, pipvt, info));
 
@@ -1215,7 +1224,7 @@
     retval = Matrix (nc, b_nc, 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ != MatrixType::Permuted_Upper && typ != MatrixType::Upper)
         (*current_liboctave_error_handler) ("incorrect matrix type");
@@ -1230,7 +1239,7 @@
       const double *tmp_data = data ();
 
       retval = b;
-      double *result = retval.fortran_vec ();
+      double *result = retval.rwdata ();
 
       char uplo = 'U';
       char trans = get_blas_char (transt);
@@ -1256,9 +1265,9 @@
           dia = 'N';
 
           Array<double> z (dim_vector (3 * nc, 1));
-          double *pz = z.fortran_vec ();
+          double *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1274,10 +1283,7 @@
           if (info != 0)
             info = -2;
 
-          // FIXME: Why calculate this, rather than just compare to 0.0?
-          volatile double rcond_plus_one = rcon + 1.0;
-
-          if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+          if (is_singular (rcon) || octave::math::isnan (rcon))
             {
               info = -2;
 
@@ -1313,7 +1319,7 @@
     retval = Matrix (nc, b_nc, 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ != MatrixType::Permuted_Lower && typ != MatrixType::Lower)
         (*current_liboctave_error_handler) ("incorrect matrix type");
@@ -1328,7 +1334,7 @@
       const double *tmp_data = data ();
 
       retval = b;
-      double *result = retval.fortran_vec ();
+      double *result = retval.rwdata ();
 
       char uplo = 'L';
       char trans = get_blas_char (transt);
@@ -1354,9 +1360,9 @@
           dia = 'N';
 
           Array<double> z (dim_vector (3 * nc, 1));
-          double *pz = z.fortran_vec ();
+          double *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (dtrcon, DTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1372,9 +1378,7 @@
           if (info != 0)
             info = -2;
 
-          volatile double rcond_plus_one = rcon + 1.0;
-
-          if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+          if (is_singular (rcon) || octave::math::isnan (rcon))
             {
               info = -2;
 
@@ -1407,7 +1411,7 @@
     retval = Matrix (nc, b.cols (), 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       double anorm = -1.0;
@@ -1418,7 +1422,7 @@
           char job = 'L';
 
           Matrix atmp = *this;
-          double *tmp_data = atmp.fortran_vec ();
+          double *tmp_data = atmp.rwdata ();
 
           // The norm of the matrix for later use when determining rcon.
           if (calc_cond)
@@ -1446,9 +1450,9 @@
               if (calc_cond)
                 {
                   Array<double> z (dim_vector (3 * nc, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, tmp_data, nr, anorm,
@@ -1460,9 +1464,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile double rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1476,7 +1478,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  double *result = retval.fortran_vec ();
+                  double *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -1501,18 +1503,18 @@
           info = 0;
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           Matrix atmp = *this;
-          double *tmp_data = atmp.fortran_vec ();
+          double *tmp_data = atmp.rwdata ();
 
           if (calc_cond && anorm < 0.0)
             anorm = norm1 (atmp);
 
           Array<double> z (dim_vector (4 * nc, 1));
-          double *pz = z.fortran_vec ();
+          double *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_INT tmp_info = 0;
 
@@ -1549,9 +1551,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile double rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       if (sing_handler)
                         sing_handler (rcon);
@@ -1563,7 +1563,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  double *result = retval.fortran_vec ();
+                  double *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -1675,7 +1675,7 @@
   octave_idx_type nel = m*n;
   Matrix retval (m, 2*n);
   const Complex *cmd = cm.data ();
-  double *rd = retval.fortran_vec ();
+  double *rd = retval.rwdata ();
   for (octave_idx_type i = 0; i < nel; i++)
     {
       rd[i] = std::real (cmd[i]);
@@ -1692,7 +1692,7 @@
   octave_idx_type nel = m*n;
   ComplexMatrix retval (m, n);
   const double *smd = sm.data ();
-  Complex *rd = retval.fortran_vec ();
+  Complex *rd = retval.rwdata ();
   for (octave_idx_type i = 0; i < nel; i++)
     rd[i] = Complex (smd[i], smd[nel+i]);
   return retval;
@@ -1944,7 +1944,7 @@
     retval = Matrix (n, b_nc, 0.0);
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
       if (m != n)
@@ -1959,11 +1959,11 @@
         retval = b;
 
       Matrix atmp = *this;
-      double *tmp_data = atmp.fortran_vec ();
-
-      double *pretval = retval.fortran_vec ();
+      double *tmp_data = atmp.rwdata ();
+
+      double *pretval = retval.rwdata ();
       Array<double> s (dim_vector (minmn, 1));
-      double *ps = s.fortran_vec ();
+      double *ps = s.rwdata ();
 
       // Ask DGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -1998,13 +1998,13 @@
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
-                                 ps, rcon, tmp_rank, work.fortran_vec (),
+                                 ps, rcon, tmp_rank, work.rwdata (),
                                  lwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2066,7 +2066,7 @@
         {
           F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,
                                      maxmn, ps, rcon, tmp_rank,
-                                     work.fortran_vec (), lwork,
+                                     work.rwdata (), lwork,
                                      piwork, tmp_info));
 
           info = tmp_info;
@@ -2166,7 +2166,7 @@
     retval = ColumnVector (n, 0.0);
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2181,11 +2181,11 @@
         retval = b;
 
       Matrix atmp = *this;
-      double *tmp_data = atmp.fortran_vec ();
-
-      double *pretval = retval.fortran_vec ();
+      double *tmp_data = atmp.rwdata ();
+
+      double *pretval = retval.rwdata ();
       Array<double> s (dim_vector (minmn, 1));
-      double *ps = s.fortran_vec ();
+      double *ps = s.rwdata ();
 
       // Ask DGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2213,13 +2213,13 @@
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
-                                 ps, rcon, tmp_rank, work.fortran_vec (),
+                                 ps, rcon, tmp_rank, work.rwdata (),
                                  lwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2230,7 +2230,7 @@
 
       F77_XFCN (dgelsd, DGELSD, (m, n, nrhs, tmp_data, m, pretval,
                                  maxmn, ps, rcon, tmp_rank,
-                                 work.fortran_vec (), lwork,
+                                 work.rwdata (), lwork,
                                  piwork, tmp_info));
 
       info = tmp_info;
@@ -2338,7 +2338,7 @@
       F77_INT a_len = octave::to_f77_int (a.numel ());
 
       retval = Matrix (len, a_len);
-      double *c = retval.fortran_vec ();
+      double *c = retval.rwdata ();
 
       F77_XFCN (dgemm, DGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
                                F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2730,9 +2730,9 @@
   double scale;
   F77_INT info;
 
-  double *pa = sch_a.fortran_vec ();
-  double *pb = sch_b.fortran_vec ();
-  double *px = cx.fortran_vec ();
+  double *pa = sch_a.rwdata ();
+  double *pb = sch_b.rwdata ();
+  double *px = cx.rwdata ();
 
   F77_XFCN (dtrsyl, DTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
                              F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2807,7 +2807,7 @@
       F77_INT lda = octave::to_f77_int (a.rows ());
 
       retval = Matrix (a_nr, b_nc);
-      double *c = retval.fortran_vec ();
+      double *c = retval.rwdata ();
 
       const char ctra = get_blas_trans_arg (tra);
       F77_XFCN (dsyrk, DSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
@@ -2829,7 +2829,7 @@
       F77_INT tdb = octave::to_f77_int (b.cols ());
 
       retval = Matrix (a_nr, b_nc);
-      double *c = retval.fortran_vec ();
+      double *c = retval.rwdata ();
 
       if (b_nc == 1)
         {
--- a/liboctave/array/dMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-Matrix : public NDArray
+class OCTAVE_API Matrix : public NDArray
 {
 public:
 
@@ -171,8 +169,8 @@
   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,
-           bool calc_cond = true) const;
+  inverse (octave_idx_type& info, double& rcon,
+           bool force = false, bool calc_cond = true) const;
 
   OCTAVE_API Matrix inverse (MatrixType& mattype) const;
   OCTAVE_API Matrix inverse (MatrixType& mattype, octave_idx_type& info) const;
--- a/liboctave/array/dNDArray.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dNDArray.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -49,7 +49,7 @@
 {
   const octave_idx_type *pa = a.data ();
   resize (a.dims ());
-  double *ptmp = fortran_vec ();
+  double *ptmp = rwdata ();
   if (negative_to_nan)
     {
       double nan_val = lo_ieee_nan_value ();
@@ -99,7 +99,7 @@
 ComplexNDArray
 NDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return ComplexNDArray ();
@@ -117,7 +117,7 @@
 
   const double *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -130,7 +130,7 @@
 ComplexNDArray
 NDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return ComplexNDArray ();
@@ -147,7 +147,7 @@
   octave_idx_type dist = (stride == 1 ? n : 1);
 
   ComplexNDArray retval (*this);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -160,14 +160,14 @@
 ComplexNDArray
 NDArray::fourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return ComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const double *in = data ();
   ComplexNDArray retval (dv);
-  Complex *out = retval.fortran_vec ();
+  Complex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -180,13 +180,13 @@
 ComplexNDArray
 NDArray::ifourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return ComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   ComplexNDArray retval (*this);
-  Complex *out = retval.fortran_vec ();
+  Complex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -199,12 +199,12 @@
 ComplexNDArray
 NDArray::fourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const double *in (data ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, rank, dv);
 
@@ -214,13 +214,13 @@
 ComplexNDArray
 NDArray::ifourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   ComplexNDArray tmp (*this);
-  Complex *in (tmp.fortran_vec ());
+  Complex *in (tmp.rwdata ());
   ComplexNDArray retval (dv);
-  Complex *out (retval.fortran_vec ());
+  Complex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, rank, dv);
 
--- a/liboctave/array/dNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-NDArray : public MArray<double>
+class OCTAVE_API NDArray : public MArray<double>
 {
 public:
 
--- a/liboctave/array/dRowVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dRowVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -190,7 +190,7 @@
       F77_INT ld = a_nr;
 
       retval.resize (a_nc);
-      double *y = retval.fortran_vec ();
+      double *y = retval.rwdata ();
 
       F77_XFCN (dgemv, DGEMV, (F77_CONST_CHAR_ARG2 ("T", 1),
                                a_nr, a_nc, 1.0, a.data (),
--- a/liboctave/array/dRowVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dRowVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-RowVector : public MArray<double>
+class OCTAVE_API RowVector : public MArray<double>
 {
 public:
 
--- a/liboctave/array/dSparse.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dSparse.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,9 @@
 #  include "config.h"
 #endif
 
+#include <cmath>
 #include <istream>
+#include <limits>
 #include <ostream>
 
 #include "quit.h"
@@ -55,12 +57,7 @@
 
 #include "Sparse-perm-op-defs.h"
 
-// Define whether to use a basic QR solver or one that uses a Dulmange
-// Mendelsohn factorization to separate the problem into under-determined,
-// well-determined and over-determined parts and solves them separately
-#if ! defined (USE_QRSOLVE)
-#  include "sparse-dmsolve.h"
-#endif
+#include "sparse-dmsolve.h"
 
 SparseMatrix::SparseMatrix (const SparseBoolMatrix& a)
   : MSparse<double> (a.rows (), a.cols (), a.nnz ())
@@ -193,7 +190,7 @@
 SparseMatrix::max (Array<octave_idx_type>& idx_arg, int dim) const
 {
   SparseMatrix result;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nr = dv(0);
   octave_idx_type nc = dv(1);
 
@@ -344,7 +341,7 @@
 SparseMatrix::min (Array<octave_idx_type>& idx_arg, int dim) const
 {
   SparseMatrix result;
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   octave_idx_type nr = dv(0);
   octave_idx_type nc = dv(1);
 
@@ -599,6 +596,14 @@
 
 */
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const double rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<double>::epsilon ());
+}
+
 SparseMatrix
 SparseMatrix::inverse () const
 {
@@ -1043,7 +1048,7 @@
 
       // Setup the control parameters
       Matrix Control (UMFPACK_CONTROL, 1);
-      double *control = Control.fortran_vec ();
+      double *control = Control.rwdata ();
       UMFPACK_DNAME (defaults) (control);
 
       double tmp = octave::sparse_params::get_key ("spumoni");
@@ -1078,7 +1083,7 @@
 
       void *Symbolic;
       Matrix Info (1, UMFPACK_INFO);
-      double *info = Info.fortran_vec ();
+      double *info = Info.rwdata ();
       int status = UMFPACK_DNAME (qsymbolic) (nr, nc,
                                               octave::to_suitesparse_intptr (Ap),
                                               octave::to_suitesparse_intptr (Ai),
@@ -1662,9 +1667,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -1944,9 +1947,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2175,9 +2176,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2459,9 +2458,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -2712,9 +2709,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3012,9 +3007,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3266,9 +3259,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3568,9 +3559,7 @@
             octave::warn_singular_matrix (rcond);
         }
 
-      volatile double rcond_plus_one = rcond + 1.0;
-
-      if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+      if (is_singular (rcond) || octave::math::isnan (rcond))
         {
           err = -2;
 
@@ -3611,7 +3600,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Tridiagonal_Hermitian)
@@ -3656,7 +3645,7 @@
           F77_INT b_nc = octave::to_f77_int (b.cols ());
 
           retval = b;
-          double *result = retval.fortran_vec ();
+          double *result = retval.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -3721,7 +3710,7 @@
           F77_INT b_nc = octave::to_f77_int (b.cols ());
 
           retval = b;
-          double *result = retval.fortran_vec ();
+          double *result = retval.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -3789,7 +3778,7 @@
           OCTAVE_LOCAL_BUFFER (double, D, nr);
           OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           if (mattype.is_dense ())
             {
@@ -3848,15 +3837,15 @@
             {
               rcond = 1.0;
               char job = 'N';
-              volatile octave_idx_type x_nz = b.nnz ();
+              octave_idx_type x_nz = b.nnz ();
               octave_idx_type b_nc = b.cols ();
               retval = SparseMatrix (nr, b_nc, x_nz);
               retval.xcidx (0) = 0;
-              volatile octave_idx_type ii = 0;
+              octave_idx_type ii = 0;
 
               OCTAVE_LOCAL_BUFFER (double, work, nr);
 
-              for (volatile octave_idx_type j = 0; j < b_nc; j++)
+              for (octave_idx_type j = 0; j < b_nc; j++)
                 {
                   for (octave_idx_type i = 0; i < nr; i++)
                     work[i] = 0.;
@@ -3931,7 +3920,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Tridiagonal_Hermitian)
@@ -3978,7 +3967,7 @@
           rcond = 1.;
 
           retval = b;
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -4044,7 +4033,7 @@
           rcond = 1.;
 
           retval = b;
-          Complex *result = retval.fortran_vec ();
+          Complex *result = retval.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -4113,7 +4102,7 @@
           OCTAVE_LOCAL_BUFFER (double, D, nr);
           OCTAVE_LOCAL_BUFFER (double, DL, nr - 1);
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           if (mattype.is_dense ())
             {
@@ -4181,12 +4170,12 @@
 
               // Take a first guess that the number of nonzero terms
               // will be as many as in b
-              volatile octave_idx_type x_nz = b.nnz ();
-              volatile octave_idx_type ii = 0;
+              octave_idx_type x_nz = b.nnz ();
+              octave_idx_type ii = 0;
               retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
 
               retval.xcidx (0) = 0;
-              for (volatile octave_idx_type j = 0; j < b_nc; j++)
+              for (octave_idx_type j = 0; j < b_nc; j++)
                 {
 
                   for (F77_INT i = 0; i < b_nr; i++)
@@ -4288,7 +4277,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4296,7 +4285,7 @@
           F77_INT n_lower = octave::to_f77_int (mattype.nlower ());
           F77_INT ldm = n_lower + 1;
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4345,9 +4334,9 @@
               if (calc_cond)
                 {
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpbcon, DPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -4360,9 +4349,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4381,7 +4368,7 @@
               if (err == 0)
                 {
                   retval = b;
-                  double *result = retval.fortran_vec ();
+                  double *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -4413,7 +4400,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4445,7 +4432,7 @@
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -4475,9 +4462,9 @@
                 {
                   char job = '1';
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -4492,9 +4479,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4513,7 +4498,7 @@
               if (err == 0)
                 {
                   retval = b;
-                  double *result = retval.fortran_vec ();
+                  double *result = retval.rwdata ();
 
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   F77_INT b_nc = octave::to_f77_int (b.cols ());
@@ -4557,7 +4542,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4566,7 +4551,7 @@
           F77_INT ldm = octave::to_f77_int (n_lower + 1);
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4613,9 +4598,9 @@
               if (calc_cond)
                 {
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpbcon, DPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -4628,9 +4613,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4654,12 +4637,12 @@
 
                   // Take a first guess that the number of nonzero terms
                   // will be as many as in b
-                  volatile octave_idx_type x_nz = b.nnz ();
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type ii = 0;
                   retval = SparseMatrix (b_nr, b_nc, x_nz);
 
                   retval.xcidx (0) = 0;
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (F77_INT i = 0; i < b_nr; i++)
                         Bx[i] = b.elem (i, j);
@@ -4716,7 +4699,7 @@
           F77_INT ldm = octave::to_f77_int (n_upper + 2 * n_lower + 1);
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4749,7 +4732,7 @@
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -4777,9 +4760,9 @@
                 {
                   char job = '1';
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -4794,9 +4777,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4815,15 +4796,15 @@
               if (err == 0)
                 {
                   char job = 'N';
-                  volatile octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type x_nz = b.nnz ();
                   octave_idx_type b_nc = b.cols ();
                   retval = SparseMatrix (nr, b_nc, x_nz);
                   retval.xcidx (0) = 0;
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type ii = 0;
 
                   OCTAVE_LOCAL_BUFFER (double, work, nr);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (octave_idx_type i = 0; i < nr; i++)
                         work[i] = 0.;
@@ -4897,7 +4878,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -4906,7 +4887,7 @@
           F77_INT ldm = n_lower + 1;
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -4955,9 +4936,9 @@
               if (calc_cond)
                 {
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpbcon, DPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -4970,9 +4951,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -4998,7 +4977,7 @@
 
                   retval.resize (b_nr, b_nc);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (F77_INT i = 0; i < b_nr; i++)
                         {
@@ -5056,7 +5035,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5089,7 +5068,7 @@
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -5117,9 +5096,9 @@
                 {
                   char job = '1';
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -5134,9 +5113,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5162,7 +5139,7 @@
                   OCTAVE_LOCAL_BUFFER (double, Bz, nr);
                   OCTAVE_LOCAL_BUFFER (double, Bx, nr);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (octave_idx_type i = 0; i < nr; i++)
                         {
@@ -5221,7 +5198,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Banded_Hermitian)
@@ -5230,7 +5207,7 @@
           F77_INT ldm = n_lower + 1;
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5280,9 +5257,9 @@
               if (calc_cond)
                 {
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (dpbcon, DPBCON,
                             (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -5295,9 +5272,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5322,12 +5297,12 @@
 
                   // Take a first guess that the number of nonzero terms
                   // will be as many as in b
-                  volatile octave_idx_type x_nz = b.nnz ();
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type ii = 0;
                   retval = SparseComplexMatrix (b_nr, b_nc, x_nz);
 
                   retval.xcidx (0) = 0;
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
 
                       for (F77_INT i = 0; i < b_nr; i++)
@@ -5410,7 +5385,7 @@
           F77_INT ldm = n_upper + 2 * n_lower + 1;
 
           Matrix m_band (ldm, nc);
-          double *tmp_data = m_band.fortran_vec ();
+          double *tmp_data = m_band.rwdata ();
 
           if (! mattype.is_dense ())
             {
@@ -5443,7 +5418,7 @@
           F77_INT tmp_nr = octave::to_f77_int (nr);
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           F77_INT tmp_err = 0;
 
@@ -5471,9 +5446,9 @@
                 {
                   char job = '1';
                   Array<double> z (dim_vector (3 * nr, 1));
-                  double *pz = z.fortran_vec ();
+                  double *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nr, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_INT tmp_nc = octave::to_f77_int (nc);
 
@@ -5488,9 +5463,7 @@
                   if (err != 0)
                     err = -2;
 
-                  volatile double rcond_plus_one = rcond + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+                  if (is_singular (rcond) || octave::math::isnan (rcond))
                     {
                       err = -2;
 
@@ -5509,17 +5482,17 @@
               if (err == 0)
                 {
                   char job = 'N';
-                  volatile octave_idx_type x_nz = b.nnz ();
+                  octave_idx_type x_nz = b.nnz ();
                   F77_INT b_nr = octave::to_f77_int (b.rows ());
                   octave_idx_type b_nc = b.cols ();
                   retval = SparseComplexMatrix (nr, b_nc, x_nz);
                   retval.xcidx (0) = 0;
-                  volatile octave_idx_type ii = 0;
+                  octave_idx_type ii = 0;
 
                   OCTAVE_LOCAL_BUFFER (double, Bx, nr);
                   OCTAVE_LOCAL_BUFFER (double, Bz, nr);
 
-                  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+                  for (octave_idx_type j = 0; j < b_nc; j++)
                     {
                       for (octave_idx_type i = 0; i < nr; i++)
                         {
@@ -5598,7 +5571,7 @@
 
   // Setup the control parameters
   Control = Matrix (UMFPACK_CONTROL, 1);
-  double *control = Control.fortran_vec ();
+  double *control = Control.rwdata ();
   UMFPACK_DNAME (defaults) (control);
 
   double tmp = octave::sparse_params::get_key ("spumoni");
@@ -5631,7 +5604,7 @@
 
   void *Symbolic;
   Info = Matrix (1, UMFPACK_INFO);
-  double *info = Info.fortran_vec ();
+  double *info = Info.rwdata ();
   int status = UMFPACK_DNAME (qsymbolic) (nr, nc,
                                           octave::to_suitesparse_intptr (Ap),
                                           octave::to_suitesparse_intptr (Ai),
@@ -5662,10 +5635,9 @@
         rcond = Info (UMFPACK_RCOND);
       else
         rcond = 1.;
-      volatile double rcond_plus_one = rcond + 1.0;
 
       if (status == UMFPACK_WARNING_singular_matrix
-          || rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+          || is_singular (rcond) || octave::math::isnan (rcond))
         {
           UMFPACK_DNAME (report_numeric) (Numeric, control);
 
@@ -5734,7 +5706,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -5813,9 +5785,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -5870,12 +5840,12 @@
               Control (UMFPACK_IRSTEP) = 1;
               const double *Bx = b.data ();
               retval.resize (b.rows (), b.cols ());
-              double *result = retval.fortran_vec ();
+              double *result = retval.rwdata ();
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const double *Ax = data ();
@@ -5945,7 +5915,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6034,9 +6004,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6100,8 +6068,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const double *Ax = data ();
@@ -6208,7 +6176,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6287,9 +6255,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6345,8 +6311,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const double *Ax = data ();
@@ -6440,7 +6406,7 @@
   else
     {
       // Print spparms("spumoni") info if requested
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
       mattype.info ();
 
       if (typ == MatrixType::Hermitian)
@@ -6529,9 +6495,7 @@
             }
           else
             {
-              volatile double rcond_plus_one = rcond + 1.0;
-
-              if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
+              if (is_singular (rcond) || octave::math::isnan (rcond))
                 {
                   err = -2;
 
@@ -6595,8 +6559,8 @@
               octave_idx_type b_nr = b.rows ();
               octave_idx_type b_nc = b.cols ();
               int status = 0;
-              double *control = Control.fortran_vec ();
-              double *info = Info.fortran_vec ();
+              double *control = Control.rwdata ();
+              double *info = Info.rwdata ();
               const octave_idx_type *Ap = cidx ();
               const octave_idx_type *Ai = ridx ();
               const double *Ax = data ();
@@ -6748,11 +6712,7 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<Matrix, SparseMatrix, Matrix> (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6812,12 +6772,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<SparseMatrix, SparseMatrix, SparseMatrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6877,12 +6833,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<ComplexMatrix, SparseMatrix, ComplexMatrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -6942,12 +6894,8 @@
   if (singular_fallback && mattype.type (false) == MatrixType::Rectangular)
     {
       rcond = 1.;
-#if defined (USE_QRSOLVE)
-      retval = qrsolve (*this, b, err);
-#else
       retval = dmsolve<SparseComplexMatrix, SparseMatrix, SparseComplexMatrix>
                (*this, b, err);
-#endif
     }
 
   return retval;
@@ -7207,7 +7155,7 @@
   if (neg_zero)
     {
       for (octave_idx_type i = 0; i < nel; i++)
-        if (lo_ieee_signbit (data (i)))
+        if (octave::math::signbit (data (i)))
           return true;
     }
   else
--- a/liboctave/array/dSparse.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dSparse.h	Fri Apr 12 15:10:26 2024 +0200
@@ -40,8 +40,7 @@
 #include "dMatrix.h"
 #include "dNDArray.h"
 
-class
-SparseMatrix : public MSparse<double>
+class SparseMatrix : public MSparse<double>
 {
 public:
 
--- a/liboctave/array/dim-vector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/dim-vector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,8 +30,6 @@
 
 #include "octave-config.h"
 
-#include <cassert>
-
 #include <algorithm>
 #include <initializer_list>
 #include <string>
@@ -88,9 +86,7 @@
 //! that rep points to the beginning of dims to grant faster access
 //! (reinterpret_cast is assumed to be an inexpensive operation).
 
-class
-OCTAVE_API
-dim_vector
+class OCTAVE_API dim_vector
 {
 private:
 
--- a/liboctave/array/fCColVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCColVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -265,7 +265,7 @@
   if (len == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_add2 (len, d, a.data ());
   return *this;
@@ -284,7 +284,7 @@
   if (len == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_sub2 (len, d, a.data ());
   return *this;
@@ -320,7 +320,7 @@
         retval.fill (0.0);
       else
         {
-          FloatComplex *y = retval.fortran_vec ();
+          FloatComplex *y = retval.rwdata ();
 
           F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 ("N", 1),
                                    nr, nc, 1.0f, F77_CONST_CMPLX_ARG (m.data ()), nr,
--- a/liboctave/array/fCColVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCColVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatComplexColumnVector : public MArray<FloatComplex>
+class OCTAVE_API FloatComplexColumnVector : public MArray<FloatComplex>
 {
   friend class FloatComplexMatrix;
   friend class FloatComplexRowVector;
--- a/liboctave/array/fCDiagMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCDiagMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -380,7 +380,7 @@
   if (r == 0 || c == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_add2 (length (), d, a.data ());
   return *this;
--- a/liboctave/array/fCDiagMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCDiagMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 #include "fRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatComplexDiagMatrix : public MDiagArray2<FloatComplex>
+class OCTAVE_API FloatComplexDiagMatrix : public MDiagArray2<FloatComplex>
 {
 public:
 
--- a/liboctave/array/fCMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -28,6 +28,7 @@
 #endif
 
 #include <algorithm>
+#include <cmath>
 #include <complex>
 #include <istream>
 #include <limits>
@@ -736,13 +737,21 @@
   return anorm;
 }
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const float rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<float>::epsilon ());
+}
+
 FloatComplexMatrix
 FloatComplexMatrix::inverse () const
 {
   octave_idx_type info;
   float rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatComplexMatrix
@@ -750,7 +759,7 @@
 {
   float rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatComplexMatrix
@@ -766,14 +775,14 @@
 {
   octave_idx_type info;
   float rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatComplexMatrix
 FloatComplexMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const
 {
   float rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatComplexMatrix
@@ -792,7 +801,7 @@
   char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
   char udiag = 'N';
   retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
+  FloatComplex *tmp_data = retval.rwdata ();
 
   F77_INT tmp_info = 0;
 
@@ -848,10 +857,10 @@
     (*current_liboctave_error_handler) ("inverse requires square matrix");
 
   Array<F77_INT> ipvt (dim_vector (nr, 1));
-  F77_INT *pipvt = ipvt.fortran_vec ();
+  F77_INT *pipvt = ipvt.rwdata ();
 
   retval = *this;
-  FloatComplex *tmp_data = retval.fortran_vec ();
+  FloatComplex *tmp_data = retval.rwdata ();
 
   Array<FloatComplex> z (dim_vector (1, 1));
   F77_INT lwork = -1;
@@ -861,13 +870,13 @@
   F77_INT tmp_info = 0;
 
   F77_XFCN (cgetri, CGETRI, (nc, F77_CMPLX_ARG (tmp_data), nr, pipvt,
-                             F77_CMPLX_ARG (z.fortran_vec ()), lwork,
+                             F77_CMPLX_ARG (z.rwdata ()), lwork,
                              tmp_info));
 
   lwork = static_cast<F77_INT> (std::real (z(0)));
   lwork = (lwork < 2 * nc ? 2 * nc : lwork);
   z.resize (dim_vector (lwork, 1));
-  FloatComplex *pz = z.fortran_vec ();
+  FloatComplex *pz = z.rwdata ();
 
   info = 0;
   tmp_info = 0;
@@ -902,7 +911,7 @@
           // Now calculate the condition number for non-singular matrix.
           char job = '1';
           Array<float> rz (dim_vector (2 * nc, 1));
-          float *prz = rz.fortran_vec ();
+          float *prz = rz.rwdata ();
           F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                      nc, F77_CMPLX_ARG (tmp_data), nr, anorm,
                                      rcon, F77_CMPLX_ARG (pz), prz, cgecon_info
@@ -1066,7 +1075,7 @@
     }
 
   const FloatComplex *in (data ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::fft (in, out, npts, nsamples);
 
@@ -1095,7 +1104,7 @@
     }
 
   const FloatComplex *in (data ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifft (in, out, npts, nsamples);
 
@@ -1109,7 +1118,7 @@
 
   FloatComplexMatrix retval (rows (), cols ());
   const FloatComplex *in (data ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, 2, dv);
 
@@ -1123,7 +1132,7 @@
 
   FloatComplexMatrix retval (rows (), cols ());
   const FloatComplex *in (data ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, 2, dv);
 
@@ -1209,7 +1218,7 @@
   if (nr != nc)
     (*current_liboctave_error_handler) ("matrix must be square");
 
-  volatile int typ = mattype.type ();
+  int typ = mattype.type ();
 
   // Even though the matrix is marked as singular (Rectangular), we may
   // still get a useful number from the LU factorization, because it always
@@ -1228,7 +1237,7 @@
   else if (typ == MatrixType::Hermitian)
     {
       FloatComplexMatrix atmp = *this;
-      FloatComplex *tmp_data = atmp.fortran_vec ();
+      FloatComplex *tmp_data = atmp.rwdata ();
 
       float anorm;
       if (calc_cond)
@@ -1254,9 +1263,9 @@
           if (calc_cond)
             {
               Array<FloatComplex> z (dim_vector (2 * nc, 1));
-              FloatComplex *pz = z.fortran_vec ();
+              FloatComplex *pz = z.rwdata ();
               Array<float> rz (dim_vector (nc, 1));
-              float *prz = rz.fortran_vec ();
+              float *prz = rz.rwdata ();
 
               F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nr, F77_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1281,10 +1290,10 @@
   if (typ == MatrixType::Full)
     {
       Array<F77_INT> ipvt (dim_vector (nr, 1));
-      F77_INT *pipvt = ipvt.fortran_vec ();
+      F77_INT *pipvt = ipvt.rwdata ();
 
       FloatComplexMatrix atmp = *this;
-      FloatComplex *tmp_data = atmp.fortran_vec ();
+      FloatComplex *tmp_data = atmp.rwdata ();
 
       info = 0;
 
@@ -1318,9 +1327,9 @@
               // Now calc the condition number for non-singular matrix.
               char job = '1';
               Array<FloatComplex> z (dim_vector (2 * nc, 1));
-              FloatComplex *pz = z.fortran_vec ();
+              FloatComplex *pz = z.rwdata ();
               Array<float> rz (dim_vector (2 * nc, 1));
-              float *prz = rz.fortran_vec ();
+              float *prz = rz.rwdata ();
 
               F77_XFCN (cgecon, CGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nc, F77_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1370,7 +1379,7 @@
     rcon = octave::numeric_limits<float>::Inf ();
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Unknown)
         typ = mattype.type (*this);
@@ -1385,9 +1394,9 @@
           char dia = 'N';
 
           Array<FloatComplex> z (dim_vector (2 * nc, 1));
-          FloatComplex *pz = z.fortran_vec ();
+          FloatComplex *pz = z.rwdata ();
           Array<float> rz (dim_vector (nc, 1));
-          float *prz = rz.fortran_vec ();
+          float *prz = rz.rwdata ();
 
           F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1413,9 +1422,9 @@
           char dia = 'N';
 
           Array<FloatComplex> z (dim_vector (2 * nc, 1));
-          FloatComplex *pz = z.fortran_vec ();
+          FloatComplex *pz = z.rwdata ();
           Array<float> rz (dim_vector (nc, 1));
-          float *prz = rz.fortran_vec ();
+          float *prz = rz.rwdata ();
 
           F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1442,7 +1451,7 @@
               char job = 'L';
 
               FloatComplexMatrix atmp = *this;
-              FloatComplex *tmp_data = atmp.fortran_vec ();
+              FloatComplex *tmp_data = atmp.rwdata ();
 
               anorm = norm1 (atmp);
 
@@ -1460,9 +1469,9 @@
               else
                 {
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
-                  FloatComplex *pz = z.fortran_vec ();
+                  FloatComplex *pz = z.rwdata ();
                   Array<float> rz (dim_vector (nc, 1));
-                  float *prz = rz.fortran_vec ();
+                  float *prz = rz.rwdata ();
 
                   F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, F77_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1479,18 +1488,18 @@
               F77_INT info = 0;
 
               FloatComplexMatrix atmp = *this;
-              FloatComplex *tmp_data = atmp.fortran_vec ();
+              FloatComplex *tmp_data = atmp.rwdata ();
 
               Array<F77_INT> ipvt (dim_vector (nr, 1));
-              F77_INT *pipvt = ipvt.fortran_vec ();
+              F77_INT *pipvt = ipvt.rwdata ();
 
               if (anorm < 0.0)
                 anorm = norm1 (atmp);
 
               Array<FloatComplex> z (dim_vector (2 * nc, 1));
-              FloatComplex *pz = z.fortran_vec ();
+              FloatComplex *pz = z.rwdata ();
               Array<float> rz (dim_vector (2 * nc, 1));
-              float *prz = rz.fortran_vec ();
+              float *prz = rz.rwdata ();
 
               // Work around bug #45577, LAPACK crashes Octave if norm is NaN
               if (octave::math::isnan (anorm))
@@ -1546,7 +1555,7 @@
     retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper)
         {
@@ -1561,7 +1570,7 @@
               const FloatComplex *tmp_data = data ();
 
               retval = b;
-              FloatComplex *result = retval.fortran_vec ();
+              FloatComplex *result = retval.rwdata ();
 
               char uplo = 'U';
               char trans = get_blas_char (transt);
@@ -1587,9 +1596,9 @@
                   dia = 'N';
 
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
-                  FloatComplex *pz = z.fortran_vec ();
+                  FloatComplex *pz = z.rwdata ();
                   Array<float> rz (dim_vector (nc, 1));
-                  float *prz = rz.fortran_vec ();
+                  float *prz = rz.rwdata ();
 
                   F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1605,9 +1614,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1648,7 +1655,7 @@
     retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower)
         {
@@ -1663,7 +1670,7 @@
               const FloatComplex *tmp_data = data ();
 
               retval = b;
-              FloatComplex *result = retval.fortran_vec ();
+              FloatComplex *result = retval.rwdata ();
 
               char uplo = 'L';
               char trans = get_blas_char (transt);
@@ -1689,9 +1696,9 @@
                   dia = 'N';
 
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
-                  FloatComplex *pz = z.fortran_vec ();
+                  FloatComplex *pz = z.rwdata ();
                   Array<float> rz (dim_vector (nc, 1));
-                  float *prz = rz.fortran_vec ();
+                  float *prz = rz.rwdata ();
 
                   F77_XFCN (ctrcon, CTRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1707,9 +1714,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1750,7 +1755,7 @@
     retval = FloatComplexMatrix (nc, b_nc, FloatComplex (0.0, 0.0));
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       float anorm = -1.0;
@@ -1761,7 +1766,7 @@
           char job = 'L';
 
           FloatComplexMatrix atmp = *this;
-          FloatComplex *tmp_data = atmp.fortran_vec ();
+          FloatComplex *tmp_data = atmp.rwdata ();
 
           // The norm of the matrix for later use when determining rcon.
           if (calc_cond)
@@ -1789,9 +1794,9 @@
               if (calc_cond)
                 {
                   Array<FloatComplex> z (dim_vector (2 * nc, 1));
-                  FloatComplex *pz = z.fortran_vec ();
+                  FloatComplex *pz = z.rwdata ();
                   Array<float> rz (dim_vector (nc, 1));
-                  float *prz = rz.fortran_vec ();
+                  float *prz = rz.rwdata ();
 
                   F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, F77_CMPLX_ARG (tmp_data), nr, anorm,
@@ -1803,9 +1808,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1819,7 +1822,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  FloatComplex *result = retval.fortran_vec ();
+                  FloatComplex *result = retval.rwdata ();
 
                   F77_XFCN (cpotrs, CPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, b_nc, F77_CMPLX_ARG (tmp_data), nr,
@@ -1841,15 +1844,15 @@
           info = 0;
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           FloatComplexMatrix atmp = *this;
-          FloatComplex *tmp_data = atmp.fortran_vec ();
+          FloatComplex *tmp_data = atmp.rwdata ();
 
           Array<FloatComplex> z (dim_vector (2 * nc, 1));
-          FloatComplex *pz = z.fortran_vec ();
+          FloatComplex *pz = z.rwdata ();
           Array<float> rz (dim_vector (2 * nc, 1));
-          float *prz = rz.fortran_vec ();
+          float *prz = rz.rwdata ();
 
           // Calculate the norm of the matrix, for later use.
           if (calc_cond && anorm < 0.0)
@@ -1898,9 +1901,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       if (sing_handler)
                         sing_handler (rcon);
@@ -1912,7 +1913,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  FloatComplex *result = retval.fortran_vec ();
+                  FloatComplex *result = retval.rwdata ();
 
                   char job = 'N';
                   F77_XFCN (cgetrs, CGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -2320,7 +2321,7 @@
     retval = FloatComplexMatrix (n, b_nc, FloatComplex (0.0, 0.0));
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2336,11 +2337,11 @@
         retval = b;
 
       FloatComplexMatrix atmp = *this;
-      FloatComplex *tmp_data = atmp.fortran_vec ();
-
-      FloatComplex *pretval = retval.fortran_vec ();
+      FloatComplex *tmp_data = atmp.rwdata ();
+
+      FloatComplex *pretval = retval.rwdata ();
       Array<float> s (dim_vector (minmn, 1));
-      float *ps = s.fortran_vec ();
+      float *ps = s.rwdata ();
 
       // Ask ZGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2379,20 +2380,20 @@
       if (lrwork < 1)
         lrwork = 1;
       Array<float> rwork (dim_vector (lrwork, 1));
-      float *prwork = rwork.fortran_vec ();
+      float *prwork = rwork.rwdata ();
 
       F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,
                                  F77_CMPLX_ARG (pretval), maxmn,
-                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.fortran_vec ()),
+                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.rwdata ()),
                                  lwork, prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2449,7 +2450,7 @@
           F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data),
                                      m, F77_CMPLX_ARG (pretval),
                                      maxmn, ps, rcon, tmp_rank,
-                                     F77_CMPLX_ARG (work.fortran_vec ()),
+                                     F77_CMPLX_ARG (work.rwdata ()),
                                      lwork, prwork, piwork, tmp_info));
 
           info = tmp_info;
@@ -2550,7 +2551,7 @@
     retval = FloatComplexColumnVector (n, FloatComplex (0.0, 0.0));
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2565,11 +2566,11 @@
         retval = b;
 
       FloatComplexMatrix atmp = *this;
-      FloatComplex *tmp_data = atmp.fortran_vec ();
-
-      FloatComplex *pretval = retval.fortran_vec ();
+      FloatComplex *tmp_data = atmp.rwdata ();
+
+      FloatComplex *pretval = retval.rwdata ();
       Array<float> s (dim_vector (minmn, 1));
-      float *ps = s.fortran_vec ();
+      float *ps = s.rwdata ();
 
       // Ask ZGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2599,20 +2600,20 @@
       if (lrwork < 1)
         lrwork = 1;
       Array<float> rwork (dim_vector (lrwork, 1));
-      float *prwork = rwork.fortran_vec ();
+      float *prwork = rwork.rwdata ();
 
       F77_INT liwork = 3 * minmn * nlvl + 11 * minmn;
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,
                                  F77_CMPLX_ARG (pretval), maxmn,
-                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.fortran_vec ()),
+                                 ps, rcon, tmp_rank, F77_CMPLX_ARG (work.rwdata ()),
                                  lwork, prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2626,7 +2627,7 @@
       F77_XFCN (cgelsd, CGELSD, (m, n, nrhs, F77_CMPLX_ARG (tmp_data), m,
                                  F77_CMPLX_ARG (pretval),
                                  maxmn, ps, rcon, tmp_rank,
-                                 F77_CMPLX_ARG (work.fortran_vec ()), lwork,
+                                 F77_CMPLX_ARG (work.rwdata ()), lwork,
                                  prwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2674,7 +2675,7 @@
       F77_INT a_len = octave::to_f77_int (a.numel ());
 
       retval = FloatComplexMatrix (len, a_len);
-      FloatComplex *c = retval.fortran_vec ();
+      FloatComplex *c = retval.rwdata ();
 
       F77_XFCN (cgemm, CGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
                                F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2778,7 +2779,7 @@
   if (nr == 0 || nc == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_add2 (numel (), d, a.data ());
   return *this;
@@ -2799,7 +2800,7 @@
   if (nr == 0 || nc == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_sub2 (numel (), d, a.data ());
   return *this;
@@ -3307,9 +3308,9 @@
   float scale;
   F77_INT info;
 
-  FloatComplex *pa = sch_a.fortran_vec ();
-  FloatComplex *pb = sch_b.fortran_vec ();
-  FloatComplex *px = cx.fortran_vec ();
+  FloatComplex *pa = sch_a.rwdata ();
+  FloatComplex *pb = sch_b.rwdata ();
+  FloatComplex *px = cx.rwdata ();
 
   F77_XFCN (ctrsyl, CTRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
                              F77_CONST_CHAR_ARG2 ("N", 1),
@@ -3406,7 +3407,7 @@
       // use the result matrix before zeroing the elements.
 
       retval = FloatComplexMatrix (a_nr, b_nc, 0.0);
-      FloatComplex *c = retval.fortran_vec ();
+      FloatComplex *c = retval.rwdata ();
 
       const char ctra = get_blas_trans_arg (tra, cja);
       if (cja || cjb)
@@ -3444,7 +3445,7 @@
       F77_INT tdb = octave::to_f77_int (b.cols ());
 
       retval = FloatComplexMatrix (a_nr, b_nc, 0.0);
-      FloatComplex *c = retval.fortran_vec ();
+      FloatComplex *c = retval.rwdata ();
 
       if (b_nc == 1 && a_nr == 1)
         {
--- a/liboctave/array/fCMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 #include "mx-op-decl.h"
 #include "oct-cmplx.h"
 
-class
-OCTAVE_API
-FloatComplexMatrix : public FloatComplexNDArray
+class OCTAVE_API FloatComplexMatrix : public FloatComplexNDArray
 {
 public:
 
@@ -215,8 +213,8 @@
   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,
-           bool calc_cond = true) const;
+  inverse (octave_idx_type& info, float& rcon,
+           bool force = false, bool calc_cond = true) const;
 
   OCTAVE_API FloatComplexMatrix inverse (MatrixType& mattype) const;
   OCTAVE_API FloatComplexMatrix
--- a/liboctave/array/fCNDArray.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCNDArray.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,7 @@
 FloatComplexNDArray
 FloatComplexNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return FloatComplexNDArray ();
@@ -75,7 +75,7 @@
 
   const FloatComplex *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -88,7 +88,7 @@
 FloatComplexNDArray
 FloatComplexNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return FloatComplexNDArray ();
@@ -106,7 +106,7 @@
 
   const FloatComplex *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -119,14 +119,14 @@
 FloatComplexNDArray
 FloatComplexNDArray::fourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return FloatComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const FloatComplex *in = data ();
   FloatComplexNDArray retval (dv);
-  FloatComplex *out = retval.fortran_vec ();
+  FloatComplex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -139,14 +139,14 @@
 FloatComplexNDArray
 FloatComplexNDArray::ifourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return FloatComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const FloatComplex *in = data ();
   FloatComplexNDArray retval (dv);
-  FloatComplex *out = retval.fortran_vec ();
+  FloatComplex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -159,12 +159,12 @@
 FloatComplexNDArray
 FloatComplexNDArray::fourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const FloatComplex *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, rank, dv);
 
@@ -174,12 +174,12 @@
 FloatComplexNDArray
 FloatComplexNDArray::ifourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const FloatComplex *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, rank, dv);
 
@@ -520,8 +520,8 @@
 FloatComplexNDArray::insert (const NDArray& a,
                              octave_idx_type r, octave_idx_type c)
 {
-  dim_vector a_dv = a.dims ();
-  dim_vector dv = dims ();
+  const dim_vector& a_dv = a.dims ();
+  const dim_vector& dv = dims ();
 
   int n = a_dv.ndims ();
 
--- a/liboctave/array/fCNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-FloatComplexNDArray : public MArray<FloatComplex>
+class OCTAVE_API FloatComplexNDArray : public MArray<FloatComplex>
 {
 public:
 
--- a/liboctave/array/fCRowVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCRowVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -254,7 +254,7 @@
   if (len == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_add2 (len, d, a.data ());
   return *this;
@@ -273,7 +273,7 @@
   if (len == 0)
     return *this;
 
-  FloatComplex *d = fortran_vec (); // Ensures only 1 reference to my privates!
+  FloatComplex *d = rwdata (); // Ensures only 1 reference to my privates!
 
   mx_inline_sub2 (len, d, a.data ());
   return *this;
@@ -303,7 +303,7 @@
       F77_INT ld = a_nr;
 
       retval.resize (a_nc);
-      FloatComplex *y = retval.fortran_vec ();
+      FloatComplex *y = retval.rwdata ();
 
       F77_XFCN (cgemv, CGEMV, (F77_CONST_CHAR_ARG2 ("T", 1),
                                a_nr, a_nc, 1.0, F77_CONST_CMPLX_ARG (a.data ()),
--- a/liboctave/array/fCRowVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fCRowVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,9 +32,7 @@
 #include "fRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatComplexRowVector : public MArray<FloatComplex>
+class OCTAVE_API FloatComplexRowVector : public MArray<FloatComplex>
 {
   friend class FloatComplexColumnVector;
 
--- a/liboctave/array/fColVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fColVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -196,7 +196,7 @@
         retval.fill (0.0);
       else
         {
-          float *y = retval.fortran_vec ();
+          float *y = retval.rwdata ();
 
           F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 ("N", 1),
                                    nr, nc, 1.0f, m.data (), nr,
--- a/liboctave/array/fColVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fColVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatColumnVector : public MArray<float>
+class OCTAVE_API FloatColumnVector : public MArray<float>
 {
 public:
 
--- a/liboctave/array/fDiagMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fDiagMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 #include "fRowVector.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatDiagMatrix : public MDiagArray2<float>
+class OCTAVE_API FloatDiagMatrix : public MDiagArray2<float>
 {
 public:
 
--- a/liboctave/array/fMatrix.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fMatrix.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -28,6 +28,7 @@
 #endif
 
 #include <algorithm>
+#include <cmath>
 #include <istream>
 #include <limits>
 #include <ostream>
@@ -453,13 +454,21 @@
   return anorm;
 }
 
+// Local function to check if matrix is singular based on rcond.
+static inline
+bool
+is_singular (const float rcond)
+{
+  return (std::abs (rcond) <= std::numeric_limits<float>::epsilon ());
+}
+
 FloatMatrix
 FloatMatrix::inverse () const
 {
   octave_idx_type info;
   float rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatMatrix
@@ -467,12 +476,12 @@
 {
   float rcon;
   MatrixType mattype (*this);
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatMatrix
-FloatMatrix::inverse (octave_idx_type& info, float& rcon, bool force,
-                      bool calc_cond) const
+FloatMatrix::inverse (octave_idx_type& info, float& rcon,
+                      bool force, bool calc_cond) const
 {
   MatrixType mattype (*this);
   return inverse (mattype, info, rcon, force, calc_cond);
@@ -483,14 +492,14 @@
 {
   octave_idx_type info;
   float rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatMatrix
 FloatMatrix::inverse (MatrixType& mattype, octave_idx_type& info) const
 {
   float rcon;
-  return inverse (mattype, info, rcon, 0, 0);
+  return inverse (mattype, info, rcon, false, false);
 }
 
 FloatMatrix
@@ -509,7 +518,7 @@
   char uplo = (typ == MatrixType::Lower ? 'L' : 'U');
   char udiag = 'N';
   retval = *this;
-  float *tmp_data = retval.fortran_vec ();
+  float *tmp_data = retval.rwdata ();
 
   F77_INT tmp_info = 0;
 
@@ -565,10 +574,10 @@
     (*current_liboctave_error_handler) ("inverse requires square matrix");
 
   Array<F77_INT> ipvt (dim_vector (nr, 1));
-  F77_INT *pipvt = ipvt.fortran_vec ();
+  F77_INT *pipvt = ipvt.rwdata ();
 
   retval = *this;
-  float *tmp_data = retval.fortran_vec ();
+  float *tmp_data = retval.rwdata ();
 
   Array<float> z (dim_vector (1, 1));
   F77_INT lwork = -1;
@@ -577,12 +586,12 @@
 
   // Query the optimum work array size.
   F77_XFCN (sgetri, SGETRI, (nc, tmp_data, nr, pipvt,
-                             z.fortran_vec (), lwork, tmp_info));
+                             z.rwdata (), lwork, tmp_info));
 
   lwork = static_cast<F77_INT> (z(0));
   lwork = (lwork < 4 * nc ? 4 * nc : lwork);
   z.resize (dim_vector (lwork, 1));
-  float *pz = z.fortran_vec ();
+  float *pz = z.rwdata ();
 
   info = 0;
   tmp_info = 0;
@@ -611,7 +620,7 @@
           // Now calculate the condition number for non-singular matrix.
           char job = '1';
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
           F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                      nc, tmp_data, nr, anorm,
                                      rcon, pz, piz, sgecon_info
@@ -758,7 +767,7 @@
     }
 
   const float *in (data ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::fft (in, out, npts, nsamples);
 
@@ -787,8 +796,8 @@
     }
 
   FloatComplexMatrix tmp (*this);
-  FloatComplex *in (tmp.fortran_vec ());
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *in (tmp.rwdata ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifft (in, out, npts, nsamples);
 
@@ -802,7 +811,7 @@
 
   const float *in = data ();
   FloatComplexMatrix retval (rows (), cols ());
-  octave::fftw::fftNd (in, retval.fortran_vec (), 2, dv);
+  octave::fftw::fftNd (in, retval.rwdata (), 2, dv);
 
   return retval;
 }
@@ -813,7 +822,7 @@
   dim_vector dv (rows (), cols ());
 
   FloatComplexMatrix retval (*this);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (out, out, 2, dv);
 
@@ -899,7 +908,7 @@
   if (nr != nc)
     (*current_liboctave_error_handler) ("matrix must be square");
 
-  volatile int typ = mattype.type ();
+  int typ = mattype.type ();
 
   // Even though the matrix is marked as singular (Rectangular), we may
   // still get a useful number from the LU factorization, because it always
@@ -918,7 +927,7 @@
   else if (typ == MatrixType::Hermitian)
     {
       FloatMatrix atmp = *this;
-      float *tmp_data = atmp.fortran_vec ();
+      float *tmp_data = atmp.rwdata ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       float anorm;
@@ -945,9 +954,9 @@
           if (calc_cond)
             {
               Array<float> z (dim_vector (3 * nc, 1));
-              float *pz = z.fortran_vec ();
+              float *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nr, tmp_data, nr, anorm,
@@ -972,10 +981,10 @@
   if (typ == MatrixType::Full)
     {
       Array<F77_INT> ipvt (dim_vector (nr, 1));
-      F77_INT *pipvt = ipvt.fortran_vec ();
+      F77_INT *pipvt = ipvt.rwdata ();
 
       FloatMatrix atmp = *this;
-      float *tmp_data = atmp.fortran_vec ();
+      float *tmp_data = atmp.rwdata ();
 
       info = 0;
       F77_INT tmp_info = 0;
@@ -1003,9 +1012,9 @@
               // Now calc the condition number for non-singular matrix.
               char job = '1';
               Array<float> z (dim_vector (4 * nc, 1));
-              float *pz = z.fortran_vec ();
+              float *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (sgecon, SGECON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                          nc, tmp_data, nr, anorm,
@@ -1055,7 +1064,7 @@
     rcon = octave::numeric_limits<float>::Inf ();
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Unknown)
         typ = mattype.type (*this);
@@ -1070,9 +1079,9 @@
           char dia = 'N';
 
           Array<float> z (dim_vector (3 * nc, 1));
-          float *pz = z.fortran_vec ();
+          float *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1098,9 +1107,9 @@
           char dia = 'N';
 
           Array<float> z (dim_vector (3 * nc, 1));
-          float *pz = z.fortran_vec ();
+          float *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                      F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1127,7 +1136,7 @@
               char job = 'L';
 
               FloatMatrix atmp = *this;
-              float *tmp_data = atmp.fortran_vec ();
+              float *tmp_data = atmp.rwdata ();
 
               anorm = norm1 (atmp);
 
@@ -1144,9 +1153,9 @@
               else
                 {
                   Array<float> z (dim_vector (3 * nc, 1));
-                  float *pz = z.fortran_vec ();
+                  float *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, tmp_data, nr, anorm,
@@ -1163,18 +1172,18 @@
               F77_INT info = 0;
 
               FloatMatrix atmp = *this;
-              float *tmp_data = atmp.fortran_vec ();
+              float *tmp_data = atmp.rwdata ();
 
               Array<F77_INT> ipvt (dim_vector (nr, 1));
-              F77_INT *pipvt = ipvt.fortran_vec ();
+              F77_INT *pipvt = ipvt.rwdata ();
 
               if (anorm < 0.0)
                 anorm = norm1 (atmp);
 
               Array<float> z (dim_vector (4 * nc, 1));
-              float *pz = z.fortran_vec ();
+              float *pz = z.rwdata ();
               Array<F77_INT> iz (dim_vector (nc, 1));
-              F77_INT *piz = iz.fortran_vec ();
+              F77_INT *piz = iz.rwdata ();
 
               F77_XFCN (sgetrf, SGETRF, (nr, nr, tmp_data, nr, pipvt, info));
 
@@ -1225,7 +1234,7 @@
     retval = FloatMatrix (nc, b_nc, 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Permuted_Upper || typ == MatrixType::Upper)
         {
@@ -1240,7 +1249,7 @@
               const float *tmp_data = data ();
 
               retval = b;
-              float *result = retval.fortran_vec ();
+              float *result = retval.rwdata ();
 
               char uplo = 'U';
               char trans = get_blas_char (transt);
@@ -1266,9 +1275,9 @@
                   dia = 'N';
 
                   Array<float> z (dim_vector (3 * nc, 1));
-                  float *pz = z.fortran_vec ();
+                  float *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1284,9 +1293,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1328,7 +1335,7 @@
     retval = FloatMatrix (nc, b_nc, 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       if (typ == MatrixType::Permuted_Lower || typ == MatrixType::Lower)
         {
@@ -1343,7 +1350,7 @@
               const float *tmp_data = data ();
 
               retval = b;
-              float *result = retval.fortran_vec ();
+              float *result = retval.rwdata ();
 
               char uplo = 'L';
               char trans = get_blas_char (transt);
@@ -1369,9 +1376,9 @@
                   dia = 'N';
 
                   Array<float> z (dim_vector (3 * nc, 1));
-                  float *pz = z.fortran_vec ();
+                  float *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (strcon, STRCON, (F77_CONST_CHAR_ARG2 (&norm, 1),
                                              F77_CONST_CHAR_ARG2 (&uplo, 1),
@@ -1387,9 +1394,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1430,7 +1435,7 @@
     retval = FloatMatrix (nc, b_nc, 0.0);
   else
     {
-      volatile int typ = mattype.type ();
+      int typ = mattype.type ();
 
       // Calculate the norm of the matrix for later use when determining rcon.
       float anorm = -1.0;
@@ -1441,7 +1446,7 @@
           char job = 'L';
 
           FloatMatrix atmp = *this;
-          float *tmp_data = atmp.fortran_vec ();
+          float *tmp_data = atmp.rwdata ();
 
           // The norm of the matrix for later use when determining rcon.
           if (calc_cond)
@@ -1469,9 +1474,9 @@
               if (calc_cond)
                 {
                   Array<float> z (dim_vector (3 * nc, 1));
-                  float *pz = z.fortran_vec ();
+                  float *pz = z.rwdata ();
                   Array<F77_INT> iz (dim_vector (nc, 1));
-                  F77_INT *piz = iz.fortran_vec ();
+                  F77_INT *piz = iz.rwdata ();
 
                   F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, tmp_data, nr, anorm,
@@ -1483,9 +1488,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       info = -2;
 
@@ -1499,7 +1502,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  float *result = retval.fortran_vec ();
+                  float *result = retval.rwdata ();
 
                   F77_XFCN (spotrs, SPOTRS, (F77_CONST_CHAR_ARG2 (&job, 1),
                                              nr, b_nc, tmp_data, nr,
@@ -1521,18 +1524,18 @@
           info = 0;
 
           Array<F77_INT> ipvt (dim_vector (nr, 1));
-          F77_INT *pipvt = ipvt.fortran_vec ();
+          F77_INT *pipvt = ipvt.rwdata ();
 
           FloatMatrix atmp = *this;
-          float *tmp_data = atmp.fortran_vec ();
+          float *tmp_data = atmp.rwdata ();
 
           if (calc_cond && anorm < 0.0)
             anorm = norm1 (atmp);
 
           Array<float> z (dim_vector (4 * nc, 1));
-          float *pz = z.fortran_vec ();
+          float *pz = z.rwdata ();
           Array<F77_INT> iz (dim_vector (nc, 1));
-          F77_INT *piz = iz.fortran_vec ();
+          F77_INT *piz = iz.rwdata ();
 
           F77_INT tmp_info = 0;
 
@@ -1569,9 +1572,7 @@
                   if (info != 0)
                     info = -2;
 
-                  volatile float rcond_plus_one = rcon + 1.0;
-
-                  if (rcond_plus_one == 1.0 || octave::math::isnan (rcon))
+                  if (is_singular (rcon) || octave::math::isnan (rcon))
                     {
                       if (sing_handler)
                         sing_handler (rcon);
@@ -1583,7 +1584,7 @@
               if (info == 0)
                 {
                   retval = b;
-                  float *result = retval.fortran_vec ();
+                  float *result = retval.rwdata ();
 
                   char job = 'N';
                   F77_XFCN (sgetrs, SGETRS, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -1694,7 +1695,7 @@
   octave_idx_type nel = m*n;
   FloatMatrix retval (m, 2*n);
   const FloatComplex *cmd = cm.data ();
-  float *rd = retval.fortran_vec ();
+  float *rd = retval.rwdata ();
   for (octave_idx_type i = 0; i < nel; i++)
     {
       rd[i] = std::real (cmd[i]);
@@ -1711,7 +1712,7 @@
   octave_idx_type nel = m*n;
   FloatComplexMatrix retval (m, n);
   const float *smd = sm.data ();
-  FloatComplex *rd = retval.fortran_vec ();
+  FloatComplex *rd = retval.rwdata ();
   for (octave_idx_type i = 0; i < nel; i++)
     rd[i] = FloatComplex (smd[i], smd[nel+i]);
   return retval;
@@ -1970,7 +1971,7 @@
     retval = FloatMatrix (n, b_nc, 0.0);
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
       if (m != n)
@@ -1985,11 +1986,11 @@
         retval = b;
 
       FloatMatrix atmp = *this;
-      float *tmp_data = atmp.fortran_vec ();
-
-      float *pretval = retval.fortran_vec ();
+      float *tmp_data = atmp.rwdata ();
+
+      float *pretval = retval.rwdata ();
       Array<float> s (dim_vector (minmn, 1));
-      float *ps = s.fortran_vec ();
+      float *ps = s.rwdata ();
 
       // Ask DGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2024,13 +2025,13 @@
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
-                                 ps, rcon, tmp_rank, work.fortran_vec (),
+                                 ps, rcon, tmp_rank, work.rwdata (),
                                  lwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2093,7 +2094,7 @@
         {
           F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
                                      maxmn, ps, rcon, tmp_rank,
-                                     work.fortran_vec (), lwork,
+                                     work.rwdata (), lwork,
                                      piwork, tmp_info));
 
           info = tmp_info;
@@ -2191,7 +2192,7 @@
     retval = FloatColumnVector (n, 0.0);
   else
     {
-      volatile F77_INT minmn = (m < n ? m : n);
+      F77_INT minmn = (m < n ? m : n);
       F77_INT maxmn = (m > n ? m : n);
       rcon = -1.0;
 
@@ -2206,11 +2207,11 @@
         retval = b;
 
       FloatMatrix atmp = *this;
-      float *tmp_data = atmp.fortran_vec ();
-
-      float *pretval = retval.fortran_vec ();
+      float *tmp_data = atmp.rwdata ();
+
+      float *pretval = retval.rwdata ();
       Array<float> s (dim_vector (minmn, 1));
-      float *ps = s.fortran_vec ();
+      float *ps = s.rwdata ();
 
       // Ask DGELSD what the dimension of WORK should be.
       F77_INT lwork = -1;
@@ -2238,13 +2239,13 @@
       if (liwork < 1)
         liwork = 1;
       Array<F77_INT> iwork (dim_vector (liwork, 1));
-      F77_INT *piwork = iwork.fortran_vec ();
+      F77_INT *piwork = iwork.rwdata ();
 
       F77_INT tmp_info = 0;
       F77_INT tmp_rank = 0;
 
       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval, maxmn,
-                                 ps, rcon, tmp_rank, work.fortran_vec (),
+                                 ps, rcon, tmp_rank, work.rwdata (),
                                  lwork, piwork, tmp_info));
 
       info = tmp_info;
@@ -2255,7 +2256,7 @@
 
       F77_XFCN (sgelsd, SGELSD, (m, n, nrhs, tmp_data, m, pretval,
                                  maxmn, ps, rcon, tmp_rank,
-                                 work.fortran_vec (), lwork,
+                                 work.rwdata (), lwork,
                                  piwork, tmp_info));
 
       info = tmp_info;
@@ -2362,7 +2363,7 @@
       F77_INT a_len = octave::to_f77_int (a.numel ());
 
       retval = FloatMatrix (len, a_len);
-      float *c = retval.fortran_vec ();
+      float *c = retval.rwdata ();
 
       F77_XFCN (sgemm, SGEMM, (F77_CONST_CHAR_ARG2 ("N", 1),
                                F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2741,9 +2742,9 @@
   float scale;
   F77_INT info;
 
-  float *pa = sch_a.fortran_vec ();
-  float *pb = sch_b.fortran_vec ();
-  float *px = cx.fortran_vec ();
+  float *pa = sch_a.rwdata ();
+  float *pb = sch_b.rwdata ();
+  float *px = cx.rwdata ();
 
   F77_XFCN (strsyl, STRSYL, (F77_CONST_CHAR_ARG2 ("N", 1),
                              F77_CONST_CHAR_ARG2 ("N", 1),
@@ -2813,7 +2814,7 @@
       F77_INT lda = octave::to_f77_int (a.rows ());
 
       retval = FloatMatrix (a_nr, b_nc);
-      float *c = retval.fortran_vec ();
+      float *c = retval.rwdata ();
 
       const char ctra = get_blas_trans_arg (tra);
       F77_XFCN (ssyrk, SSYRK, (F77_CONST_CHAR_ARG2 ("U", 1),
@@ -2835,7 +2836,7 @@
       F77_INT tdb = octave::to_f77_int (b.cols ());
 
       retval = FloatMatrix (a_nr, b_nc);
-      float *c = retval.fortran_vec ();
+      float *c = retval.rwdata ();
 
       if (b_nc == 1)
         {
--- a/liboctave/array/fMatrix.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fMatrix.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-FloatMatrix : public FloatNDArray
+class OCTAVE_API FloatMatrix : public FloatNDArray
 {
 public:
 
@@ -171,8 +169,8 @@
   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,
-           bool calc_cond = true) const;
+  inverse (octave_idx_type& info, float& rcon,
+           bool force = false, bool calc_cond = true) const;
 
   OCTAVE_API FloatMatrix inverse (MatrixType& mattype) const;
   OCTAVE_API FloatMatrix
--- a/liboctave/array/fNDArray.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fNDArray.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -57,7 +57,7 @@
 FloatComplexNDArray
 FloatNDArray::fourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return FloatComplexNDArray ();
@@ -75,7 +75,7 @@
 
   const float *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -88,7 +88,7 @@
 FloatComplexNDArray
 FloatNDArray::ifourier (int dim) const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
 
   if (dim > dv.ndims () || dim < 0)
     return FloatComplexNDArray ();
@@ -105,7 +105,7 @@
   octave_idx_type dist = (stride == 1 ? n : 1);
 
   FloatComplexNDArray retval (*this);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   // Need to be careful here about the distance between fft's
   for (octave_idx_type k = 0; k < nloop; k++)
@@ -118,14 +118,14 @@
 FloatComplexNDArray
 FloatNDArray::fourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return FloatComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   const float *in = data ();
   FloatComplexNDArray retval (dv);
-  FloatComplex *out = retval.fortran_vec ();
+  FloatComplex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -138,13 +138,13 @@
 FloatComplexNDArray
 FloatNDArray::ifourier2d () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   if (dv.ndims () < 2)
     return FloatComplexNDArray ();
 
   dim_vector dv2 (dv(0), dv(1));
   FloatComplexNDArray retval (*this);
-  FloatComplex *out = retval.fortran_vec ();
+  FloatComplex *out = retval.rwdata ();
   octave_idx_type howmany = numel () / dv(0) / dv(1);
   octave_idx_type dist = dv(0) * dv(1);
 
@@ -157,12 +157,12 @@
 FloatComplexNDArray
 FloatNDArray::fourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   const float *in (data ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::fftNd (in, out, rank, dv);
 
@@ -172,13 +172,13 @@
 FloatComplexNDArray
 FloatNDArray::ifourierNd () const
 {
-  dim_vector dv = dims ();
+  const dim_vector& dv = dims ();
   int rank = dv.ndims ();
 
   FloatComplexNDArray tmp (*this);
-  FloatComplex *in (tmp.fortran_vec ());
+  FloatComplex *in (tmp.rwdata ());
   FloatComplexNDArray retval (dv);
-  FloatComplex *out (retval.fortran_vec ());
+  FloatComplex *out (retval.rwdata ());
 
   octave::fftw::ifftNd (in, out, rank, dv);
 
--- a/liboctave/array/fNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 #include "mx-defs.h"
 #include "mx-op-decl.h"
 
-class
-OCTAVE_API
-FloatNDArray : public MArray<float>
+class OCTAVE_API FloatNDArray : public MArray<float>
 {
 public:
 
--- a/liboctave/array/fRowVector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fRowVector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -190,7 +190,7 @@
       F77_INT ld = a_nr;
 
       retval.resize (a_nc);
-      float *y = retval.fortran_vec ();
+      float *y = retval.rwdata ();
 
       F77_XFCN (sgemv, SGEMV, (F77_CONST_CHAR_ARG2 ("T", 1),
                                a_nr, a_nc, 1.0, a.data (),
--- a/liboctave/array/fRowVector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/fRowVector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "MArray.h"
 #include "mx-defs.h"
 
-class
-OCTAVE_API
-FloatRowVector : public MArray<float>
+class OCTAVE_API FloatRowVector : public MArray<float>
 {
 public:
 
--- a/liboctave/array/idx-vector.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/idx-vector.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -536,7 +536,7 @@
     {
       // Use standard sort via octave_sort.
       idx.clear (m_orig_dims);
-      octave_idx_type *idx_data = idx.fortran_vec ();
+      octave_idx_type *idx_data = idx.rwdata ();
       for (octave_idx_type i = 0; i < m_len; i++)
         idx_data[i] = i;
 
@@ -557,7 +557,7 @@
         cnt[m_data[i]]++;
 
       idx.clear (m_orig_dims);
-      octave_idx_type *idx_data = idx.fortran_vec ();
+      octave_idx_type *idx_data = idx.rwdata ();
 
       octave_idx_type *new_data = new octave_idx_type [m_len];
       new_rep->m_data = new_data;
@@ -617,12 +617,12 @@
 
       if (m_data)
         {
-          std::memcpy (retval.fortran_vec (), m_data, m_len* sizeof (octave_idx_type));
+          std::memcpy (retval.rwdata (), m_data, m_len* sizeof (octave_idx_type));
           // Delete the old copy and share the m_data instead to save memory.
           delete [] m_data;
         }
 
-      m_data = retval.fortran_vec ();
+      m_data = retval.rwdata ();
       m_aowner = new Array<octave_idx_type> (retval);
 
       return retval;
@@ -761,7 +761,7 @@
   : m_rep (nullptr)
 {
   // Convert only if it means saving at least half the memory.
-  static const int factor = (2 * sizeof (octave_idx_type));
+  static constexpr int factor = (2 * sizeof (octave_idx_type));
   octave_idx_type nnz = bnda.nnz ();
   if (nnz <= bnda.numel () / factor)
     m_rep = new idx_vector_rep (bnda, nnz);
@@ -1030,7 +1030,7 @@
 
   idx_vector_rep *r = dynamic_cast<idx_vector_rep *> (m_rep);
 
-  assert (r != nullptr);
+  liboctave_panic_unless (r != nullptr);
 
   return r->get_data ();
 }
@@ -1088,7 +1088,7 @@
       break;
 
     default:
-      assert (false);
+      liboctave_panic_impossible ();
       break;
     }
 }
@@ -1108,7 +1108,7 @@
       octave_idx_type m_ext = r->extent (0);
       Array<bool> mask (dim_vector (n, 1));
       const bool *m_data = r->get_data ();
-      bool *ndata = mask.fortran_vec ();
+      bool *ndata = mask.rwdata ();
       for (octave_idx_type i = 0; i < m_ext; i++)
         ndata[i] = ! m_data[i];
       std::fill_n (ndata + m_ext, n - m_ext, true);
@@ -1117,7 +1117,7 @@
   else
     {
       Array<bool> mask (dim_vector (n, 1), true);
-      fill (false, length (n), mask.fortran_vec ());
+      fill (false, length (n), mask.rwdata ());
       retval = idx_vector (mask);
     }
 
@@ -1156,7 +1156,7 @@
 idx_vector
 idx_vector::inverse_permutation (octave_idx_type n) const
 {
-  assert (n == length (n));
+  liboctave_panic_unless (n == length (n));
 
   idx_vector retval;
 
@@ -1252,7 +1252,7 @@
       break;
 
     default:
-      assert (false);
+      liboctave_panic_impossible ();
       break;
     }
 }
--- a/liboctave/array/idx-vector.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/idx-vector.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,6 @@
 
 #include "octave-config.h"
 
-#include <cassert>
 #include <cstring>
 
 #include <algorithm>
@@ -37,6 +36,7 @@
 
 #include "Array-fwd.h"
 #include "dim-vector.h"
+#include "lo-error.h"
 #include "oct-inttypes.h"
 #include "oct-refcount.h"
 #include "Sparse-fwd.h"
@@ -54,9 +54,7 @@
 // as templates implementing "early dispatch", i.e., hoisting the checks
 // for index type out of loops.
 
-class
-OCTAVE_API
-idx_vector
+class OCTAVE_API idx_vector
 {
 public:
 
@@ -640,7 +638,7 @@
         break;
 
       default:
-        assert (false);
+        liboctave_panic_impossible ();
         break;
       }
 
@@ -712,7 +710,7 @@
         break;
 
       default:
-        assert (false);
+        liboctave_panic_impossible ();
         break;
       }
 
@@ -784,7 +782,7 @@
         break;
 
       default:
-        assert (false);
+        liboctave_panic_impossible ();
         break;
       }
 
@@ -850,7 +848,7 @@
         break;
 
       default:
-        assert (false);
+        liboctave_panic_impossible ();
         break;
       }
 
@@ -936,7 +934,7 @@
         break;
 
       default:
-        assert (false);
+        liboctave_panic_impossible ();
         break;
       }
 
--- a/liboctave/array/intNDArray.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/array/intNDArray.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,8 +34,7 @@
 #include "boolNDArray.h"
 
 template <typename T>
-class
-intNDArray : public MArray<T>
+class intNDArray : public MArray<T>
 {
 public:
 
--- a/liboctave/external/Faddeeva/Faddeeva.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/external/Faddeeva/Faddeeva.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -184,10 +184,7 @@
 #  define FADDEEVA_RE(name) Faddeeva::name
 
 // isnan/isinf were introduced in C++11
-#  if defined (lo_ieee_isnan) && defined (lo_ieee_isinf)
-#    define isnan lo_ieee_isnan
-#    define isinf lo_ieee_isinf
-#  elif (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF))
+#  if (__cplusplus < 201103L) && (!defined(HAVE_ISNAN) || !defined(HAVE_ISINF))
 static inline bool my_isnan(double x) { return x != x; }
 #    define isnan my_isnan
 static inline bool my_isinf(double x) { return 1/x == 0.; }
@@ -214,7 +211,7 @@
 // gnulib::floor and the system ::floor (and only on ancient OSF systems)
 // has to do with floor(-0), which doesn't occur in the usage below, but
 // the Octave developers prefer that we silence the warning.
-#  ifdef GNULIB_NAMESPACE
+#  if defined (GNULIB_NAMESPACE)
 #    define floor GNULIB_NAMESPACE::floor
 #  endif
 
--- a/liboctave/numeric/CollocWt.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/CollocWt.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
 #include <cmath>
 
 #include <limits>
@@ -152,12 +151,12 @@
        double alpha, double beta, double *dif1, double *dif2,
        double *dif3, double *root)
 {
-  assert (n0 == 0 || n0 == 1);
-  assert (n1 == 0 || n1 == 1);
+  liboctave_panic_unless (n0 == 0 || n0 == 1);
+  liboctave_panic_unless (n1 == 0 || n1 == 1);
 
   octave_idx_type nt = n + n0 + n1;
 
-  assert (nt >= 1);
+  liboctave_panic_unless (nt >= 1);
 
   // -- first evaluation of coefficients in recursion formulas.
   // -- recursion coefficients are stored in dif1 and dif2.
@@ -314,17 +313,17 @@
        octave_idx_type i, octave_idx_type id, double *dif1,
        double *dif2, double *dif3, double *root, double *vect)
 {
-  assert (n0 == 0 || n0 == 1);
-  assert (n1 == 0 || n1 == 1);
+  liboctave_panic_unless (n0 == 0 || n0 == 1);
+  liboctave_panic_unless (n1 == 0 || n1 == 1);
 
   octave_idx_type nt = n + n0 + n1;
 
-  assert (nt >= 1);
+  liboctave_panic_unless (nt >= 1);
 
-  assert (id == 1 || id == 2 || id == 3);
+  liboctave_panic_unless (id == 1 || id == 2 || id == 3);
 
   if (id != 3)
-    assert (i >= 0 && i < nt);
+    liboctave_panic_unless (i >= 0 && i < nt);
 
   // Evaluate discretization matrices and Gaussian quadrature weights.
   // Quadrature weights are normalized to sum to one.
@@ -426,23 +425,23 @@
     return;
 
   Array<double> dif1 (dim_vector (nt, 1));
-  double *pdif1 = dif1.fortran_vec ();
+  double *pdif1 = dif1.rwdata ();
 
   Array<double> dif2 (dim_vector (nt, 1));
-  double *pdif2 = dif2.fortran_vec ();
+  double *pdif2 = dif2.rwdata ();
 
   Array<double> dif3 (dim_vector (nt, 1));
-  double *pdif3 = dif3.fortran_vec ();
+  double *pdif3 = dif3.rwdata ();
 
   Array<double> vect (dim_vector (nt, 1));
-  double *pvect = vect.fortran_vec ();
+  double *pvect = vect.rwdata ();
 
   m_r.resize (nt, 1);
   m_q.resize (nt, 1);
   m_A.resize (nt, nt);
   m_B.resize (nt, nt);
 
-  double *pr = m_r.fortran_vec ();
+  double *pr = m_r.rwdata ();
 
   // Compute roots.
 
@@ -479,7 +478,7 @@
   // Gaussian quadrature weights.
 
   id = 3;
-  double *pq = m_q.fortran_vec ();
+  double *pq = m_q.rwdata ();
   dfopr (m_n, m_inc_left, m_inc_right, id, id, pdif1, pdif2, pdif3, pr, pq);
 
   m_initialized = 1;
--- a/liboctave/numeric/DAE.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DAE.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "DAEFunc.h"
 #include "base-dae.h"
 
-class
-OCTAVE_API
-DAE : public base_diff_alg_eqn, public DAEFunc
+class OCTAVE_API DAE : public base_diff_alg_eqn, public DAEFunc
 {
 public:
 
--- a/liboctave/numeric/DAEFunc.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DAEFunc.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,8 +30,7 @@
 
 #include "mx-fwd.h"
 
-class
-DAEFunc
+class DAEFunc
 {
 public:
 
--- a/liboctave/numeric/DAERT.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DAERT.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 #include "DAERTFunc.h"
 #include "base-dae.h"
 
-class
-DAERT : public base_diff_alg_eqn, public DAERTFunc
+class DAERT : public base_diff_alg_eqn, public DAERTFunc
 {
 public:
 
--- a/liboctave/numeric/DAERTFunc.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DAERTFunc.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,8 +30,7 @@
 
 #include "DAEFunc.h"
 
-class
-DAERTFunc : public DAEFunc
+class DAERTFunc : public DAEFunc
 {
 public:
 
--- a/liboctave/numeric/DASPK.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASPK.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -455,16 +455,16 @@
       m_restart = false;
     }
 
-  double *px = m_x.fortran_vec ();
-  double *pxdot = m_xdot.fortran_vec ();
+  double *px = m_x.rwdata ();
+  double *pxdot = m_xdot.rwdata ();
 
-  F77_INT *pinfo = m_info.fortran_vec ();
+  F77_INT *pinfo = m_info.rwdata ();
 
-  double *prel_tol = m_rel_tol.fortran_vec ();
-  double *pabs_tol = m_abs_tol.fortran_vec ();
+  double *prel_tol = m_rel_tol.rwdata ();
+  double *pabs_tol = m_abs_tol.rwdata ();
 
-  double *prwork = m_rwork.fortran_vec ();
-  F77_INT *piwork = m_iwork.fortran_vec ();
+  double *prwork = m_rwork.rwdata ();
+  F77_INT *piwork = m_iwork.rwdata ();
 
   double *dummy = nullptr;
   F77_INT *idummy = nullptr;
--- a/liboctave/numeric/DASPK.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASPK.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 
 #include "mx-fwd.h"
 
-class
-OCTAVE_API
-DASPK : public DAE, public DASPK_options
+class OCTAVE_API DASPK : public DAE, public DASPK_options
 {
 public:
 
--- a/liboctave/numeric/DASRT.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASRT.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -297,18 +297,18 @@
       DASRT_options::m_reset = false;
     }
 
-  double *px = m_x.fortran_vec ();
-  double *pxdot = m_xdot.fortran_vec ();
+  double *px = m_x.rwdata ();
+  double *pxdot = m_xdot.rwdata ();
 
-  F77_INT *pinfo = m_info.fortran_vec ();
+  F77_INT *pinfo = m_info.rwdata ();
 
-  double *prel_tol = m_rel_tol.fortran_vec ();
-  double *pabs_tol = m_abs_tol.fortran_vec ();
+  double *prel_tol = m_rel_tol.rwdata ();
+  double *pabs_tol = m_abs_tol.rwdata ();
 
-  double *prwork = m_rwork.fortran_vec ();
-  F77_INT *piwork = m_iwork.fortran_vec ();
+  double *prwork = m_rwork.rwdata ();
+  F77_INT *piwork = m_iwork.rwdata ();
 
-  F77_INT *pjroot = m_jroot.fortran_vec ();
+  F77_INT *pjroot = m_jroot.rwdata ();
 
   double *dummy = nullptr;
   F77_INT *idummy = nullptr;
--- a/liboctave/numeric/DASRT.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASRT.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,8 +34,7 @@
 #include "DASRT-opts.h"
 #include "dMatrix.h"
 
-class
-DASRT_result
+class DASRT_result
 {
 public:
 
@@ -72,9 +71,7 @@
   ColumnVector m_t;
 };
 
-class
-OCTAVE_API
-DASRT : public DAERT, public DASRT_options
+class OCTAVE_API DASRT : public DAERT, public DASRT_options
 {
 public:
 
--- a/liboctave/numeric/DASSL.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASSL.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -272,16 +272,16 @@
       DASSL_options::m_reset = false;
     }
 
-  double *px = m_x.fortran_vec ();
-  double *pxdot = m_xdot.fortran_vec ();
+  double *px = m_x.rwdata ();
+  double *pxdot = m_xdot.rwdata ();
 
-  F77_INT *pinfo = m_info.fortran_vec ();
+  F77_INT *pinfo = m_info.rwdata ();
 
-  double *prel_tol = m_rel_tol.fortran_vec ();
-  double *pabs_tol = m_abs_tol.fortran_vec ();
+  double *prel_tol = m_rel_tol.rwdata ();
+  double *pabs_tol = m_abs_tol.rwdata ();
 
-  double *prwork = m_rwork.fortran_vec ();
-  F77_INT *piwork = m_iwork.fortran_vec ();
+  double *prwork = m_rwork.rwdata ();
+  F77_INT *piwork = m_iwork.rwdata ();
 
   double *dummy = nullptr;
   F77_INT *idummy = nullptr;
--- a/liboctave/numeric/DASSL.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DASSL.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 #include "Array.h"
 #include "DASSL-opts.h"
 
-class
-OCTAVE_API
-DASSL : public DAE, public DASSL_options
+class OCTAVE_API DASSL : public DAE, public DASSL_options
 {
 public:
 
--- a/liboctave/numeric/DET.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/DET.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,8 +34,7 @@
 #include "oct-cmplx.h"
 
 template <typename T>
-class
-base_det
+class base_det
 {
 public:
 
--- a/liboctave/numeric/EIG.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/EIG.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -53,21 +53,21 @@
   F77_INT info = 0;
 
   Matrix atmp = a;
-  double *tmp_data = atmp.fortran_vec ();
+  double *tmp_data = atmp.rwdata ();
 
   Array<double> wr (dim_vector (n, 1));
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   Array<double> wi (dim_vector (n, 1));
-  double *pwi = wi.fortran_vec ();
+  double *pwi = wi.rwdata ();
 
   F77_INT tnvr = (calc_rev ? n : 0);
   Matrix vr (tnvr, tnvr);
-  double *pvr = vr.fortran_vec ();
+  double *pvr = vr.rwdata ();
 
   F77_INT tnvl = (calc_lev ? n : 0);
   Matrix vl (tnvl, tnvl);
-  double *pvl = vl.fortran_vec ();
+  double *pvl = vl.rwdata ();
 
   F77_INT lwork = -1;
   double dummy_work;
@@ -76,15 +76,15 @@
   F77_INT ihi;
 
   Array<double> scale (dim_vector (n, 1));
-  double *pscale = scale.fortran_vec ();
+  double *pscale = scale.rwdata ();
 
   double abnrm;
 
   Array<double> rconde (dim_vector (n, 1));
-  double *prconde = rconde.fortran_vec ();
+  double *prconde = rconde.rwdata ();
 
   Array<double> rcondv (dim_vector (n, 1));
-  double *prcondv = rcondv.fortran_vec ();
+  double *prcondv = rcondv.rwdata ();
 
   F77_INT dummy_iwork;
 
@@ -106,7 +106,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   F77_XFCN (dgeevx, DGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
@@ -186,10 +186,10 @@
   F77_INT info = 0;
 
   Matrix atmp = a;
-  double *tmp_data = atmp.fortran_vec ();
+  double *tmp_data = atmp.rwdata ();
 
   ColumnVector wr (n);
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   double dummy_work;
@@ -205,7 +205,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   F77_XFCN (dsyev, DSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -245,39 +245,39 @@
   F77_INT info = 0;
 
   ComplexMatrix atmp = a;
-  Complex *tmp_data = atmp.fortran_vec ();
+  Complex *tmp_data = atmp.rwdata ();
 
   ComplexColumnVector wr (n);
-  Complex *pw = wr.fortran_vec ();
+  Complex *pw = wr.rwdata ();
 
   F77_INT nvr = (calc_rev ? n : 0);
   ComplexMatrix vrtmp (nvr, nvr);
-  Complex *pvr = vrtmp.fortran_vec ();
+  Complex *pvr = vrtmp.rwdata ();
 
   F77_INT nvl = (calc_lev ? n : 0);
   ComplexMatrix vltmp (nvl, nvl);
-  Complex *pvl = vltmp.fortran_vec ();
+  Complex *pvl = vltmp.rwdata ();
 
   F77_INT lwork = -1;
   Complex dummy_work;
 
   F77_INT lrwork = 2*n;
   Array<double> rwork (dim_vector (lrwork, 1));
-  double *prwork = rwork.fortran_vec ();
+  double *prwork = rwork.rwdata ();
 
   F77_INT ilo;
   F77_INT ihi;
 
   Array<double> scale (dim_vector (n, 1));
-  double *pscale = scale.fortran_vec ();
+  double *pscale = scale.rwdata ();
 
   double abnrm;
 
   Array<double> rconde (dim_vector (n, 1));
-  double *prconde = rconde.fortran_vec ();
+  double *prconde = rconde.rwdata ();
 
   Array<double> rcondv (dim_vector (n, 1));
-  double *prcondv = rcondv.fortran_vec ();
+  double *prcondv = rcondv.rwdata ();
 
   F77_XFCN (zgeevx, ZGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
@@ -299,7 +299,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   F77_XFCN (zgeevx, ZGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
@@ -340,17 +340,17 @@
   F77_INT info = 0;
 
   ComplexMatrix atmp = a;
-  Complex *tmp_data = atmp.fortran_vec ();
+  Complex *tmp_data = atmp.rwdata ();
 
   ColumnVector wr (n);
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   Complex dummy_work;
 
   F77_INT lrwork = 3*n;
   Array<double> rwork (dim_vector (lrwork, 1));
-  double *prwork = rwork.fortran_vec ();
+  double *prwork = rwork.rwdata ();
 
   F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -365,7 +365,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   F77_XFCN (zheev, ZHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -410,7 +410,7 @@
   F77_INT info = 0;
 
   Matrix tmp = b;
-  double *tmp_data = tmp.fortran_vec ();
+  double *tmp_data = tmp.rwdata ();
 
   if (! force_qz)
     {
@@ -424,27 +424,27 @@
     }
 
   Matrix atmp = a;
-  double *atmp_data = atmp.fortran_vec ();
+  double *atmp_data = atmp.rwdata ();
 
   Matrix btmp = b;
-  double *btmp_data = btmp.fortran_vec ();
+  double *btmp_data = btmp.rwdata ();
 
   Array<double> ar (dim_vector (n, 1));
-  double *par = ar.fortran_vec ();
+  double *par = ar.rwdata ();
 
   Array<double> ai (dim_vector (n, 1));
-  double *pai = ai.fortran_vec ();
+  double *pai = ai.rwdata ();
 
   Array<double> beta (dim_vector (n, 1));
-  double *pbeta = beta.fortran_vec ();
+  double *pbeta = beta.rwdata ();
 
   F77_INT tnvr = (calc_rev ? n : 0);
   Matrix vr (tnvr, tnvr);
-  double *pvr = vr.fortran_vec ();
+  double *pvr = vr.rwdata ();
 
   F77_INT tnvl = (calc_lev ? n : 0);
   Matrix vl (tnvl, tnvl);
-  double *pvl = vl.fortran_vec ();
+  double *pvl = vl.rwdata ();
 
   F77_INT lwork = -1;
   double dummy_work;
@@ -463,7 +463,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   F77_XFCN (dggev, DGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -547,13 +547,13 @@
   F77_INT info = 0;
 
   Matrix atmp = a;
-  double *atmp_data = atmp.fortran_vec ();
+  double *atmp_data = atmp.rwdata ();
 
   Matrix btmp = b;
-  double *btmp_data = btmp.fortran_vec ();
+  double *btmp_data = btmp.rwdata ();
 
   ColumnVector wr (n);
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   double dummy_work;
@@ -571,7 +571,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   F77_XFCN (dsygv, DSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -617,7 +617,7 @@
   F77_INT info = 0;
 
   ComplexMatrix tmp = b;
-  Complex *tmp_data = tmp.fortran_vec ();
+  Complex *tmp_data = tmp.rwdata ();
 
   if (! force_qz)
     {
@@ -631,31 +631,31 @@
     }
 
   ComplexMatrix atmp = a;
-  Complex *atmp_data = atmp.fortran_vec ();
+  Complex *atmp_data = atmp.rwdata ();
 
   ComplexMatrix btmp = b;
-  Complex *btmp_data = btmp.fortran_vec ();
+  Complex *btmp_data = btmp.rwdata ();
 
   ComplexColumnVector alpha (n);
-  Complex *palpha = alpha.fortran_vec ();
+  Complex *palpha = alpha.rwdata ();
 
   ComplexColumnVector beta (n);
-  Complex *pbeta = beta.fortran_vec ();
+  Complex *pbeta = beta.rwdata ();
 
   F77_INT nvr = (calc_rev ? n : 0);
   ComplexMatrix vrtmp (nvr, nvr);
-  Complex *pvr = vrtmp.fortran_vec ();
+  Complex *pvr = vrtmp.rwdata ();
 
   F77_INT nvl = (calc_lev ? n : 0);
   ComplexMatrix vltmp (nvl, nvl);
-  Complex *pvl = vltmp.fortran_vec ();
+  Complex *pvl = vltmp.rwdata ();
 
   F77_INT lwork = -1;
   Complex dummy_work;
 
   F77_INT lrwork = 8*n;
   Array<double> rwork (dim_vector (lrwork, 1));
-  double *prwork = rwork.fortran_vec ();
+  double *prwork = rwork.rwdata ();
 
   F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -675,7 +675,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   F77_XFCN (zggev, ZGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -725,20 +725,20 @@
   F77_INT info = 0;
 
   ComplexMatrix atmp = a;
-  Complex *atmp_data = atmp.fortran_vec ();
+  Complex *atmp_data = atmp.rwdata ();
 
   ComplexMatrix btmp = b;
-  Complex *btmp_data = btmp.fortran_vec ();
+  Complex *btmp_data = btmp.rwdata ();
 
   ColumnVector wr (n);
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   Complex dummy_work;
 
   F77_INT lrwork = 3*n;
   Array<double> rwork (dim_vector (lrwork, 1));
-  double *prwork = rwork.fortran_vec ();
+  double *prwork = rwork.rwdata ();
 
   F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -754,7 +754,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   F77_XFCN (zhegv, ZHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
--- a/liboctave/numeric/EIG.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/EIG.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 #include "CColVector.h"
 #include "CMatrix.h"
 
-class
-OCTAVE_API
-EIG
+class OCTAVE_API EIG
 {
   friend class Matrix;
   friend class ComplexMatrix;
--- a/liboctave/numeric/LSODE.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/LSODE.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -301,12 +301,12 @@
       LSODE_options::m_reset = false;
     }
 
-  double *px = m_x.fortran_vec ();
+  double *px = m_x.rwdata ();
 
-  double *pabs_tol = m_abs_tol.fortran_vec ();
+  double *pabs_tol = m_abs_tol.rwdata ();
 
-  F77_INT *piwork = m_iwork.fortran_vec ();
-  double *prwork = m_rwork.fortran_vec ();
+  F77_INT *piwork = m_iwork.rwdata ();
+  double *prwork = m_rwork.rwdata ();
 
   F77_INT tmp_istate = octave::to_f77_int (m_istate);
 
--- a/liboctave/numeric/LSODE.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/LSODE.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "Array.h"
 #include "LSODE-opts.h"
 
-class
-OCTAVE_API
-LSODE : public ODE, public LSODE_options
+class OCTAVE_API LSODE : public ODE, public LSODE_options
 {
 public:
 
--- a/liboctave/numeric/ODE.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/ODE.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 #include "base-de.h"
 #include "dMatrix.h"
 
-class
-ODE : public base_diff_eqn, public ODEFunc
+class ODE : public base_diff_eqn, public ODEFunc
 {
 public:
 
--- a/liboctave/numeric/ODEFunc.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/ODEFunc.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,8 +30,7 @@
 
 #include "mx-fwd.h"
 
-class
-ODEFunc
+class ODEFunc
 {
 public:
 
--- a/liboctave/numeric/ODES.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/ODES.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,8 +31,7 @@
 #include "ODESFunc.h"
 #include "base-de.h"
 
-class
-ODES : public base_diff_eqn, public ODESFunc
+class ODES : public base_diff_eqn, public ODESFunc
 {
 public:
 
--- a/liboctave/numeric/ODESFunc.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/ODESFunc.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 
 #include "dMatrix.h"
 
-class
-ODESFunc
+class ODESFunc
 {
 public:
 
--- a/liboctave/numeric/Quad.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/Quad.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include "Array.h"
 #include "Quad.h"
 #include "f77-fcn.h"
@@ -97,16 +95,16 @@
                        double& abserr)
 {
   F77_INT npts = octave::to_f77_int (m_singularities.numel () + 2);
-  double *points = m_singularities.fortran_vec ();
+  double *points = m_singularities.rwdata ();
   double result = 0.0;
 
   F77_INT leniw = 183*npts - 122;
   Array<F77_INT> iwork (dim_vector (leniw, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_INT lenw = 2*leniw - npts;
   Array<double> work (dim_vector (lenw, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   user_fcn = m_f;
   F77_INT last;
@@ -147,11 +145,11 @@
 
   F77_INT leniw = 128;
   Array<F77_INT> iwork (dim_vector (leniw, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_INT lenw = 8*leniw;
   Array<double> work (dim_vector (lenw, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   user_fcn = m_f;
   F77_INT last;
@@ -172,7 +170,7 @@
       break;
 
     default:
-      assert (0);
+      liboctave_panic_impossible ();
       break;
     }
 
@@ -214,16 +212,16 @@
                             float& abserr)
 {
   F77_INT npts = octave::to_f77_int (m_singularities.numel () + 2);
-  float *points = m_singularities.fortran_vec ();
+  float *points = m_singularities.rwdata ();
   float result = 0.0;
 
   F77_INT leniw = 183*npts - 122;
   Array<F77_INT> iwork (dim_vector (leniw, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_INT lenw = 2*leniw - npts;
   Array<float> work (dim_vector (lenw, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   float_user_fcn = m_ff;
   F77_INT last;
@@ -264,11 +262,11 @@
 
   F77_INT leniw = 128;
   Array<F77_INT> iwork (dim_vector (leniw, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_INT lenw = 8*leniw;
   Array<float> work (dim_vector (lenw, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   float_user_fcn = m_ff;
   F77_INT last;
@@ -289,7 +287,7 @@
       break;
 
     default:
-      assert (0);
+      liboctave_panic_impossible ();
       break;
     }
 
--- a/liboctave/numeric/Quad.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/Quad.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 
 #include "Quad-opts.h"
 
-class
-OCTAVE_API
-Quad : public Quad_options
+class OCTAVE_API Quad : public Quad_options
 {
 public:
 
@@ -118,9 +116,7 @@
   float_integrand_fcn m_ff;
 };
 
-class
-OCTAVE_API
-DefQuad : public Quad
+class OCTAVE_API DefQuad : public Quad
 {
 public:
 
@@ -159,9 +155,7 @@
   ColumnVector m_singularities;
 };
 
-class
-OCTAVE_API
-IndefQuad : public Quad
+class OCTAVE_API IndefQuad : public Quad
 {
 public:
 
@@ -189,9 +183,7 @@
   IntegralType m_type;
 };
 
-class
-OCTAVE_API
-FloatDefQuad : public Quad
+class OCTAVE_API FloatDefQuad : public Quad
 {
 public:
 
@@ -230,9 +222,7 @@
   FloatColumnVector m_singularities;
 };
 
-class
-OCTAVE_API
-FloatIndefQuad : public Quad
+class OCTAVE_API FloatIndefQuad : public Quad
 {
 public:
 
--- a/liboctave/numeric/aepbalance.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/aepbalance.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -64,8 +64,8 @@
   F77_INT info, t_ilo, t_ihi;
 
   F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,
-                             m_balanced_mat.fortran_vec (), n,
-                             t_ilo, t_ihi, m_scale.fortran_vec (), info
+                             m_balanced_mat.rwdata (), n,
+                             t_ilo, t_ihi, m_scale.rwdata (), info
                              F77_CHAR_ARG_LEN (1)));
 
   m_ilo = t_ilo;
@@ -91,7 +91,7 @@
   F77_XFCN (dgebak, DGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),
                              F77_CONST_CHAR_ARG2 (&side, 1),
                              n, t_ilo, t_ihi, m_scale.data (), n,
-                             balancing_mat.fortran_vec (), n, info
+                             balancing_mat.rwdata (), n, info
                              F77_CHAR_ARG_LEN (1)
                              F77_CHAR_ARG_LEN (1)));
 
@@ -116,8 +116,8 @@
   F77_INT info, t_ilo, t_ihi;
 
   F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,
-                             m_balanced_mat.fortran_vec (), n, t_ilo,
-                             t_ihi, m_scale.fortran_vec (), info
+                             m_balanced_mat.rwdata (), n, t_ilo,
+                             t_ihi, m_scale.rwdata (), info
                              F77_CHAR_ARG_LEN (1)));
 
   m_ilo = t_ilo;
@@ -143,7 +143,7 @@
   F77_XFCN (sgebak, SGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),
                              F77_CONST_CHAR_ARG2 (&side, 1),
                              n, t_ilo, t_ihi, m_scale.data (), n,
-                             balancing_mat.fortran_vec (), n, info
+                             balancing_mat.rwdata (), n, info
                              F77_CHAR_ARG_LEN (1)
                              F77_CHAR_ARG_LEN (1)));
 
@@ -169,8 +169,8 @@
 
   F77_XFCN (zgebal, ZGEBAL,
             (F77_CONST_CHAR_ARG2 (&m_job, 1), n,
-             F77_DBLE_CMPLX_ARG (m_balanced_mat.fortran_vec ()),
-             n, t_ilo, t_ihi, m_scale.fortran_vec (), info
+             F77_DBLE_CMPLX_ARG (m_balanced_mat.rwdata ()),
+             n, t_ilo, t_ihi, m_scale.rwdata (), info
              F77_CHAR_ARG_LEN (1)));
 
   m_ilo = t_ilo;
@@ -197,7 +197,7 @@
             (F77_CONST_CHAR_ARG2 (&m_job, 1),
              F77_CONST_CHAR_ARG2 (&side, 1),
              n, t_ilo, t_ihi, m_scale.data (), n,
-             F77_DBLE_CMPLX_ARG (balancing_mat.fortran_vec ()),
+             F77_DBLE_CMPLX_ARG (balancing_mat.rwdata ()),
              n, info
              F77_CHAR_ARG_LEN (1)
              F77_CHAR_ARG_LEN (1)));
@@ -223,8 +223,8 @@
   F77_INT info, t_ilo, t_ihi;
 
   F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&m_job, 1), n,
-                             F77_CMPLX_ARG (m_balanced_mat.fortran_vec ()),
-                             n, t_ilo, t_ihi, m_scale.fortran_vec (), info
+                             F77_CMPLX_ARG (m_balanced_mat.rwdata ()),
+                             n, t_ilo, t_ihi, m_scale.rwdata (), info
                              F77_CHAR_ARG_LEN (1)));
 
   m_ilo = t_ilo;
@@ -250,7 +250,7 @@
   F77_XFCN (cgebak, CGEBAK, (F77_CONST_CHAR_ARG2 (&m_job, 1),
                              F77_CONST_CHAR_ARG2 (&side, 1),
                              n, t_ilo, t_ihi, m_scale.data (), n,
-                             F77_CMPLX_ARG (balancing_mat.fortran_vec ()),
+                             F77_CMPLX_ARG (balancing_mat.rwdata ()),
                              n, info
                              F77_CHAR_ARG_LEN (1)
                              F77_CHAR_ARG_LEN (1)));
--- a/liboctave/numeric/aepbalance.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/aepbalance.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename MT>
-class
-aepbalance
+class aepbalance
 {
 public:
 
--- a/liboctave/numeric/base-dae.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/base-dae.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,8 +30,7 @@
 
 #include "base-de.h"
 
-class
-base_diff_alg_eqn : public base_diff_eqn
+class base_diff_alg_eqn : public base_diff_eqn
 {
 public:
 
--- a/liboctave/numeric/base-de.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/base-de.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 
 #include "dColVector.h"
 
-class
-base_diff_eqn
+class base_diff_eqn
 {
 public:
 
--- a/liboctave/numeric/bsxfun-defs.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/bsxfun-defs.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -44,8 +44,8 @@
               void (*op_vs) (std::size_t, R *, const X *, Y))
 {
   int nd = std::max (x.ndims (), y.ndims ());
-  dim_vector dvx = x.dims ().redim (nd);
-  dim_vector dvy = y.dims ().redim (nd);
+  const dim_vector& dvx = x.dims ().redim (nd);
+  const dim_vector& dvy = y.dims ().redim (nd);
 
   // Construct the result dimensions.
   dim_vector dvr;
@@ -68,7 +68,7 @@
 
   const X *xvec = x.data ();
   const Y *yvec = y.data ();
-  R *rvec = retval.fortran_vec ();
+  R *rvec = retval.rwdata ();
 
   // Fold the common leading dimensions.
   octave_idx_type start, ldr = 1;
@@ -143,13 +143,13 @@
                       void (*op_vv) (std::size_t, R *, const X *),
                       void (*op_vs) (std::size_t, R *, X))
 {
-  dim_vector dvr = r.dims ();
+  const dim_vector& dvr = r.dims ();
   dim_vector dvx = x.dims ();
   octave_idx_type nd = r.ndims ();
   dvx = dvx.redim (nd);
 
   const X *xvec = x.data ();
-  R *rvec = r.fortran_vec ();
+  R *rvec = r.rwdata ();
 
   // Fold the common leading dimensions.
   octave_idx_type start, ldr = 1;
--- a/liboctave/numeric/chol.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/chol.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -64,7 +64,7 @@
   F77_INT info;
 
   Matrix tmp = r;
-  double *v = tmp.fortran_vec ();
+  double *v = tmp.rwdata ();
 
   if (is_upper)
     F77_XFCN (dpotri, DPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
@@ -112,7 +112,7 @@
   F77_INT info;
 
   FloatMatrix tmp = r;
-  float *v = tmp.fortran_vec ();
+  float *v = tmp.rwdata ();
 
   if (is_upper)
     F77_XFCN (spotri, SPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
@@ -163,11 +163,11 @@
 
   if (is_upper)
     F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                               F77_DBLE_CMPLX_ARG (tmp.rwdata ()), n, info
                                F77_CHAR_ARG_LEN (1)));
   else
     F77_XFCN (zpotri, ZPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               F77_DBLE_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                               F77_DBLE_CMPLX_ARG (tmp.rwdata ()), n, info
                                F77_CHAR_ARG_LEN (1)));
 
   // If someone thinks of a more graceful way of doing this (or
@@ -208,11 +208,11 @@
 
   if (is_upper)
     F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("U", 1), n,
-                               F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                               F77_CMPLX_ARG (tmp.rwdata ()), n, info
                                F77_CHAR_ARG_LEN (1)));
   else
     F77_XFCN (cpotri, CPOTRI, (F77_CONST_CHAR_ARG2 ("L", 1), n,
-                               F77_CMPLX_ARG (tmp.fortran_vec ()), n, info
+                               F77_CMPLX_ARG (tmp.rwdata ()), n, info
                                F77_CHAR_ARG_LEN (1)));
 
   // If someone thinks of a more graceful way of doing this (or
@@ -437,7 +437,7 @@
         for (octave_idx_type i = j; i < n; i++)
           m_chol_mat.xelem (i, j) = a(i, j);
       }
-  double *h = m_chol_mat.fortran_vec ();
+  double *h = m_chol_mat.rwdata ();
 
   // Calculate the norm of the matrix, for later use.
   double anorm = 0;
@@ -460,7 +460,7 @@
 
       // Now calculate the condition number for non-singular matrix.
       Array<double> z (dim_vector (3*n, 1));
-      double *pz = z.fortran_vec ();
+      double *pz = z.rwdata ();
       OCTAVE_LOCAL_BUFFER (F77_INT, iz, n);
       if (m_is_upper)
         F77_XFCN (dpocon, DPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h,
@@ -493,8 +493,8 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, n);
 
-  F77_XFCN (dch1up, DCH1UP, (n, m_chol_mat.fortran_vec (), n,
-                             utmp.fortran_vec (), w));
+  F77_XFCN (dch1up, DCH1UP, (n, m_chol_mat.rwdata (), n,
+                             utmp.rwdata (), w));
 }
 
 template <>
@@ -512,8 +512,8 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, n);
 
-  F77_XFCN (dch1dn, DCH1DN, (n, m_chol_mat.fortran_vec (), n,
-                             utmp.fortran_vec (), w, info));
+  F77_XFCN (dch1dn, DCH1DN, (n, m_chol_mat.rwdata (), n,
+                             utmp.rwdata (), w, info));
 
   return info;
 }
@@ -539,8 +539,8 @@
   m_chol_mat.resize (n+1, n+1);
   F77_INT ldcm = to_f77_int (m_chol_mat.rows ());
 
-  F77_XFCN (dchinx, DCHINX, (n, m_chol_mat.fortran_vec (), ldcm,
-                             j + 1, utmp.fortran_vec (), w, info));
+  F77_XFCN (dchinx, DCHINX, (n, m_chol_mat.rwdata (), ldcm,
+                             j + 1, utmp.rwdata (), w, info));
 
   return info;
 }
@@ -557,7 +557,7 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, n);
 
-  F77_XFCN (dchdex, DCHDEX, (n, m_chol_mat.fortran_vec (), n, j + 1, w));
+  F77_XFCN (dchdex, DCHDEX, (n, m_chol_mat.rwdata (), n, j + 1, w));
 
   m_chol_mat.resize (n-1, n-1);
 }
@@ -575,7 +575,7 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, 2*n);
 
-  F77_XFCN (dchshx, DCHSHX, (n, m_chol_mat.fortran_vec (), n,
+  F77_XFCN (dchshx, DCHSHX, (n, m_chol_mat.rwdata (), n,
                              i + 1, j + 1, w));
 }
 
@@ -613,7 +613,7 @@
         for (octave_idx_type i = j; i < n; i++)
           m_chol_mat.xelem (i, j) = a(i, j);
       }
-  float *h = m_chol_mat.fortran_vec ();
+  float *h = m_chol_mat.rwdata ();
 
   // Calculate the norm of the matrix, for later use.
   float anorm = 0;
@@ -636,7 +636,7 @@
 
       // Now calculate the condition number for non-singular matrix.
       Array<float> z (dim_vector (3*n, 1));
-      float *pz = z.fortran_vec ();
+      float *pz = z.rwdata ();
       OCTAVE_LOCAL_BUFFER (F77_INT, iz, n);
       if (m_is_upper)
         F77_XFCN (spocon, SPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n, h,
@@ -669,8 +669,8 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, n);
 
-  F77_XFCN (sch1up, SCH1UP, (n, m_chol_mat.fortran_vec (), n,
-                             utmp.fortran_vec (), w));
+  F77_XFCN (sch1up, SCH1UP, (n, m_chol_mat.rwdata (), n,
+                             utmp.rwdata (), w));
 }
 
 template <>
@@ -688,8 +688,8 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, n);
 
-  F77_XFCN (sch1dn, SCH1DN, (n, m_chol_mat.fortran_vec (), n,
-                             utmp.fortran_vec (), w, info));
+  F77_XFCN (sch1dn, SCH1DN, (n, m_chol_mat.rwdata (), n,
+                             utmp.rwdata (), w, info));
 
   return info;
 }
@@ -716,8 +716,8 @@
   m_chol_mat.resize (n+1, n+1);
   F77_INT ldcm = to_f77_int (m_chol_mat.rows ());
 
-  F77_XFCN (schinx, SCHINX, (n, m_chol_mat.fortran_vec (), ldcm,
-                             j + 1, utmp.fortran_vec (), w, info));
+  F77_XFCN (schinx, SCHINX, (n, m_chol_mat.rwdata (), ldcm,
+                             j + 1, utmp.rwdata (), w, info));
 
   return info;
 }
@@ -734,7 +734,7 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, n);
 
-  F77_XFCN (schdex, SCHDEX, (n, m_chol_mat.fortran_vec (), n,
+  F77_XFCN (schdex, SCHDEX, (n, m_chol_mat.rwdata (), n,
                              j + 1, w));
 
   m_chol_mat.resize (n-1, n-1);
@@ -753,7 +753,7 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, 2*n);
 
-  F77_XFCN (schshx, SCHSHX, (n, m_chol_mat.fortran_vec (), n,
+  F77_XFCN (schshx, SCHSHX, (n, m_chol_mat.rwdata (), n,
                              i + 1, j + 1, w));
 }
 
@@ -791,7 +791,7 @@
         for (octave_idx_type i = j; i < n; i++)
           m_chol_mat.xelem (i, j) = a(i, j);
       }
-  Complex *h = m_chol_mat.fortran_vec ();
+  Complex *h = m_chol_mat.rwdata ();
 
   // Calculate the norm of the matrix, for later use.
   double anorm = 0;
@@ -816,9 +816,9 @@
 
       // Now calculate the condition number for non-singular matrix.
       Array<Complex> z (dim_vector (2*n, 1));
-      Complex *pz = z.fortran_vec ();
+      Complex *pz = z.rwdata ();
       Array<double> rz (dim_vector (n, 1));
-      double *prz = rz.fortran_vec ();
+      double *prz = rz.rwdata ();
       F77_XFCN (zpocon, ZPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n,
                                  F77_DBLE_CMPLX_ARG (h), n, anorm, m_rcond,
                                  F77_DBLE_CMPLX_ARG (pz), prz, zpocon_info
@@ -847,9 +847,9 @@
   OCTAVE_LOCAL_BUFFER (double, rw, n);
 
   F77_XFCN (zch1up, ZCH1UP, (n,
-                             F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
                              rw));
 }
 
@@ -869,9 +869,9 @@
   OCTAVE_LOCAL_BUFFER (double, rw, n);
 
   F77_XFCN (zch1dn, ZCH1DN, (n,
-                             F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
                              rw, info));
 
   return info;
@@ -900,9 +900,9 @@
   F77_INT ldcm = to_f77_int (m_chol_mat.rows ());
 
   F77_XFCN (zchinx, ZCHINX, (n,
-                             F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),
                              ldcm, j + 1,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
                              rw, info));
 
   return info;
@@ -921,7 +921,7 @@
   OCTAVE_LOCAL_BUFFER (double, rw, n);
 
   F77_XFCN (zchdex, ZCHDEX, (n,
-                             F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n, j + 1, rw));
 
   m_chol_mat.resize (n-1, n-1);
@@ -943,7 +943,7 @@
   OCTAVE_LOCAL_BUFFER (double, rw, n);
 
   F77_XFCN (zchshx, ZCHSHX, (n,
-                             F77_DBLE_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+                             F77_DBLE_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n, i + 1, j + 1,
                              F77_DBLE_CMPLX_ARG (w), rw));
 }
@@ -983,7 +983,7 @@
         for (octave_idx_type i = j; i < n; i++)
           m_chol_mat.xelem (i, j) = a(i, j);
       }
-  FloatComplex *h = m_chol_mat.fortran_vec ();
+  FloatComplex *h = m_chol_mat.rwdata ();
 
   // Calculate the norm of the matrix, for later use.
   float anorm = 0;
@@ -1008,9 +1008,9 @@
 
       // Now calculate the condition number for non-singular matrix.
       Array<FloatComplex> z (dim_vector (2*n, 1));
-      FloatComplex *pz = z.fortran_vec ();
+      FloatComplex *pz = z.rwdata ();
       Array<float> rz (dim_vector (n, 1));
-      float *prz = rz.fortran_vec ();
+      float *prz = rz.rwdata ();
       F77_XFCN (cpocon, CPOCON, (F77_CONST_CHAR_ARG2 ("U", 1), n,
                                  F77_CMPLX_ARG (h), n, anorm, m_rcond,
                                  F77_CMPLX_ARG (pz), prz, cpocon_info
@@ -1038,8 +1038,8 @@
 
   OCTAVE_LOCAL_BUFFER (float, rw, n);
 
-  F77_XFCN (cch1up, CCH1UP, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()),
-                             n, F77_CMPLX_ARG (utmp.fortran_vec ()), rw));
+  F77_XFCN (cch1up, CCH1UP, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),
+                             n, F77_CMPLX_ARG (utmp.rwdata ()), rw));
 }
 
 template <>
@@ -1057,8 +1057,8 @@
 
   OCTAVE_LOCAL_BUFFER (float, rw, n);
 
-  F77_XFCN (cch1dn, CCH1DN, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()),
-                             n, F77_CMPLX_ARG (utmp.fortran_vec ()),
+  F77_XFCN (cch1dn, CCH1DN, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),
+                             n, F77_CMPLX_ARG (utmp.rwdata ()),
                              rw, info));
 
   return info;
@@ -1086,9 +1086,9 @@
   m_chol_mat.resize (n+1, n+1);
   F77_INT ldcm = to_f77_int (m_chol_mat.rows ());
 
-  F77_XFCN (cchinx, CCHINX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+  F77_XFCN (cchinx, CCHINX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),
                              ldcm, j + 1,
-                             F77_CMPLX_ARG (utmp.fortran_vec ()),
+                             F77_CMPLX_ARG (utmp.rwdata ()),
                              rw, info));
 
   return info;
@@ -1106,7 +1106,7 @@
 
   OCTAVE_LOCAL_BUFFER (float, rw, n);
 
-  F77_XFCN (cchdex, CCHDEX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+  F77_XFCN (cchdex, CCHDEX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n, j + 1, rw));
 
   m_chol_mat.resize (n-1, n-1);
@@ -1127,7 +1127,7 @@
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, n);
   OCTAVE_LOCAL_BUFFER (float, rw, n);
 
-  F77_XFCN (cchshx, CCHSHX, (n, F77_CMPLX_ARG (m_chol_mat.fortran_vec ()),
+  F77_XFCN (cchshx, CCHSHX, (n, F77_CMPLX_ARG (m_chol_mat.rwdata ()),
                              n, i + 1, j + 1, F77_CMPLX_ARG (w), rw));
 }
 
--- a/liboctave/numeric/chol.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/chol.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,8 +33,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-chol
+class chol
 {
 public:
 
--- a/liboctave/numeric/eigs-base.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/eigs-base.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -509,7 +509,8 @@
     }
 
   double rcond = (minU / maxU);
-  volatile double rcond_plus_one = rcond + 1.0;
+  // Prevent use of extra precision.
+  double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
     warn_convergence ();
@@ -538,7 +539,7 @@
             {
               Matrix tmp = sigma * b.transpose () * b;
               const double *pB = permB.data ();
-              double *p = AminusSigmaB.fortran_vec ();
+              double *p = AminusSigmaB.rwdata ();
 
               if (permB.numel ())
                 {
@@ -557,7 +558,7 @@
         }
       else
         {
-          double *p = AminusSigmaB.fortran_vec ();
+          double *p = AminusSigmaB.rwdata ();
 
           for (octave_idx_type i = 0; i < n; i++)
             p[i*(n+1)] -= sigma;
@@ -591,7 +592,8 @@
     }
 
   double rcond = (minU / maxU);
-  volatile double rcond_plus_one = rcond + 1.0;
+  // Prevent use of extra precision.
+  double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
     warn_convergence ();
@@ -691,7 +693,8 @@
     }
 
   double rcond = (minU / maxU);
-  volatile double rcond_plus_one = rcond + 1.0;
+  // Prevent use of extra precision.
+  double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
     warn_convergence ();
@@ -720,7 +723,7 @@
             {
               ComplexMatrix tmp = sigma * b.hermitian () * b;
               const double *pB = permB.data ();
-              Complex *p = AminusSigmaB.fortran_vec ();
+              Complex *p = AminusSigmaB.rwdata ();
 
               if (permB.numel ())
                 {
@@ -739,7 +742,7 @@
         }
       else
         {
-          Complex *p = AminusSigmaB.fortran_vec ();
+          Complex *p = AminusSigmaB.rwdata ();
 
           for (octave_idx_type i = 0; i < n; i++)
             p[i*(n+1)] -= sigma;
@@ -773,7 +776,8 @@
     }
 
   double rcond = (minU / maxU);
-  volatile double rcond_plus_one = rcond + 1.0;
+  // Prevent use of extra precision.
+  double rcond_plus_one = rcond + 1.0;
 
   if (rcond_plus_one == 1.0 || octave::math::isnan (rcond))
     warn_convergence ();
@@ -892,7 +896,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -908,7 +912,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -917,7 +921,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * p);
   OCTAVE_LOCAL_BUFFER (double, workl, lwork);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -1000,13 +1004,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  double *z = eig_vec.fortran_vec ();
+  double *z = eig_vec.rwdata ();
 
   eig_val.resize (k);
-  double *d = eig_val.fortran_vec ();
+  double *d = eig_val.rwdata ();
 
   F77_FUNC (dseupd, DSEUPD)
   (rvec, F77_CONST_CHAR_ARG2 ("A", 1), sel, d, z, n, sigma,
@@ -1159,7 +1163,7 @@
     bmat = 'G';
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -1175,7 +1179,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -1193,7 +1197,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * p);
   OCTAVE_LOCAL_BUFFER (double, workl, lwork);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -1312,13 +1316,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  double *z = eig_vec.fortran_vec ();
+  double *z = eig_vec.rwdata ();
 
   eig_val.resize (k);
-  double *d = eig_val.fortran_vec ();
+  double *d = eig_val.rwdata ();
 
   F77_FUNC (dseupd, DSEUPD)
   (rvec, F77_CONST_CHAR_ARG2 ("A", 1), sel, d, z, n, sigma,
@@ -1512,7 +1516,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -1528,7 +1532,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -1537,7 +1541,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * p);
   OCTAVE_LOCAL_BUFFER (double, workl, lwork);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -1685,13 +1689,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  double *z = eig_vec.fortran_vec ();
+  double *z = eig_vec.rwdata ();
 
   eig_val.resize (k);
-  double *d = eig_val.fortran_vec ();
+  double *d = eig_val.rwdata ();
 
   F77_FUNC (dseupd, DSEUPD)
   (rvec, F77_CONST_CHAR_ARG2 ("A", 1), sel, d, z, n, sigma,
@@ -1869,7 +1873,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -1885,7 +1889,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -1894,7 +1898,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * (p + 1));
   OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -1981,7 +1985,7 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip
   // the assignment to elements of Z that represent imaginary parts.
@@ -1991,7 +1995,7 @@
   //   [vecs, vals, f] = eigs (A, 1)
 
   Matrix eig_vec2 (n, k + 1, 0.0);
-  double *z = eig_vec2.fortran_vec ();
+  double *z = eig_vec2.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (double, dr, k + 1);
   OCTAVE_LOCAL_BUFFER (double, di, k + 1);
@@ -2013,7 +2017,7 @@
     k = ip(4);
 
   eig_val.resize (k);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   if (info2 == 0)
     {
@@ -2196,7 +2200,7 @@
     bmat = 'G';
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -2212,7 +2216,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -2230,7 +2234,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * (p + 1));
   OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -2354,7 +2358,7 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip
   // the assignment to elements of Z that represent imaginary parts.
@@ -2364,7 +2368,7 @@
   //   [vecs, vals, f] = eigs (A, 1)
 
   Matrix eig_vec2 (n, k + 1, 0.0);
-  double *z = eig_vec2.fortran_vec ();
+  double *z = eig_vec2.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (double, dr, k + 1);
   OCTAVE_LOCAL_BUFFER (double, di, k + 1);
@@ -2386,7 +2390,7 @@
     k = ip(4);
 
   eig_val.resize (k);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   if (info2 == 0)
     {
@@ -2617,7 +2621,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -2633,7 +2637,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -2642,7 +2646,7 @@
   OCTAVE_LOCAL_BUFFER (double, v, n * (p + 1));
   OCTAVE_LOCAL_BUFFER (double, workl, lwork + 1);
   OCTAVE_LOCAL_BUFFER (double, workd, 3 * n + 1);
-  double *presid = resid.fortran_vec ();
+  double *presid = resid.rwdata ();
 
   do
     {
@@ -2794,7 +2798,7 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   // FIXME: initialize eig_vec2 to zero; apparently dneupd can skip
   // the assignment to elements of Z that represent imaginary parts.
@@ -2804,7 +2808,7 @@
   //   [vecs, vals, f] = eigs (A, 1)
 
   Matrix eig_vec2 (n, k + 1, 0.0);
-  double *z = eig_vec2.fortran_vec ();
+  double *z = eig_vec2.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (double, dr, k + 1);
   OCTAVE_LOCAL_BUFFER (double, di, k + 1);
@@ -2826,7 +2830,7 @@
     k = ip(4);
 
   eig_val.resize (k);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   if (info2 == 0)
     {
@@ -3038,7 +3042,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -3054,7 +3058,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -3064,7 +3068,7 @@
   OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);
   OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);
   OCTAVE_LOCAL_BUFFER (double, rwork, p);
-  Complex *presid = cresid.fortran_vec ();
+  Complex *presid = cresid.rwdata ();
 
   do
     {
@@ -3147,13 +3151,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  Complex *z = eig_vec.fortran_vec ();
+  Complex *z = eig_vec.rwdata ();
 
   eig_val.resize (k+1);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);
 
@@ -3317,7 +3321,7 @@
     bmat = 'G';
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -3333,7 +3337,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -3352,7 +3356,7 @@
   OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);
   OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);
   OCTAVE_LOCAL_BUFFER (double, rwork, p);
-  Complex *presid = cresid.fortran_vec ();
+  Complex *presid = cresid.rwdata ();
 
   do
     {
@@ -3473,13 +3477,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  Complex *z = eig_vec.fortran_vec ();
+  Complex *z = eig_vec.rwdata ();
 
   eig_val.resize (k+1);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);
 
@@ -3688,7 +3692,7 @@
     }
 
   Array<F77_INT> ip (dim_vector (11, 1));
-  F77_INT *iparam = ip.fortran_vec ();
+  F77_INT *iparam = ip.rwdata ();
 
   ip(0) = 1; //ishift
   ip(1) = 0;   // ip(1) not referenced
@@ -3704,7 +3708,7 @@
   // ip(7) to ip(10) return values
 
   Array<F77_INT> iptr (dim_vector (14, 1));
-  F77_INT *ipntr = iptr.fortran_vec ();
+  F77_INT *ipntr = iptr.rwdata ();
 
   F77_INT ido = 0;
   int iter = 0;
@@ -3714,7 +3718,7 @@
   OCTAVE_LOCAL_BUFFER (Complex, workl, lwork);
   OCTAVE_LOCAL_BUFFER (Complex, workd, 3 * n);
   OCTAVE_LOCAL_BUFFER (double, rwork, p);
-  Complex *presid = cresid.fortran_vec ();
+  Complex *presid = cresid.rwdata ();
 
   do
     {
@@ -3863,13 +3867,13 @@
   // is just workspace for ARPACK, so use int type to
   // avoid problems.
   Array<F77_INT> s (dim_vector (p, 1));
-  F77_INT *sel = s.fortran_vec ();
+  F77_INT *sel = s.rwdata ();
 
   eig_vec.resize (n, k);
-  Complex *z = eig_vec.fortran_vec ();
+  Complex *z = eig_vec.rwdata ();
 
   eig_val.resize (k+1);
-  Complex *d = eig_val.fortran_vec ();
+  Complex *d = eig_val.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (Complex, workev, 2 * p);
 
--- a/liboctave/numeric/fEIG.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/fEIG.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -54,21 +54,21 @@
   F77_INT info = 0;
 
   FloatMatrix atmp = a;
-  float *tmp_data = atmp.fortran_vec ();
+  float *tmp_data = atmp.rwdata ();
 
   Array<float> wr (dim_vector (n, 1));
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   Array<float> wi (dim_vector (n, 1));
-  float *pwi = wi.fortran_vec ();
+  float *pwi = wi.rwdata ();
 
-  volatile F77_INT nvr = (calc_rev ? n : 0);
+  F77_INT nvr = (calc_rev ? n : 0);
   FloatMatrix vr (nvr, nvr);
-  float *pvr = vr.fortran_vec ();
+  float *pvr = vr.rwdata ();
 
-  volatile F77_INT nvl = (calc_lev ? n : 0);
+  F77_INT nvl = (calc_lev ? n : 0);
   FloatMatrix vl (nvl, nvl);
-  float *pvl = vl.fortran_vec ();
+  float *pvl = vl.rwdata ();
 
   F77_INT lwork = -1;
   float dummy_work;
@@ -77,15 +77,15 @@
   F77_INT ihi;
 
   Array<float> scale (dim_vector (n, 1));
-  float *pscale = scale.fortran_vec ();
+  float *pscale = scale.rwdata ();
 
   float abnrm;
 
   Array<float> rconde (dim_vector (n, 1));
-  float *prconde = rconde.fortran_vec ();
+  float *prconde = rconde.rwdata ();
 
   Array<float> rcondv (dim_vector (n, 1));
-  float *prcondv = rcondv.fortran_vec ();
+  float *prcondv = rcondv.rwdata ();
 
   F77_INT dummy_iwork;
 
@@ -107,7 +107,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   F77_XFCN (sgeevx, SGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 ("N", 1),
@@ -184,10 +184,10 @@
   F77_INT info = 0;
 
   FloatMatrix atmp = a;
-  float *tmp_data = atmp.fortran_vec ();
+  float *tmp_data = atmp.rwdata ();
 
   FloatColumnVector wr (n);
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   float dummy_work;
@@ -203,7 +203,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   F77_XFCN (ssyev, SSYEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -244,39 +244,39 @@
   F77_INT info = 0;
 
   FloatComplexMatrix atmp = a;
-  FloatComplex *tmp_data = atmp.fortran_vec ();
+  FloatComplex *tmp_data = atmp.rwdata ();
 
   FloatComplexColumnVector wr (n);
-  FloatComplex *pw = wr.fortran_vec ();
+  FloatComplex *pw = wr.rwdata ();
 
   F77_INT nvr = (calc_rev ? n : 0);
   FloatComplexMatrix vrtmp (nvr, nvr);
-  FloatComplex *pvr = vrtmp.fortran_vec ();
+  FloatComplex *pvr = vrtmp.rwdata ();
 
   F77_INT nvl = (calc_lev ? n : 0);
   FloatComplexMatrix vltmp (nvl, nvl);
-  FloatComplex *pvl = vltmp.fortran_vec ();
+  FloatComplex *pvl = vltmp.rwdata ();
 
   F77_INT lwork = -1;
   FloatComplex dummy_work;
 
   F77_INT lrwork = 2*n;
   Array<float> rwork (dim_vector (lrwork, 1));
-  float *prwork = rwork.fortran_vec ();
+  float *prwork = rwork.rwdata ();
 
   F77_INT ilo;
   F77_INT ihi;
 
   Array<float> scale (dim_vector (n, 1));
-  float *pscale = scale.fortran_vec ();
+  float *pscale = scale.rwdata ();
 
   float abnrm;
 
   Array<float> rconde (dim_vector (n, 1));
-  float *prconde = rconde.fortran_vec ();
+  float *prconde = rconde.rwdata ();
 
   Array<float> rcondv (dim_vector (n, 1));
-  float *prcondv = rcondv.fortran_vec ();
+  float *prcondv = rcondv.rwdata ();
 
   F77_XFCN (cgeevx, CGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
@@ -296,7 +296,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   F77_XFCN (cgeevx, CGEEVX, (F77_CONST_CHAR_ARG2 (balance ? "B" : "N", 1),
                              F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
@@ -337,17 +337,17 @@
   F77_INT info = 0;
 
   FloatComplexMatrix atmp = a;
-  FloatComplex *tmp_data = atmp.fortran_vec ();
+  FloatComplex *tmp_data = atmp.rwdata ();
 
   FloatColumnVector wr (n);
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   FloatComplex dummy_work;
 
   F77_INT lrwork = 3*n;
   Array<float> rwork (dim_vector (lrwork, 1));
-  float *prwork = rwork.fortran_vec ();
+  float *prwork = rwork.rwdata ();
 
   F77_XFCN (cheev, CHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -362,7 +362,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   F77_XFCN (cheev, CHEEV, (F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -407,7 +407,7 @@
   F77_INT info = 0;
 
   FloatMatrix tmp = b;
-  float *tmp_data = tmp.fortran_vec ();
+  float *tmp_data = tmp.rwdata ();
   if (! force_qz)
     {
       F77_XFCN (spotrf, SPOTRF, (F77_CONST_CHAR_ARG2 ("L", 1),
@@ -420,27 +420,27 @@
     }
 
   FloatMatrix atmp = a;
-  float *atmp_data = atmp.fortran_vec ();
+  float *atmp_data = atmp.rwdata ();
 
   FloatMatrix btmp = b;
-  float *btmp_data = btmp.fortran_vec ();
+  float *btmp_data = btmp.rwdata ();
 
   Array<float> ar (dim_vector (n, 1));
-  float *par = ar.fortran_vec ();
+  float *par = ar.rwdata ();
 
   Array<float> ai (dim_vector (n, 1));
-  float *pai = ai.fortran_vec ();
+  float *pai = ai.rwdata ();
 
   Array<float> beta (dim_vector (n, 1));
-  float *pbeta = beta.fortran_vec ();
+  float *pbeta = beta.rwdata ();
 
-  volatile F77_INT nvr = (calc_rev ? n : 0);
+  F77_INT nvr = (calc_rev ? n : 0);
   FloatMatrix vr (nvr, nvr);
-  float *pvr = vr.fortran_vec ();
+  float *pvr = vr.rwdata ();
 
-  volatile F77_INT nvl = (calc_lev ? n : 0);
+  F77_INT nvl = (calc_lev ? n : 0);
   FloatMatrix vl (nvl, nvl);
-  float *pvl = vl.fortran_vec ();
+  float *pvl = vl.rwdata ();
 
   F77_INT lwork = -1;
   float dummy_work;
@@ -459,7 +459,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   F77_XFCN (sggev, SGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -542,13 +542,13 @@
   F77_INT info = 0;
 
   FloatMatrix atmp = a;
-  float *atmp_data = atmp.fortran_vec ();
+  float *atmp_data = atmp.rwdata ();
 
   FloatMatrix btmp = b;
-  float *btmp_data = btmp.fortran_vec ();
+  float *btmp_data = btmp.rwdata ();
 
   FloatColumnVector wr (n);
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   float dummy_work;
@@ -566,7 +566,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work);
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   F77_XFCN (ssygv, SSYGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -612,7 +612,7 @@
   F77_INT info = 0;
 
   FloatComplexMatrix tmp = b;
-  FloatComplex *tmp_data = tmp.fortran_vec ();
+  FloatComplex *tmp_data = tmp.rwdata ();
 
   if (! force_qz)
     {
@@ -626,31 +626,31 @@
     }
 
   FloatComplexMatrix atmp = a;
-  FloatComplex *atmp_data = atmp.fortran_vec ();
+  FloatComplex *atmp_data = atmp.rwdata ();
 
   FloatComplexMatrix btmp = b;
-  FloatComplex *btmp_data = btmp.fortran_vec ();
+  FloatComplex *btmp_data = btmp.rwdata ();
 
   FloatComplexColumnVector alpha (n);
-  FloatComplex *palpha = alpha.fortran_vec ();
+  FloatComplex *palpha = alpha.rwdata ();
 
   FloatComplexColumnVector beta (n);
-  FloatComplex *pbeta = beta.fortran_vec ();
+  FloatComplex *pbeta = beta.rwdata ();
 
   F77_INT nvr = (calc_rev ? n : 0);
   FloatComplexMatrix vrtmp (nvr, nvr);
-  FloatComplex *pvr = vrtmp.fortran_vec ();
+  FloatComplex *pvr = vrtmp.rwdata ();
 
   F77_INT nvl = (calc_lev ? n : 0);
   FloatComplexMatrix vltmp (nvl, nvl);
-  FloatComplex *pvl = vltmp.fortran_vec ();
+  FloatComplex *pvl = vltmp.rwdata ();
 
   F77_INT lwork = -1;
   FloatComplex dummy_work;
 
   F77_INT lrwork = 8*n;
   Array<float> rwork (dim_vector (lrwork, 1));
-  float *prwork = rwork.fortran_vec ();
+  float *prwork = rwork.rwdata ();
 
   F77_XFCN (cggev, CGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -667,7 +667,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   F77_XFCN (cggev, CGGEV, (F77_CONST_CHAR_ARG2 (calc_lev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
@@ -716,20 +716,20 @@
   F77_INT info = 0;
 
   FloatComplexMatrix atmp = a;
-  FloatComplex *atmp_data = atmp.fortran_vec ();
+  FloatComplex *atmp_data = atmp.rwdata ();
 
   FloatComplexMatrix btmp = b;
-  FloatComplex *btmp_data = btmp.fortran_vec ();
+  FloatComplex *btmp_data = btmp.rwdata ();
 
   FloatColumnVector wr (n);
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   F77_INT lwork = -1;
   FloatComplex dummy_work;
 
   F77_INT lrwork = 3*n;
   Array<float> rwork (dim_vector (lrwork, 1));
-  float *prwork = rwork.fortran_vec ();
+  float *prwork = rwork.rwdata ();
 
   F77_XFCN (chegv, CHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
@@ -745,7 +745,7 @@
 
   lwork = static_cast<F77_INT> (dummy_work.real ());
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   F77_XFCN (chegv, CHEGV, (1, F77_CONST_CHAR_ARG2 (calc_rev ? "V" : "N", 1),
                            F77_CONST_CHAR_ARG2 ("U", 1),
--- a/liboctave/numeric/fEIG.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/fEIG.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 #include "fCColVector.h"
 #include "fCMatrix.h"
 
-class
-OCTAVE_API
-FloatEIG
+class OCTAVE_API FloatEIG
 {
   friend class FloatMatrix;
   friend class FloatComplexMatrix;
--- a/liboctave/numeric/gepbalance.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/gepbalance.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -65,9 +65,9 @@
   OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n);
 
   m_balanced_mat = a;
-  double *p_balanced_mat = m_balanced_mat.fortran_vec ();
+  double *p_balanced_mat = m_balanced_mat.rwdata ();
   m_balanced_mat2 = b;
-  double *p_balanced_mat2 = m_balanced_mat2.fortran_vec ();
+  double *p_balanced_mat2 = m_balanced_mat2.rwdata ();
 
   char job = balance_job[0];
 
@@ -85,8 +85,8 @@
       m_balancing_mat2.elem (i, i) = 1.0;
     }
 
-  double *p_balancing_mat = m_balancing_mat.fortran_vec ();
-  double *p_balancing_mat2 = m_balancing_mat2.fortran_vec ();
+  double *p_balancing_mat = m_balancing_mat.rwdata ();
+  double *p_balancing_mat2 = m_balancing_mat2.rwdata ();
 
   // first left
   F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -131,9 +131,9 @@
   OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n);
 
   m_balanced_mat = a;
-  float *p_balanced_mat = m_balanced_mat.fortran_vec ();
+  float *p_balanced_mat = m_balanced_mat.rwdata ();
   m_balanced_mat2 = b;
-  float *p_balanced_mat2 = m_balanced_mat2.fortran_vec ();
+  float *p_balanced_mat2 = m_balanced_mat2.rwdata ();
 
   char job = balance_job[0];
 
@@ -151,8 +151,8 @@
       m_balancing_mat2.elem (i, i) = 1.0;
     }
 
-  float *p_balancing_mat = m_balancing_mat.fortran_vec ();
-  float *p_balancing_mat2 = m_balancing_mat2.fortran_vec ();
+  float *p_balancing_mat = m_balancing_mat.rwdata ();
+  float *p_balancing_mat2 = m_balancing_mat2.rwdata ();
 
   // first left
   F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -198,9 +198,9 @@
   OCTAVE_LOCAL_BUFFER (double, pwork, 6 * n);
 
   m_balanced_mat = a;
-  Complex *p_balanced_mat = m_balanced_mat.fortran_vec ();
+  Complex *p_balanced_mat = m_balanced_mat.rwdata ();
   m_balanced_mat2 = b;
-  Complex *p_balanced_mat2 = m_balanced_mat2.fortran_vec ();
+  Complex *p_balanced_mat2 = m_balanced_mat2.rwdata ();
 
   char job = balance_job[0];
 
@@ -219,8 +219,8 @@
       m_balancing_mat2.elem (i, i) = 1.0;
     }
 
-  double *p_balancing_mat = m_balancing_mat.fortran_vec ();
-  double *p_balancing_mat2 = m_balancing_mat2.fortran_vec ();
+  double *p_balancing_mat = m_balancing_mat.rwdata ();
+  double *p_balancing_mat2 = m_balancing_mat2.rwdata ();
 
   // first left
   F77_XFCN (dggbak, DGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),
@@ -269,9 +269,9 @@
   OCTAVE_LOCAL_BUFFER (float, pwork, 6 * n);
 
   m_balanced_mat = a;
-  FloatComplex *p_balanced_mat = m_balanced_mat.fortran_vec ();
+  FloatComplex *p_balanced_mat = m_balanced_mat.rwdata ();
   m_balanced_mat2 = b;
-  FloatComplex *p_balanced_mat2 = m_balanced_mat2.fortran_vec ();
+  FloatComplex *p_balanced_mat2 = m_balanced_mat2.rwdata ();
 
   char job = balance_job[0];
 
@@ -290,8 +290,8 @@
       m_balancing_mat2.elem (i, i) = 1.0;
     }
 
-  float *p_balancing_mat = m_balancing_mat.fortran_vec ();
-  float *p_balancing_mat2 = m_balancing_mat2.fortran_vec ();
+  float *p_balancing_mat = m_balancing_mat.rwdata ();
+  float *p_balancing_mat2 = m_balancing_mat2.rwdata ();
 
   // first left
   F77_XFCN (sggbak, SGGBAK, (F77_CONST_CHAR_ARG2 (&job, 1),
--- a/liboctave/numeric/gepbalance.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/gepbalance.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-gepbalance
+class gepbalance
 {
 public:
 
--- a/liboctave/numeric/gsvd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/gsvd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -23,7 +23,7 @@
 //
 ////////////////////////////////////////////////////////////////////////
 
-#ifdef HAVE_CONFIG_H
+#if defined (HAVE_CONFIG_H)
 #  include "config.h"
 #endif
 
@@ -253,7 +253,7 @@
              F77_CONST_CHAR_ARG2 (&jobv, 1),
              F77_CONST_CHAR_ARG2 (&jobq, 1),
              m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              u, nrow_u, v, nrow_v, q, nrow_q,
              work, lwork, iwork, info
              F77_CHAR_ARG_LEN (1)
@@ -267,7 +267,7 @@
              F77_CONST_CHAR_ARG2 (&jobv, 1),
              F77_CONST_CHAR_ARG2 (&jobq, 1),
              m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              u, nrow_u, v, nrow_v, q, nrow_q,
              work, iwork, info
              F77_CHAR_ARG_LEN (1)
@@ -297,7 +297,7 @@
              F77_CONST_CHAR_ARG2 (&jobv, 1),
              F77_CONST_CHAR_ARG2 (&jobq, 1),
              m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              u, nrow_u, v, nrow_v, q, nrow_q,
              work, lwork, iwork, info
              F77_CHAR_ARG_LEN (1)
@@ -311,7 +311,7 @@
              F77_CONST_CHAR_ARG2 (&jobv, 1),
              F77_CONST_CHAR_ARG2 (&jobq, 1),
              m, n, p, k, l, tmp_dataA, m1, tmp_dataB, p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              u, nrow_u, v, nrow_v, q, nrow_q,
              work, iwork, info
              F77_CHAR_ARG_LEN (1)
@@ -345,7 +345,7 @@
              m, n, p, k, l,
              F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
              F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              F77_DBLE_CMPLX_ARG (u), nrow_u,
              F77_DBLE_CMPLX_ARG (v), nrow_v,
              F77_DBLE_CMPLX_ARG (q), nrow_q,
@@ -364,7 +364,7 @@
              m, n, p, k, l,
              F77_DBLE_CMPLX_ARG (tmp_dataA), m1,
              F77_DBLE_CMPLX_ARG (tmp_dataB), p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              F77_DBLE_CMPLX_ARG (u), nrow_u,
              F77_DBLE_CMPLX_ARG (v), nrow_v,
              F77_DBLE_CMPLX_ARG (q), nrow_q,
@@ -404,7 +404,7 @@
              m, n, p, k, l,
              F77_CMPLX_ARG (tmp_dataA), m1,
              F77_CMPLX_ARG (tmp_dataB), p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              F77_CMPLX_ARG (u), nrow_u,
              F77_CMPLX_ARG (v), nrow_v,
              F77_CMPLX_ARG (q), nrow_q,
@@ -423,7 +423,7 @@
              m, n, p, k, l,
              F77_CMPLX_ARG (tmp_dataA), m1,
              F77_CMPLX_ARG (tmp_dataB), p1,
-             alpha.fortran_vec (), beta.fortran_vec (),
+             alpha.rwdata (), beta.rwdata (),
              F77_CMPLX_ARG (u), nrow_u,
              F77_CMPLX_ARG (v), nrow_v,
              F77_CMPLX_ARG (q), nrow_q,
@@ -482,10 +482,10 @@
   F77_INT p = to_f77_int (b.rows ());
 
   T atmp = a;
-  P *tmp_dataA = atmp.fortran_vec ();
+  P *tmp_dataA = atmp.rwdata ();
 
   T btmp = b;
-  P *tmp_dataB = btmp.fortran_vec ();
+  P *tmp_dataB = btmp.rwdata ();
 
   char jobu = 'U';
   char jobv = 'V';
@@ -523,17 +523,17 @@
   if (jobu != 'N')
     m_left_smA.resize (nrow_u, m);
 
-  P *u = m_left_smA.fortran_vec ();
+  P *u = m_left_smA.rwdata ();
 
   if (jobv != 'N')
     m_left_smB.resize (nrow_v, p);
 
-  P *v = m_left_smB.fortran_vec ();
+  P *v = m_left_smB.rwdata ();
 
   if (jobq != 'N')
     m_right_sm.resize (nrow_q, n);
 
-  P *q = m_right_sm.fortran_vec ();
+  P *q = m_right_sm.rwdata ();
 
   real_matrix alpha (n, 1);
   real_matrix beta (n, 1);
--- a/liboctave/numeric/gsvd.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/gsvd.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-OCTAVE_API
-gsvd
+class OCTAVE_API gsvd
 {
 public:
 
--- a/liboctave/numeric/hess.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/hess.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -60,26 +60,26 @@
   F77_INT ihi;
 
   m_hess_mat = a;
-  double *h = m_hess_mat.fortran_vec ();
+  double *h = m_hess_mat.rwdata ();
 
   Array<double> scale (dim_vector (n, 1));
-  double *pscale = scale.fortran_vec ();
+  double *pscale = scale.rwdata ();
 
   F77_XFCN (dgebal, DGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),
                              n, h, n, ilo, ihi, pscale, info
                              F77_CHAR_ARG_LEN (1)));
 
   Array<double> tau (dim_vector (n-1, 1));
-  double *ptau = tau.fortran_vec ();
+  double *ptau = tau.rwdata ();
 
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   F77_XFCN (dgehrd, DGEHRD, (n, ilo, ihi, h, n, ptau, pwork,
                              lwork, info));
 
   m_unitary_hess_mat = m_hess_mat;
-  double *z = m_unitary_hess_mat.fortran_vec ();
+  double *z = m_unitary_hess_mat.rwdata ();
 
   F77_XFCN (dorghr, DORGHR, (n, ilo, ihi, z, n, ptau, pwork,
                              lwork, info));
@@ -123,26 +123,26 @@
   F77_INT ihi;
 
   m_hess_mat = a;
-  float *h = m_hess_mat.fortran_vec ();
+  float *h = m_hess_mat.rwdata ();
 
   Array<float> scale (dim_vector (n, 1));
-  float *pscale = scale.fortran_vec ();
+  float *pscale = scale.rwdata ();
 
   F77_XFCN (sgebal, SGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),
                              n, h, n, ilo, ihi, pscale, info
                              F77_CHAR_ARG_LEN (1)));
 
   Array<float> tau (dim_vector (n-1, 1));
-  float *ptau = tau.fortran_vec ();
+  float *ptau = tau.rwdata ();
 
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   F77_XFCN (sgehrd, SGEHRD, (n, ilo, ihi, h, n, ptau, pwork,
                              lwork, info));
 
   m_unitary_hess_mat = m_hess_mat;
-  float *z = m_unitary_hess_mat.fortran_vec ();
+  float *z = m_unitary_hess_mat.rwdata ();
 
   F77_XFCN (sorghr, SORGHR, (n, ilo, ihi, z, n, ptau, pwork,
                              lwork, info));
@@ -186,26 +186,26 @@
   F77_INT ihi;
 
   m_hess_mat = a;
-  Complex *h = m_hess_mat.fortran_vec ();
+  Complex *h = m_hess_mat.rwdata ();
 
   Array<double> scale (dim_vector (n, 1));
-  double *pscale = scale.fortran_vec ();
+  double *pscale = scale.rwdata ();
 
   F77_XFCN (zgebal, ZGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),
                              n, F77_DBLE_CMPLX_ARG (h), n, ilo, ihi, pscale, info
                              F77_CHAR_ARG_LEN (1)));
 
   Array<Complex> tau (dim_vector (n-1, 1));
-  Complex *ptau = tau.fortran_vec ();
+  Complex *ptau = tau.rwdata ();
 
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   F77_XFCN (zgehrd, ZGEHRD, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (h), n,
                              F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork), lwork, info));
 
   m_unitary_hess_mat = m_hess_mat;
-  Complex *z = m_unitary_hess_mat.fortran_vec ();
+  Complex *z = m_unitary_hess_mat.rwdata ();
 
   F77_XFCN (zunghr, ZUNGHR, (n, ilo, ihi, F77_DBLE_CMPLX_ARG (z), n,
                              F77_DBLE_CMPLX_ARG (ptau), F77_DBLE_CMPLX_ARG (pwork),
@@ -252,26 +252,26 @@
   F77_INT ihi;
 
   m_hess_mat = a;
-  FloatComplex *h = m_hess_mat.fortran_vec ();
+  FloatComplex *h = m_hess_mat.rwdata ();
 
   Array<float> scale (dim_vector (n, 1));
-  float *pscale = scale.fortran_vec ();
+  float *pscale = scale.rwdata ();
 
   F77_XFCN (cgebal, CGEBAL, (F77_CONST_CHAR_ARG2 (&job, 1),
                              n, F77_CMPLX_ARG (h), n, ilo, ihi, pscale, info
                              F77_CHAR_ARG_LEN (1)));
 
   Array<FloatComplex> tau (dim_vector (n-1, 1));
-  FloatComplex *ptau = tau.fortran_vec ();
+  FloatComplex *ptau = tau.rwdata ();
 
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   F77_XFCN (cgehrd, CGEHRD, (n, ilo, ihi, F77_CMPLX_ARG (h), n,
                              F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork), lwork, info));
 
   m_unitary_hess_mat = m_hess_mat;
-  FloatComplex *z = m_unitary_hess_mat.fortran_vec ();
+  FloatComplex *z = m_unitary_hess_mat.rwdata ();
 
   F77_XFCN (cunghr, CUNGHR, (n, ilo, ihi, F77_CMPLX_ARG (z), n,
                              F77_CMPLX_ARG (ptau), F77_CMPLX_ARG (pwork),
--- a/liboctave/numeric/hess.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/hess.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-hess
+class hess
 {
 public:
 
--- a/liboctave/numeric/lo-mappers.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/lo-mappers.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -178,38 +178,38 @@
 }
 
 bool
-negative_sign (double x) { return __lo_ieee_signbit (x); }
+negative_sign (double x) { return signbit (x); }
 bool
-negative_sign (float x) { return __lo_ieee_float_signbit (x); }
+negative_sign (float x) { return signbit (x); }
 
 // Sometimes you need a large integer, but not always.
 
 octave_idx_type
 nint_big (double x)
 {
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<octave_idx_type>::max ())+1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
+
   if (x >= out_of_range_top)
     return std::numeric_limits<octave_idx_type>::max ();
   else if (x < std::numeric_limits<octave_idx_type>::min ())
     return std::numeric_limits<octave_idx_type>::min ();
   else
-    return static_cast<octave_idx_type> ((x > 0.0) ? (x + 0.5)
-                                         : (x - 0.5));
+    return static_cast<octave_idx_type> ((x > 0.0) ? (x + 0.5) : (x - 0.5));
 }
 
 octave_idx_type
 nint_big (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<octave_idx_type>::max ())+1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
+
   if (x >= out_of_range_top)
     return std::numeric_limits<octave_idx_type>::max ();
   else if (x < std::numeric_limits<octave_idx_type>::min ())
     return std::numeric_limits<octave_idx_type>::min ();
   else
-    return static_cast<octave_idx_type> ((x > 0.0f) ? (x + 0.5f)
-                                         : (x - 0.5f));
+    return static_cast<octave_idx_type> ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f));
 }
 
 int
@@ -226,8 +226,9 @@
 int
 nint (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;
+
   if (x >= out_of_range_top)
     return std::numeric_limits<int>::max ();
   else if (x < std::numeric_limits<int>::min ())
--- a/liboctave/numeric/lo-mappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/lo-mappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -310,7 +310,7 @@
           T n = std::floor (q);
 
           // Prevent use of extra precision.
-          volatile T tmp = y * n;
+          T tmp = y * n;
 
           retval = x - tmp;
         }
@@ -343,7 +343,7 @@
           T n = std::trunc (q);
 
           // Prevent use of extra precision.
-          volatile T tmp = y * n;
+          T tmp = y * n;
 
           retval = x - tmp;
         }
--- a/liboctave/numeric/lo-specfun.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/lo-specfun.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -170,7 +170,7 @@
 airy (const ComplexNDArray& z, bool deriv, bool scaled,
       Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = z.dims ();
+  const dim_vector& dv = z.dims ();
   octave_idx_type nel = dv.numel ();
   ComplexNDArray retval (dv);
 
@@ -228,7 +228,7 @@
 airy (const FloatComplexNDArray& z, bool deriv, bool scaled,
       Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = z.dims ();
+  const dim_vector& dv = z.dims ();
   octave_idx_type nel = dv.numel ();
   FloatComplexNDArray retval (dv);
 
@@ -643,7 +643,7 @@
 do_bessel (dptr f, const char *, double alpha, const ComplexNDArray& x,
            bool scaled, Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = x.dims ();
+  const dim_vector& dv = x.dims ();
   octave_idx_type nel = dv.numel ();
   ComplexNDArray retval (dv);
 
@@ -659,7 +659,7 @@
 do_bessel (dptr f, const char *, const NDArray& alpha, const Complex& x,
            bool scaled, Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = alpha.dims ();
+  const dim_vector& dv = alpha.dims ();
   octave_idx_type nel = dv.numel ();
   ComplexNDArray retval (dv);
 
@@ -675,7 +675,7 @@
 do_bessel (dptr f, const char *fn, const NDArray& alpha,
            const ComplexNDArray& x, bool scaled, Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = x.dims ();
+  const dim_vector& dv = x.dims ();
   ComplexNDArray retval;
 
   if (dv != alpha.dims ())
@@ -1185,7 +1185,7 @@
 do_bessel (fptr f, const char *, float alpha, const FloatComplexNDArray& x,
            bool scaled, Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = x.dims ();
+  const dim_vector& dv = x.dims ();
   octave_idx_type nel = dv.numel ();
   FloatComplexNDArray retval (dv);
 
@@ -1201,7 +1201,7 @@
 do_bessel (fptr f, const char *, const FloatNDArray& alpha,
            const FloatComplex& x, bool scaled, Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = alpha.dims ();
+  const dim_vector& dv = alpha.dims ();
   octave_idx_type nel = dv.numel ();
   FloatComplexNDArray retval (dv);
 
@@ -1218,7 +1218,7 @@
            const FloatComplexNDArray& x, bool scaled,
            Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = x.dims ();
+  const dim_vector& dv = x.dims ();
   FloatComplexNDArray retval;
 
   if (dv != alpha.dims ())
@@ -1392,7 +1392,7 @@
 biry (const ComplexNDArray& z, bool deriv, bool scaled,
       Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = z.dims ();
+  const dim_vector& dv = z.dims ();
   octave_idx_type nel = dv.numel ();
   ComplexNDArray retval (dv);
 
@@ -1450,7 +1450,7 @@
 biry (const FloatComplexNDArray& z, bool deriv, bool scaled,
       Array<octave_idx_type>& ierr)
 {
-  dim_vector dv = z.dims ();
+  const dim_vector& dv = z.dims ();
   octave_idx_type nel = dv.numel ();
   FloatComplexNDArray retval (dv);
 
--- a/liboctave/numeric/lu.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/lu.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -278,10 +278,10 @@
   F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
 
   m_ipvt.resize (dim_vector (mn, 1));
-  F77_INT *pipvt = m_ipvt.fortran_vec ();
+  F77_INT *pipvt = m_ipvt.rwdata ();
 
   m_a_fact = a;
-  double *tmp_data = m_a_fact.fortran_vec ();
+  double *tmp_data = m_a_fact.rwdata ();
 
   F77_INT info = 0;
 
@@ -315,8 +315,8 @@
 
   ColumnVector utmp = u;
   ColumnVector vtmp = v;
-  F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (), m, r.fortran_vec (),
-                             k, utmp.fortran_vec (), vtmp.fortran_vec ()));
+  F77_XFCN (dlu1up, DLU1UP, (m, n, l.rwdata (), m, r.rwdata (),
+                             k, utmp.rwdata (), vtmp.rwdata ()));
 }
 
 template <>
@@ -342,13 +342,13 @@
   if (u_nr != m || v_nr != n || u_nc != v_nc)
     (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
 
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       ColumnVector utmp = u.column (i);
       ColumnVector vtmp = v.column (i);
-      F77_XFCN (dlu1up, DLU1UP, (m, n, l.fortran_vec (),
-                                 m, r.fortran_vec (), k,
-                                 utmp.fortran_vec (), vtmp.fortran_vec ()));
+      F77_XFCN (dlu1up, DLU1UP, (m, n, l.rwdata (),
+                                 m, r.rwdata (), k,
+                                 utmp.rwdata (), vtmp.rwdata ()));
     }
 }
 
@@ -376,9 +376,9 @@
   ColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (double, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (),
-                               m, r.fortran_vec (), k,
-                               m_ipvt.fortran_vec (),
+  F77_XFCN (dlup1up, DLUP1UP, (m, n, l.rwdata (),
+                               m, r.rwdata (), k,
+                               m_ipvt.rwdata (),
                                utmp.data (), vtmp.data (), w));
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
 }
@@ -408,13 +408,13 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       ColumnVector utmp = u.column (i);
       ColumnVector vtmp = v.column (i);
-      F77_XFCN (dlup1up, DLUP1UP, (m, n, l.fortran_vec (),
-                                   m, r.fortran_vec (), k,
-                                   m_ipvt.fortran_vec (),
+      F77_XFCN (dlup1up, DLUP1UP, (m, n, l.rwdata (),
+                                   m, r.rwdata (), k,
+                                   m_ipvt.rwdata (),
                                    utmp.data (), vtmp.data (), w));
     }
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
@@ -431,10 +431,10 @@
   F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
 
   m_ipvt.resize (dim_vector (mn, 1));
-  F77_INT *pipvt = m_ipvt.fortran_vec ();
+  F77_INT *pipvt = m_ipvt.rwdata ();
 
   m_a_fact = a;
-  float *tmp_data = m_a_fact.fortran_vec ();
+  float *tmp_data = m_a_fact.rwdata ();
 
   F77_INT info = 0;
 
@@ -469,9 +469,9 @@
 
   FloatColumnVector utmp = u;
   FloatColumnVector vtmp = v;
-  F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (),
-                             m, r.fortran_vec (), k,
-                             utmp.fortran_vec (), vtmp.fortran_vec ()));
+  F77_XFCN (slu1up, SLU1UP, (m, n, l.rwdata (),
+                             m, r.rwdata (), k,
+                             utmp.rwdata (), vtmp.rwdata ()));
 }
 
 template <>
@@ -497,13 +497,13 @@
   if (u_nr != m || v_nr != n || u_nc != v_nc)
     (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
 
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       FloatColumnVector utmp = u.column (i);
       FloatColumnVector vtmp = v.column (i);
-      F77_XFCN (slu1up, SLU1UP, (m, n, l.fortran_vec (),
-                                 m, r.fortran_vec (), k,
-                                 utmp.fortran_vec (), vtmp.fortran_vec ()));
+      F77_XFCN (slu1up, SLU1UP, (m, n, l.rwdata (),
+                                 m, r.rwdata (), k,
+                                 utmp.rwdata (), vtmp.rwdata ()));
     }
 }
 
@@ -532,9 +532,9 @@
   FloatColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (float, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (),
-                               m, r.fortran_vec (), k,
-                               m_ipvt.fortran_vec (),
+  F77_XFCN (slup1up, SLUP1UP, (m, n, l.rwdata (),
+                               m, r.rwdata (), k,
+                               m_ipvt.rwdata (),
                                utmp.data (), vtmp.data (), w));
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
 }
@@ -564,13 +564,13 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       FloatColumnVector utmp = u.column (i);
       FloatColumnVector vtmp = v.column (i);
-      F77_XFCN (slup1up, SLUP1UP, (m, n, l.fortran_vec (),
-                                   m, r.fortran_vec (), k,
-                                   m_ipvt.fortran_vec (),
+      F77_XFCN (slup1up, SLUP1UP, (m, n, l.rwdata (),
+                                   m, r.rwdata (), k,
+                                   m_ipvt.rwdata (),
                                    utmp.data (), vtmp.data (), w));
     }
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) -= 1; // decrement
@@ -587,10 +587,10 @@
   F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
 
   m_ipvt.resize (dim_vector (mn, 1));
-  F77_INT *pipvt = m_ipvt.fortran_vec ();
+  F77_INT *pipvt = m_ipvt.rwdata ();
 
   m_a_fact = a;
-  Complex *tmp_data = m_a_fact.fortran_vec ();
+  Complex *tmp_data = m_a_fact.rwdata ();
 
   F77_INT info = 0;
 
@@ -626,10 +626,10 @@
 
   ComplexColumnVector utmp = u;
   ComplexColumnVector vtmp = v;
-  F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()), m,
-                             F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
-                             F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ())));
+  F77_XFCN (zlu1up, ZLU1UP, (m, n, F77_DBLE_CMPLX_ARG (l.rwdata ()), m,
+                             F77_DBLE_CMPLX_ARG (r.rwdata ()), k,
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
+                             F77_DBLE_CMPLX_ARG (vtmp.rwdata ())));
 }
 
 template <>
@@ -655,16 +655,16 @@
   if (u_nr != m || v_nr != n || u_nc != v_nc)
     (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
 
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       ComplexColumnVector utmp = u.column (i);
       ComplexColumnVector vtmp = v.column (i);
       F77_XFCN (zlu1up, ZLU1UP, (m, n,
-                                 F77_DBLE_CMPLX_ARG (l.fortran_vec ()),
-                                 m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
+                                 F77_DBLE_CMPLX_ARG (l.rwdata ()),
+                                 m, F77_DBLE_CMPLX_ARG (r.rwdata ()),
                                  k,
-                                 F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
-                                 F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ())));
+                                 F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
+                                 F77_DBLE_CMPLX_ARG (vtmp.rwdata ())));
     }
 }
 
@@ -693,9 +693,9 @@
   ComplexColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (Complex, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.fortran_vec ()),
-                               m, F77_DBLE_CMPLX_ARG (r.fortran_vec ()), k,
-                               m_ipvt.fortran_vec (),
+  F77_XFCN (zlup1up, ZLUP1UP, (m, n, F77_DBLE_CMPLX_ARG (l.rwdata ()),
+                               m, F77_DBLE_CMPLX_ARG (r.rwdata ()), k,
+                               m_ipvt.rwdata (),
                                F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
                                F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),
                                F77_DBLE_CMPLX_ARG (w)));
@@ -728,15 +728,15 @@
 
   OCTAVE_LOCAL_BUFFER (Complex, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       ComplexColumnVector utmp = u.column (i);
       ComplexColumnVector vtmp = v.column (i);
       F77_XFCN (zlup1up, ZLUP1UP, (m, n,
-                                   F77_DBLE_CMPLX_ARG (l.fortran_vec ()),
+                                   F77_DBLE_CMPLX_ARG (l.rwdata ()),
                                    m,
-                                   F77_DBLE_CMPLX_ARG (r.fortran_vec ()),
-                                   k, m_ipvt.fortran_vec (),
+                                   F77_DBLE_CMPLX_ARG (r.rwdata ()),
+                                   k, m_ipvt.rwdata (),
                                    F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
                                    F77_CONST_DBLE_CMPLX_ARG (vtmp.data ()),
                                    F77_DBLE_CMPLX_ARG (w)));
@@ -755,10 +755,10 @@
   F77_INT mn = (a_nr < a_nc ? a_nr : a_nc);
 
   m_ipvt.resize (dim_vector (mn, 1));
-  F77_INT *pipvt = m_ipvt.fortran_vec ();
+  F77_INT *pipvt = m_ipvt.rwdata ();
 
   m_a_fact = a;
-  FloatComplex *tmp_data = m_a_fact.fortran_vec ();
+  FloatComplex *tmp_data = m_a_fact.rwdata ();
 
   F77_INT info = 0;
 
@@ -794,10 +794,10 @@
 
   FloatComplexColumnVector utmp = u;
   FloatComplexColumnVector vtmp = v;
-  F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()), m,
-                             F77_CMPLX_ARG (r.fortran_vec ()), k,
-                             F77_CMPLX_ARG (utmp.fortran_vec ()),
-                             F77_CMPLX_ARG (vtmp.fortran_vec ())));
+  F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()), m,
+                             F77_CMPLX_ARG (r.rwdata ()), k,
+                             F77_CMPLX_ARG (utmp.rwdata ()),
+                             F77_CMPLX_ARG (vtmp.rwdata ())));
 }
 
 template <>
@@ -824,14 +824,14 @@
   if (u_nr != m || v_nr != n || u_nc != v_nc)
     (*current_liboctave_error_handler) ("luupdate: dimensions mismatch");
 
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       FloatComplexColumnVector utmp = u.column (i);
       FloatComplexColumnVector vtmp = v.column (i);
-      F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
-                                 m, F77_CMPLX_ARG (r.fortran_vec ()), k,
-                                 F77_CMPLX_ARG (utmp.fortran_vec ()),
-                                 F77_CMPLX_ARG (vtmp.fortran_vec ())));
+      F77_XFCN (clu1up, CLU1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),
+                                 m, F77_CMPLX_ARG (r.rwdata ()), k,
+                                 F77_CMPLX_ARG (utmp.rwdata ()),
+                                 F77_CMPLX_ARG (vtmp.rwdata ())));
     }
 }
 
@@ -860,9 +860,9 @@
   FloatComplexColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
-                               m, F77_CMPLX_ARG (r.fortran_vec ()), k,
-                               m_ipvt.fortran_vec (),
+  F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),
+                               m, F77_CMPLX_ARG (r.rwdata ()), k,
+                               m_ipvt.rwdata (),
                                F77_CONST_CMPLX_ARG (utmp.data ()),
                                F77_CONST_CMPLX_ARG (vtmp.data ()),
                                F77_CMPLX_ARG (w)));
@@ -895,13 +895,13 @@
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);
   for (F77_INT i = 0; i < m; i++) m_ipvt(i) += 1; // increment
-  for (volatile F77_INT i = 0; i < u_nc; i++)
+  for (F77_INT i = 0; i < u_nc; i++)
     {
       FloatComplexColumnVector utmp = u.column (i);
       FloatComplexColumnVector vtmp = v.column (i);
-      F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.fortran_vec ()),
-                                   m, F77_CMPLX_ARG (r.fortran_vec ()), k,
-                                   m_ipvt.fortran_vec (),
+      F77_XFCN (clup1up, CLUP1UP, (m, n, F77_CMPLX_ARG (l.rwdata ()),
+                                   m, F77_CMPLX_ARG (r.rwdata ()), k,
+                                   m_ipvt.rwdata (),
                                    F77_CONST_CMPLX_ARG (utmp.data ()),
                                    F77_CONST_CMPLX_ARG (vtmp.data ()),
                                    F77_CMPLX_ARG (w)));
--- a/liboctave/numeric/lu.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/lu.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,8 +37,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-lu
+class lu
 {
 public:
 
--- a/liboctave/numeric/oct-convn.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/oct-convn.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -180,7 +180,7 @@
 
   convolve_nd<T, R> (a.data (), adims, adims.cumulative (),
                      b.data (), bdims, bdims.cumulative (),
-                     c.fortran_vec (), cdims.cumulative (),
+                     c.rwdata (), cdims.cumulative (),
                      nd, ct == convn_valid);
 
   if (ct == convn_same)
--- a/liboctave/numeric/oct-fftw.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/oct-fftw.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-fftw_planner
+class OCTAVE_API fftw_planner
 {
 protected:
 
@@ -179,9 +177,7 @@
   int m_nthreads;
 };
 
-class
-OCTAVE_API
-float_fftw_planner
+class OCTAVE_API float_fftw_planner
 {
 protected:
 
@@ -321,9 +317,7 @@
   int m_nthreads;
 };
 
-class
-OCTAVE_API
-fftw
+class OCTAVE_API fftw
 {
 public:
 
--- a/liboctave/numeric/oct-norm.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/oct-norm.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -357,7 +357,7 @@
     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))                                 \
+  else if (math::isinf (p))                                   \
     {                                                         \
       if (p > 0)                                              \
         FCN_NAME (v, res, norm_accumulator_inf<R> ());        \
@@ -551,7 +551,7 @@
     }
   else if (p == 1)
     res = xcolnorms (m, static_cast<R> (1)).max ();
-  else if (lo_ieee_isinf (p) && p > 1)
+  else if (math::isinf (p) && p > 1)
     res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
@@ -573,7 +573,7 @@
   R res = 0;
   if (p == 1)
     res = xcolnorms (m, static_cast<R> (1)).max ();
-  else if (lo_ieee_isinf (p) && p > 1)
+  else if (math::isinf (p) && p > 1)
     res = xrownorms (m, static_cast<R> (1)).max ();
   else if (p > 1)
     {
--- a/liboctave/numeric/oct-rand.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/oct-rand.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,7 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
 #include <cstdint>
 
 #include <limits>
@@ -98,7 +97,7 @@
 static int32_t
 force_to_fit_range (int32_t i, int32_t lo, int32_t hi)
 {
-  assert (hi > lo && lo >= 0);
+  liboctave_panic_unless (hi > lo && lo >= 0);
 
   i = (i > 0 ? i : -i);
 
@@ -523,7 +522,7 @@
     {
       retval.clear (n, 1);
 
-      fill (retval.numel (), retval.fortran_vec (), a);
+      fill (retval.numel (), retval.rwdata (), a);
     }
   else if (n < 0)
     (*current_liboctave_error_handler) ("rand: invalid negative argument");
@@ -545,7 +544,7 @@
     {
       retval.clear (dims);
 
-      fill (retval.numel (), retval.fortran_vec (), a);
+      fill (retval.numel (), retval.rwdata (), a);
     }
 
   return retval;
@@ -560,7 +559,7 @@
     {
       retval.clear (dims);
 
-      fill (retval.numel (), retval.fortran_vec (), a);
+      fill (retval.numel (), retval.rwdata (), a);
     }
 
   return retval;
@@ -627,7 +626,7 @@
 {
   uint32NDArray s (dim_vector (MT_N + 1, 1));
 
-  get_mersenne_twister_state (reinterpret_cast<uint32_t *> (s.fortran_vec ()));
+  get_mersenne_twister_state (reinterpret_cast<uint32_t *> (s.rwdata ()));
 
   return s;
 }
--- a/liboctave/numeric/qr.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/qr.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -435,14 +435,14 @@
           F77_INT k = to_f77_int (m_q.cols ());
           // workspace query.
           double rlwork;
-          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m,
+          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.rwdata (), m,
                                      tau, &rlwork, -1, info));
 
           // allocate buffer and do the job.
           F77_INT lwork = static_cast<F77_INT> (rlwork);
           lwork = std::max (lwork, static_cast<F77_INT> (1));
           OCTAVE_LOCAL_BUFFER (double, work, lwork);
-          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.fortran_vec (), m,
+          F77_XFCN (dorgqr, DORGQR, (m, k, min_mn, m_q.rwdata (), m,
                                      tau, work, lwork, info));
         }
     }
@@ -468,14 +468,14 @@
     {
       // workspace query.
       double rlwork;
-      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau,
+      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.rwdata (), m, tau,
                                  &rlwork, -1, info));
 
       // allocate buffer and do the job.
       F77_INT lwork = static_cast<F77_INT> (rlwork);
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (double, work, lwork);
-      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.fortran_vec (), m, tau,
+      F77_XFCN (dgeqrf, DGEQRF, (m, n, afact.rwdata (), m, tau,
                                  work, lwork, info));
     }
 
@@ -501,9 +501,9 @@
   ColumnVector utmp = u;
   ColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (double, w, 2*k);
-  F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.fortran_vec (), m,
-                             m_r.fortran_vec (), k, utmp.fortran_vec (),
-                             vtmp.fortran_vec (), w));
+  F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.rwdata (), m,
+                             m_r.rwdata (), k, utmp.rwdata (),
+                             vtmp.rwdata (), w));
 }
 
 template <>
@@ -524,13 +524,13 @@
     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
 
   OCTAVE_LOCAL_BUFFER (double, w, 2*k);
-  for (volatile F77_INT i = 0; i < u_cols; i++)
+  for (F77_INT i = 0; i < u_cols; i++)
     {
       ColumnVector utmp = u.column (i);
       ColumnVector vtmp = v.column (i);
-      F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.fortran_vec (), m,
-                                 m_r.fortran_vec (), k, utmp.fortran_vec (),
-                                 vtmp.fortran_vec (), w));
+      F77_XFCN (dqr1up, DQR1UP, (m, n, k, m_q.rwdata (), m,
+                                 m_r.rwdata (), k, utmp.rwdata (),
+                                 vtmp.rwdata (), w));
     }
 }
 
@@ -565,8 +565,8 @@
 
   ColumnVector utmp = u;
   OCTAVE_LOCAL_BUFFER (double, w, k);
-  F77_XFCN (dqrinc, DQRINC, (m, n, k, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1,
+  F77_XFCN (dqrinc, DQRINC, (m, n, k, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1,
                              utmp.data (), w));
 }
 
@@ -615,14 +615,14 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (double, w, kmax);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           ColumnVector utmp = u.column (jsi(i));
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (dqrinc, DQRINC, (m, n + ii, std::min (kmax, k + ii),
-                                     m_q.fortran_vec (), ldq,
-                                     m_r.fortran_vec (), ldr, js_elt + 1,
+                                     m_q.rwdata (), ldq,
+                                     m_r.rwdata (), ldr, js_elt + 1,
                                      utmp.data (), w));
         }
     }
@@ -645,8 +645,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (double, w, k);
-  F77_XFCN (dqrdec, DQRDEC, (m, n, k, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1, w));
+  F77_XFCN (dqrdec, DQRDEC, (m, n, k, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1, w));
 
   if (k < m)
     {
@@ -687,13 +687,13 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (double, w, k);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (dqrdec, DQRDEC, (m, n - ii, (k == m ? k : k - ii),
-                                     m_q.fortran_vec (), ldq,
-                                     m_r.fortran_vec (), ldr,
+                                     m_q.rwdata (), ldq,
+                                     m_r.rwdata (), ldr,
                                      js_elt + 1, w));
         }
 
@@ -733,9 +733,9 @@
 
   RowVector utmp = u;
   OCTAVE_LOCAL_BUFFER (double, w, k);
-  F77_XFCN (dqrinr, DQRINR, (m, n, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr,
-                             j + 1, utmp.fortran_vec (), w));
+  F77_XFCN (dqrinr, DQRINR, (m, n, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr,
+                             j + 1, utmp.rwdata (), w));
 
 }
 
@@ -758,8 +758,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (double, w, 2*m);
-  F77_XFCN (dqrder, DQRDER, (m, n, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1, w));
+  F77_XFCN (dqrder, DQRDER, (m, n, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1, w));
 
   m_q.resize (m - 1, m - 1);
   m_r.resize (m - 1, n);
@@ -784,8 +784,8 @@
 
   OCTAVE_LOCAL_BUFFER (double, w, 2*k);
   F77_XFCN (dqrshc, DQRSHC, (m, n, k,
-                             m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr,
+                             m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr,
                              i + 1, j + 1, w));
 }
 
@@ -849,14 +849,14 @@
           F77_INT k = to_f77_int (m_q.cols ());
           // workspace query.
           float rlwork;
-          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m,
+          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.rwdata (), m,
                                      tau, &rlwork, -1, info));
 
           // allocate buffer and do the job.
           F77_INT lwork = static_cast<F77_INT> (rlwork);
           lwork = std::max (lwork, static_cast<F77_INT> (1));
           OCTAVE_LOCAL_BUFFER (float, work, lwork);
-          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.fortran_vec (), m,
+          F77_XFCN (sorgqr, SORGQR, (m, k, min_mn, m_q.rwdata (), m,
                                      tau, work, lwork, info));
         }
     }
@@ -882,14 +882,14 @@
     {
       // workspace query.
       float rlwork;
-      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau,
+      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.rwdata (), m, tau,
                                  &rlwork, -1, info));
 
       // allocate buffer and do the job.
       F77_INT lwork = static_cast<F77_INT> (rlwork);
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (float, work, lwork);
-      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.fortran_vec (), m, tau,
+      F77_XFCN (sgeqrf, SGEQRF, (m, n, afact.rwdata (), m, tau,
                                  work, lwork, info));
     }
 
@@ -915,9 +915,9 @@
   FloatColumnVector utmp = u;
   FloatColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (float, w, 2*k);
-  F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.fortran_vec (), m,
-                             m_r.fortran_vec (), k, utmp.fortran_vec (),
-                             vtmp.fortran_vec (), w));
+  F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.rwdata (), m,
+                             m_r.rwdata (), k, utmp.rwdata (),
+                             vtmp.rwdata (), w));
 }
 
 template <>
@@ -938,13 +938,13 @@
     (*current_liboctave_error_handler) ("qrupdate: dimensions mismatch");
 
   OCTAVE_LOCAL_BUFFER (float, w, 2*k);
-  for (volatile F77_INT i = 0; i < u_cols; i++)
+  for (F77_INT i = 0; i < u_cols; i++)
     {
       FloatColumnVector utmp = u.column (i);
       FloatColumnVector vtmp = v.column (i);
-      F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.fortran_vec (), m,
-                                 m_r.fortran_vec (), k, utmp.fortran_vec (),
-                                 vtmp.fortran_vec (), w));
+      F77_XFCN (sqr1up, SQR1UP, (m, n, k, m_q.rwdata (), m,
+                                 m_r.rwdata (), k, utmp.rwdata (),
+                                 vtmp.rwdata (), w));
     }
 }
 
@@ -980,8 +980,8 @@
 
   FloatColumnVector utmp = u;
   OCTAVE_LOCAL_BUFFER (float, w, k);
-  F77_XFCN (sqrinc, SQRINC, (m, n, k, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1,
+  F77_XFCN (sqrinc, SQRINC, (m, n, k, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1,
                              utmp.data (), w));
 }
 
@@ -1031,14 +1031,14 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (float, w, kmax);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           FloatColumnVector utmp = u.column (jsi(i));
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (sqrinc, SQRINC, (m, n + ii, std::min (kmax, k + ii),
-                                     m_q.fortran_vec (), ldq,
-                                     m_r.fortran_vec (), ldr, js_elt + 1,
+                                     m_q.rwdata (), ldq,
+                                     m_r.rwdata (), ldr, js_elt + 1,
                                      utmp.data (), w));
         }
     }
@@ -1061,8 +1061,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (float, w, k);
-  F77_XFCN (sqrdec, SQRDEC, (m, n, k, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1, w));
+  F77_XFCN (sqrdec, SQRDEC, (m, n, k, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1, w));
 
   if (k < m)
     {
@@ -1103,13 +1103,13 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (float, w, k);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (sqrdec, SQRDEC, (m, n - ii, (k == m ? k : k - ii),
-                                     m_q.fortran_vec (), ldq,
-                                     m_r.fortran_vec (), ldr,
+                                     m_q.rwdata (), ldq,
+                                     m_r.rwdata (), ldr,
                                      js_elt + 1, w));
         }
 
@@ -1150,9 +1150,9 @@
 
   FloatRowVector utmp = u;
   OCTAVE_LOCAL_BUFFER (float, w, k);
-  F77_XFCN (sqrinr, SQRINR, (m, n, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr,
-                             j + 1, utmp.fortran_vec (), w));
+  F77_XFCN (sqrinr, SQRINR, (m, n, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr,
+                             j + 1, utmp.rwdata (), w));
 
 }
 
@@ -1175,8 +1175,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (float, w, 2*m);
-  F77_XFCN (sqrder, SQRDER, (m, n, m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr, j + 1,
+  F77_XFCN (sqrder, SQRDER, (m, n, m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr, j + 1,
                              w));
 
   m_q.resize (m - 1, m - 1);
@@ -1202,8 +1202,8 @@
 
   OCTAVE_LOCAL_BUFFER (float, w, 2*k);
   F77_XFCN (sqrshc, SQRSHC, (m, n, k,
-                             m_q.fortran_vec (), ldq,
-                             m_r.fortran_vec (), ldr,
+                             m_q.rwdata (), ldq,
+                             m_r.rwdata (), ldr,
                              i + 1, j + 1, w));
 }
 
@@ -1268,7 +1268,7 @@
           // workspace query.
           Complex clwork;
           F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,
-                                     F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
                                      m, F77_DBLE_CMPLX_ARG (tau),
                                      F77_DBLE_CMPLX_ARG (&clwork), -1,
                                      info));
@@ -1278,7 +1278,7 @@
           lwork = std::max (lwork, static_cast<F77_INT> (1));
           OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
           F77_XFCN (zungqr, ZUNGQR, (m, k, min_mn,
-                                     F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
                                      m, F77_DBLE_CMPLX_ARG (tau),
                                      F77_DBLE_CMPLX_ARG (work), lwork,
                                      info));
@@ -1307,7 +1307,7 @@
       // workspace query.
       Complex clwork;
       F77_XFCN (zgeqrf, ZGEQRF, (m, n,
-                                 F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
+                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),
                                  m, F77_DBLE_CMPLX_ARG (tau),
                                  F77_DBLE_CMPLX_ARG (&clwork), -1, info));
 
@@ -1316,7 +1316,7 @@
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
       F77_XFCN (zgeqrf, ZGEQRF, (m, n,
-                                 F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
+                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),
                                  m, F77_DBLE_CMPLX_ARG (tau),
                                  F77_DBLE_CMPLX_ARG (work), lwork, info));
     }
@@ -1345,10 +1345,10 @@
   ComplexColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (Complex, w, k);
   OCTAVE_LOCAL_BUFFER (double, rw, k);
-  F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                             m, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), k,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
-                             F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()),
+  F77_XFCN (zqr1up, ZQR1UP, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                             m, F77_DBLE_CMPLX_ARG (m_r.rwdata ()), k,
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
+                             F77_DBLE_CMPLX_ARG (vtmp.rwdata ()),
                              F77_DBLE_CMPLX_ARG (w), rw));
 }
 
@@ -1371,15 +1371,15 @@
 
   OCTAVE_LOCAL_BUFFER (Complex, w, k);
   OCTAVE_LOCAL_BUFFER (double, rw, k);
-  for (volatile F77_INT i = 0; i < u_cols; i++)
+  for (F77_INT i = 0; i < u_cols; i++)
     {
       ComplexColumnVector utmp = u.column (i);
       ComplexColumnVector vtmp = v.column (i);
       F77_XFCN (zqr1up, ZQR1UP, (m, n, k,
-                                 F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                                 m, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), k,
-                                 F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()),
-                                 F77_DBLE_CMPLX_ARG (vtmp.fortran_vec ()),
+                                 F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                                 m, F77_DBLE_CMPLX_ARG (m_r.rwdata ()), k,
+                                 F77_DBLE_CMPLX_ARG (utmp.rwdata ()),
+                                 F77_DBLE_CMPLX_ARG (vtmp.rwdata ()),
                                  F77_DBLE_CMPLX_ARG (w), rw));
     }
 }
@@ -1416,8 +1416,8 @@
 
   ComplexColumnVector utmp = u;
   OCTAVE_LOCAL_BUFFER (double, rw, k);
-  F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                             ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+  F77_XFCN (zqrinc, ZQRINC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                              ldr, j + 1,
                              F77_CONST_DBLE_CMPLX_ARG (utmp.data ()), rw));
 }
@@ -1468,15 +1468,15 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (double, rw, kmax);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           ComplexColumnVector utmp = u.column (jsi(i));
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (zqrinc, ZQRINC, (m, n + ii, std::min (kmax, k + ii),
-                                     F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
                                      ldq,
-                                     F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                                      ldr, js_elt + 1,
                                      F77_CONST_DBLE_CMPLX_ARG (utmp.data ()),
                                      rw));
@@ -1501,8 +1501,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (double, rw, k);
-  F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                             ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+  F77_XFCN (zqrdec, ZQRDEC, (m, n, k, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                              ldr, j + 1, rw));
 
   if (k < m)
@@ -1544,14 +1544,14 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (double, rw, k);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (zqrdec, ZQRDEC, (m, n - ii, (k == m ? k : k - ii),
-                                     F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
                                      ldq,
-                                     F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+                                     F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                                      ldr, js_elt + 1, rw));
         }
 
@@ -1592,10 +1592,10 @@
 
   ComplexRowVector utmp = u;
   OCTAVE_LOCAL_BUFFER (double, rw, k);
-  F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                             ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+  F77_XFCN (zqrinr, ZQRINR, (m, n, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                              ldr, j + 1,
-                             F77_DBLE_CMPLX_ARG (utmp.fortran_vec ()), rw));
+                             F77_DBLE_CMPLX_ARG (utmp.rwdata ()), rw));
 
 }
 
@@ -1619,8 +1619,8 @@
 
   OCTAVE_LOCAL_BUFFER (Complex, w, m);
   OCTAVE_LOCAL_BUFFER (double, rw, m);
-  F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()),
-                             ldq, F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()),
+  F77_XFCN (zqrder, ZQRDER, (m, n, F77_DBLE_CMPLX_ARG (m_q.rwdata ()),
+                             ldq, F77_DBLE_CMPLX_ARG (m_r.rwdata ()),
                              ldr, j + 1, F77_DBLE_CMPLX_ARG (w), rw));
 
   m_q.resize (m - 1, m - 1);
@@ -1648,8 +1648,8 @@
   OCTAVE_LOCAL_BUFFER (Complex, w, k);
   OCTAVE_LOCAL_BUFFER (double, rw, k);
   F77_XFCN (zqrshc, ZQRSHC, (m, n, k,
-                             F77_DBLE_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_DBLE_CMPLX_ARG (m_r.fortran_vec ()), ldr,
+                             F77_DBLE_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_DBLE_CMPLX_ARG (m_r.rwdata ()), ldr,
                              i + 1, j + 1, F77_DBLE_CMPLX_ARG (w), rw));
 }
 
@@ -1714,7 +1714,7 @@
           // workspace query.
           FloatComplex clwork;
           F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,
-                                     F77_CMPLX_ARG (m_q.fortran_vec ()), m,
+                                     F77_CMPLX_ARG (m_q.rwdata ()), m,
                                      F77_CMPLX_ARG (tau),
                                      F77_CMPLX_ARG (&clwork), -1, info));
 
@@ -1723,7 +1723,7 @@
           lwork = std::max (lwork, static_cast<F77_INT> (1));
           OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
           F77_XFCN (cungqr, CUNGQR, (m, k, min_mn,
-                                     F77_CMPLX_ARG (m_q.fortran_vec ()), m,
+                                     F77_CMPLX_ARG (m_q.rwdata ()), m,
                                      F77_CMPLX_ARG (tau),
                                      F77_CMPLX_ARG (work), lwork, info));
         }
@@ -1750,7 +1750,7 @@
     {
       // workspace query.
       FloatComplex clwork;
-      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()),
+      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.rwdata ()),
                                  m, F77_CMPLX_ARG (tau),
                                  F77_CMPLX_ARG (&clwork), -1, info));
 
@@ -1758,7 +1758,7 @@
       F77_INT lwork = static_cast<F77_INT> (clwork.real ());
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
-      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.fortran_vec ()),
+      F77_XFCN (cgeqrf, CGEQRF, (m, n, F77_CMPLX_ARG (afact.rwdata ()),
                                  m, F77_CMPLX_ARG (tau),
                                  F77_CMPLX_ARG (work), lwork, info));
     }
@@ -1787,10 +1787,10 @@
   FloatComplexColumnVector vtmp = v;
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
   OCTAVE_LOCAL_BUFFER (float, rw, k);
-  F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()),
-                             m, F77_CMPLX_ARG (m_r.fortran_vec ()), k,
-                             F77_CMPLX_ARG (utmp.fortran_vec ()),
-                             F77_CMPLX_ARG (vtmp.fortran_vec ()),
+  F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()),
+                             m, F77_CMPLX_ARG (m_r.rwdata ()), k,
+                             F77_CMPLX_ARG (utmp.rwdata ()),
+                             F77_CMPLX_ARG (vtmp.rwdata ()),
                              F77_CMPLX_ARG (w), rw));
 }
 
@@ -1814,14 +1814,14 @@
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
   OCTAVE_LOCAL_BUFFER (float, rw, k);
-  for (volatile F77_INT i = 0; i < u_cols; i++)
+  for (F77_INT i = 0; i < u_cols; i++)
     {
       FloatComplexColumnVector utmp = u.column (i);
       FloatComplexColumnVector vtmp = v.column (i);
-      F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()),
-                                 m, F77_CMPLX_ARG (m_r.fortran_vec ()), k,
-                                 F77_CMPLX_ARG (utmp.fortran_vec ()),
-                                 F77_CMPLX_ARG (vtmp.fortran_vec ()),
+      F77_XFCN (cqr1up, CQR1UP, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()),
+                                 m, F77_CMPLX_ARG (m_r.rwdata ()), k,
+                                 F77_CMPLX_ARG (utmp.rwdata ()),
+                                 F77_CMPLX_ARG (vtmp.rwdata ()),
                                  F77_CMPLX_ARG (w), rw));
     }
 }
@@ -1858,8 +1858,8 @@
 
   FloatComplexColumnVector utmp = u;
   OCTAVE_LOCAL_BUFFER (float, rw, k);
-  F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1,
+  F77_XFCN (cqrinc, CQRINC, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,
                              F77_CONST_CMPLX_ARG (utmp.data ()), rw));
 }
 
@@ -1909,13 +1909,13 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (float, rw, kmax);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (cqrinc, CQRINC, (m, n + ii, std::min (kmax, k + ii),
-                                     F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                                     F77_CMPLX_ARG (m_r.fortran_vec ()), ldr,
+                                     F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                                     F77_CMPLX_ARG (m_r.rwdata ()), ldr,
                                      js_elt + 1,
                                      F77_CONST_CMPLX_ARG (u.column (jsi(i)).data ()),
                                      rw));
@@ -1940,8 +1940,8 @@
   F77_INT ldr = to_f77_int (m_r.rows ());
 
   OCTAVE_LOCAL_BUFFER (float, rw, k);
-  F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1,
+  F77_XFCN (cqrdec, CQRDEC, (m, n, k, F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,
                              rw));
 
   if (k < m)
@@ -1983,13 +1983,13 @@
       F77_INT ldr = to_f77_int (m_r.rows ());
 
       OCTAVE_LOCAL_BUFFER (float, rw, k);
-      for (volatile F77_INT i = 0; i < nj; i++)
+      for (F77_INT i = 0; i < nj; i++)
         {
           F77_INT ii = i;
           F77_INT js_elt = to_f77_int (js(ii));
           F77_XFCN (cqrdec, CQRDEC, (m, n - ii, (k == m ? k : k - ii),
-                                     F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                                     F77_CMPLX_ARG (m_r.fortran_vec ()), ldr,
+                                     F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                                     F77_CMPLX_ARG (m_r.rwdata ()), ldr,
                                      js_elt + 1, rw));
         }
 
@@ -2030,9 +2030,9 @@
 
   FloatComplexRowVector utmp = u;
   OCTAVE_LOCAL_BUFFER (float, rw, k);
-  F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_CMPLX_ARG (m_r.fortran_vec ()), ldr,
-                             j + 1, F77_CMPLX_ARG (utmp.fortran_vec ()),
+  F77_XFCN (cqrinr, CQRINR, (m, n, F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_CMPLX_ARG (m_r.rwdata ()), ldr,
+                             j + 1, F77_CMPLX_ARG (utmp.rwdata ()),
                              rw));
 
 }
@@ -2057,8 +2057,8 @@
 
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, m);
   OCTAVE_LOCAL_BUFFER (float, rw, m);
-  F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_CMPLX_ARG (m_r.fortran_vec ()), ldr, j + 1,
+  F77_XFCN (cqrder, CQRDER, (m, n, F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_CMPLX_ARG (m_r.rwdata ()), ldr, j + 1,
                              F77_CMPLX_ARG (w), rw));
 
   m_q.resize (m - 1, m - 1);
@@ -2086,8 +2086,8 @@
   OCTAVE_LOCAL_BUFFER (FloatComplex, w, k);
   OCTAVE_LOCAL_BUFFER (float, rw, k);
   F77_XFCN (cqrshc, CQRSHC, (m, n, k,
-                             F77_CMPLX_ARG (m_q.fortran_vec ()), ldq,
-                             F77_CMPLX_ARG (m_r.fortran_vec ()), ldr,
+                             F77_CMPLX_ARG (m_q.rwdata ()), ldq,
+                             F77_CMPLX_ARG (m_r.rwdata ()), ldr,
                              i + 1, j + 1, F77_CMPLX_ARG (w), rw));
 }
 
--- a/liboctave/numeric/qr.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/qr.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,8 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-qr
+class qr
 {
 public:
 
--- a/liboctave/numeric/qrp.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/qrp.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include <algorithm>
 
 #include "Array.h"
@@ -54,7 +52,7 @@
 void
 qrp<Matrix>::init (const Matrix& a, type qr_type)
 {
-  assert (qr_type != qr<Matrix>::raw);
+  liboctave_panic_if (qr_type == qr<Matrix>::raw);
 
   F77_INT m = to_f77_int (a.rows ());
   F77_INT n = to_f77_int (a.cols ());
@@ -74,8 +72,8 @@
     {
       // workspace query.
       double rlwork;
-      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (),
-                                 m, jpvt.fortran_vec (), tau,
+      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.rwdata (),
+                                 m, jpvt.rwdata (), tau,
                                  &rlwork, -1, info));
 
       // allocate buffer and do the job.
@@ -83,8 +81,8 @@
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (double, work, lwork);
 
-      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.fortran_vec (),
-                                 m, jpvt.fortran_vec (), tau,
+      F77_XFCN (dgeqp3, DGEQP3, (m, n, afact.rwdata (),
+                                 m, jpvt.rwdata (), tau,
                                  work, lwork, info));
     }
   else
@@ -125,7 +123,7 @@
 void
 qrp<FloatMatrix>::init (const FloatMatrix& a, type qr_type)
 {
-  assert (qr_type != qr<FloatMatrix>::raw);
+  liboctave_panic_if (qr_type == qr<FloatMatrix>::raw);
 
   F77_INT m = to_f77_int (a.rows ());
   F77_INT n = to_f77_int (a.cols ());
@@ -145,8 +143,8 @@
     {
       // workspace query.
       float rlwork;
-      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (),
-                                 m, jpvt.fortran_vec (), tau,
+      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.rwdata (),
+                                 m, jpvt.rwdata (), tau,
                                  &rlwork, -1, info));
 
       // allocate buffer and do the job.
@@ -154,8 +152,8 @@
       lwork = std::max (lwork, static_cast<F77_INT> (1));
       OCTAVE_LOCAL_BUFFER (float, work, lwork);
 
-      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.fortran_vec (),
-                                 m, jpvt.fortran_vec (), tau,
+      F77_XFCN (sgeqp3, SGEQP3, (m, n, afact.rwdata (),
+                                 m, jpvt.rwdata (), tau,
                                  work, lwork, info));
     }
   else
@@ -196,7 +194,7 @@
 void
 qrp<ComplexMatrix>::init (const ComplexMatrix& a, type qr_type)
 {
-  assert (qr_type != qr<ComplexMatrix>::raw);
+  liboctave_panic_if (qr_type == qr<ComplexMatrix>::raw);
 
   F77_INT m = to_f77_int (a.rows ());
   F77_INT n = to_f77_int (a.cols ());
@@ -219,8 +217,8 @@
       // workspace query.
       Complex clwork;
       F77_XFCN (zgeqp3, ZGEQP3, (m, n,
-                                 F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
-                                 m, jpvt.fortran_vec (),
+                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),
+                                 m, jpvt.rwdata (),
                                  F77_DBLE_CMPLX_ARG (tau),
                                  F77_DBLE_CMPLX_ARG (&clwork),
                                  -1, rwork, info));
@@ -231,8 +229,8 @@
       OCTAVE_LOCAL_BUFFER (Complex, work, lwork);
 
       F77_XFCN (zgeqp3, ZGEQP3, (m, n,
-                                 F77_DBLE_CMPLX_ARG (afact.fortran_vec ()),
-                                 m, jpvt.fortran_vec (),
+                                 F77_DBLE_CMPLX_ARG (afact.rwdata ()),
+                                 m, jpvt.rwdata (),
                                  F77_DBLE_CMPLX_ARG (tau),
                                  F77_DBLE_CMPLX_ARG (work),
                                  lwork, rwork, info));
@@ -275,7 +273,7 @@
 void
 qrp<FloatComplexMatrix>::init (const FloatComplexMatrix& a, type qr_type)
 {
-  assert (qr_type != qr<FloatComplexMatrix>::raw);
+  liboctave_panic_if (qr_type == qr<FloatComplexMatrix>::raw);
 
   F77_INT m = to_f77_int (a.rows ());
   F77_INT n = to_f77_int (a.cols ());
@@ -298,8 +296,8 @@
       // workspace query.
       FloatComplex clwork;
       F77_XFCN (cgeqp3, CGEQP3, (m, n,
-                                 F77_CMPLX_ARG (afact.fortran_vec ()),
-                                 m, jpvt.fortran_vec (),
+                                 F77_CMPLX_ARG (afact.rwdata ()),
+                                 m, jpvt.rwdata (),
                                  F77_CMPLX_ARG (tau),
                                  F77_CMPLX_ARG (&clwork),
                                  -1, rwork, info));
@@ -310,8 +308,8 @@
       OCTAVE_LOCAL_BUFFER (FloatComplex, work, lwork);
 
       F77_XFCN (cgeqp3, CGEQP3, (m, n,
-                                 F77_CMPLX_ARG (afact.fortran_vec ()),
-                                 m, jpvt.fortran_vec (),
+                                 F77_CMPLX_ARG (afact.rwdata ()),
+                                 m, jpvt.rwdata (),
                                  F77_CMPLX_ARG (tau),
                                  F77_CMPLX_ARG (work),
                                  lwork, rwork, info));
--- a/liboctave/numeric/qrp.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/qrp.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,8 +36,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-qrp : public qr<T>
+class qrp : public qr<T>
 {
 public:
 
--- a/liboctave/numeric/randgamma.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/randgamma.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -87,6 +87,7 @@
 #include <cmath>
 
 #include "lo-ieee.h"
+#include "lo-mappers.h"
 #include "randgamma.h"
 #include "randmtzig.h"
 
@@ -100,7 +101,7 @@
   const T c = 1./std::sqrt (9.*d);
 
   /* Handle invalid cases */
-  if (a <= 0 || lo_ieee_isinf (a))
+  if (a <= 0 || math::isinf (a))
     {
       for (i=0; i < n; i++)
         r[i] = numeric_limits<T>::NaN ();
--- a/liboctave/numeric/randpoisson.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/randpoisson.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -36,6 +36,7 @@
 #include "f77-fcn.h"
 #include "lo-error.h"
 #include "lo-ieee.h"
+#include "lo-mappers.h"
 #include "randmtzig.h"
 #include "randpoisson.h"
 
@@ -404,7 +405,7 @@
 {
   double L = L_arg;
   octave_idx_type i;
-  if (L < 0.0 || lo_ieee_isinf (L))
+  if (L < 0.0 || math::isinf (L))
     {
       for (i=0; i<n; i++)
         p[i] = numeric_limits<T>::NaN ();
@@ -461,7 +462,7 @@
       /* numerical recipes */
       poisson_rejection<T> (L, &ret, 1);
     }
-  else if (lo_ieee_isinf (L))
+  else if (math::isinf (L))
     {
       /* FIXME: R uses NaN, but the normal approximation suggests that
        * limit should be Inf.  Which is correct? */
--- a/liboctave/numeric/schur.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/schur.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -133,7 +133,7 @@
       || ord_char == 'a' || ord_char == 'd')
     sort = 'S';
 
-  volatile double_selector selector = nullptr;
+  double_selector selector = nullptr;
   if (ord_char == 'A' || ord_char == 'a')
     selector = select_ana;
   else if (ord_char == 'D' || ord_char == 'd')
@@ -152,25 +152,25 @@
   if (calc_unitary)
     m_unitary_schur_mat.clear (n, n);
 
-  double *s = m_schur_mat.fortran_vec ();
-  double *q = m_unitary_schur_mat.fortran_vec ();
+  double *s = m_schur_mat.rwdata ();
+  double *q = m_unitary_schur_mat.rwdata ();
 
   Array<double> wr (dim_vector (n, 1));
-  double *pwr = wr.fortran_vec ();
+  double *pwr = wr.rwdata ();
 
   Array<double> wi (dim_vector (n, 1));
-  double *pwi = wi.fortran_vec ();
+  double *pwi = wi.rwdata ();
 
   Array<double> work (dim_vector (lwork, 1));
-  double *pwork = work.fortran_vec ();
+  double *pwork = work.rwdata ();
 
   // BWORK is not referenced for the non-ordered Schur routine.
   F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
   Array<F77_INT> bwork (dim_vector (ntmp, 1));
-  F77_INT *pbwork = bwork.fortran_vec ();
+  F77_INT *pbwork = bwork.rwdata ();
 
   Array<F77_INT> iwork (dim_vector (liwork, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_XFCN (dgeesx, DGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
                              F77_CONST_CHAR_ARG2 (&sort, 1),
@@ -221,7 +221,7 @@
       || ord_char == 'a' || ord_char == 'd')
     sort = 'S';
 
-  volatile float_selector selector = nullptr;
+  float_selector selector = nullptr;
   if (ord_char == 'A' || ord_char == 'a')
     selector = select_ana;
   else if (ord_char == 'D' || ord_char == 'd')
@@ -240,25 +240,25 @@
   if (calc_unitary)
     m_unitary_schur_mat.clear (n, n);
 
-  float *s = m_schur_mat.fortran_vec ();
-  float *q = m_unitary_schur_mat.fortran_vec ();
+  float *s = m_schur_mat.rwdata ();
+  float *q = m_unitary_schur_mat.rwdata ();
 
   Array<float> wr (dim_vector (n, 1));
-  float *pwr = wr.fortran_vec ();
+  float *pwr = wr.rwdata ();
 
   Array<float> wi (dim_vector (n, 1));
-  float *pwi = wi.fortran_vec ();
+  float *pwi = wi.rwdata ();
 
   Array<float> work (dim_vector (lwork, 1));
-  float *pwork = work.fortran_vec ();
+  float *pwork = work.rwdata ();
 
   // BWORK is not referenced for the non-ordered Schur routine.
   F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
   Array<F77_INT> bwork (dim_vector (ntmp, 1));
-  F77_INT *pbwork = bwork.fortran_vec ();
+  F77_INT *pbwork = bwork.rwdata ();
 
   Array<F77_INT> iwork (dim_vector (liwork, 1));
-  F77_INT *piwork = iwork.fortran_vec ();
+  F77_INT *piwork = iwork.rwdata ();
 
   F77_XFCN (sgeesx, SGEESX, (F77_CONST_CHAR_ARG2 (&jobvs, 1),
                              F77_CONST_CHAR_ARG2 (&sort, 1),
@@ -309,7 +309,7 @@
       || ord_char == 'a' || ord_char == 'd')
     sort = 'S';
 
-  volatile complex_selector selector = nullptr;
+  complex_selector selector = nullptr;
   if (ord_char == 'A' || ord_char == 'a')
     selector = select_ana;
   else if (ord_char == 'D' || ord_char == 'd')
@@ -326,22 +326,22 @@
   if (calc_unitary)
     m_unitary_schur_mat.clear (n, n);
 
-  Complex *s = m_schur_mat.fortran_vec ();
-  Complex *q = m_unitary_schur_mat.fortran_vec ();
+  Complex *s = m_schur_mat.rwdata ();
+  Complex *q = m_unitary_schur_mat.rwdata ();
 
   Array<double> rwork (dim_vector (n, 1));
-  double *prwork = rwork.fortran_vec ();
+  double *prwork = rwork.rwdata ();
 
   Array<Complex> w (dim_vector (n, 1));
-  Complex *pw = w.fortran_vec ();
+  Complex *pw = w.rwdata ();
 
   Array<Complex> work (dim_vector (lwork, 1));
-  Complex *pwork = work.fortran_vec ();
+  Complex *pwork = work.rwdata ();
 
   // BWORK is not referenced for non-ordered Schur.
   F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
   Array<F77_INT> bwork (dim_vector (ntmp, 1));
-  F77_INT *pbwork = bwork.fortran_vec ();
+  F77_INT *pbwork = bwork.rwdata ();
 
   F77_XFCN (zgeesx, ZGEESX,
             (F77_CONST_CHAR_ARG2 (&jobvs, 1),
@@ -377,8 +377,8 @@
       OCTAVE_LOCAL_BUFFER (double, sx, n-1);
 
       F77_XFCN (zrsf2csf, ZRSF2CSF,
-                (n, F77_DBLE_CMPLX_ARG (s.fortran_vec ()),
-                 F77_DBLE_CMPLX_ARG (u.fortran_vec ()), c, sx));
+                (n, F77_DBLE_CMPLX_ARG (s.rwdata ()),
+                 F77_DBLE_CMPLX_ARG (u.rwdata ()), c, sx));
     }
 
   return schur<ComplexMatrix> (s, u);
@@ -420,7 +420,7 @@
       || ord_char == 'a' || ord_char == 'd')
     sort = 'S';
 
-  volatile float_complex_selector selector = nullptr;
+  float_complex_selector selector = nullptr;
   if (ord_char == 'A' || ord_char == 'a')
     selector = select_ana;
   else if (ord_char == 'D' || ord_char == 'd')
@@ -437,22 +437,22 @@
   if (calc_unitary)
     m_unitary_schur_mat.clear (n, n);
 
-  FloatComplex *s = m_schur_mat.fortran_vec ();
-  FloatComplex *q = m_unitary_schur_mat.fortran_vec ();
+  FloatComplex *s = m_schur_mat.rwdata ();
+  FloatComplex *q = m_unitary_schur_mat.rwdata ();
 
   Array<float> rwork (dim_vector (n, 1));
-  float *prwork = rwork.fortran_vec ();
+  float *prwork = rwork.rwdata ();
 
   Array<FloatComplex> w (dim_vector (n, 1));
-  FloatComplex *pw = w.fortran_vec ();
+  FloatComplex *pw = w.rwdata ();
 
   Array<FloatComplex> work (dim_vector (lwork, 1));
-  FloatComplex *pwork = work.fortran_vec ();
+  FloatComplex *pwork = work.rwdata ();
 
   // BWORK is not referenced for non-ordered Schur.
   F77_INT ntmp = (ord_char == 'N' || ord_char == 'n') ? 0 : n;
   Array<F77_INT> bwork (dim_vector (ntmp, 1));
-  F77_INT *pbwork = bwork.fortran_vec ();
+  F77_INT *pbwork = bwork.rwdata ();
 
   F77_XFCN (cgeesx, CGEESX,
             (F77_CONST_CHAR_ARG2 (&jobvs, 1),
@@ -490,8 +490,8 @@
       OCTAVE_LOCAL_BUFFER (float, sx, n-1);
 
       F77_XFCN (crsf2csf, CRSF2CSF,
-                (n, F77_CMPLX_ARG (s.fortran_vec ()),
-                 F77_CMPLX_ARG (u.fortran_vec ()), c, sx));
+                (n, F77_CMPLX_ARG (s.rwdata ()),
+                 F77_CMPLX_ARG (u.rwdata ()), c, sx));
     }
 
   return schur<FloatComplexMatrix> (s, u);
--- a/liboctave/numeric/schur.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/schur.h	Fri Apr 12 15:10:26 2024 +0200
@@ -42,8 +42,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-schur
+class schur
 {
 public:
 
--- a/liboctave/numeric/sparse-chol.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-chol.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -211,7 +211,7 @@
 sparse_chol<chol_type>::sparse_chol_rep::init (const chol_type& a,
     bool natural, bool force)
 {
-  volatile octave_idx_type info = 0;
+  octave_idx_type info = 0;
 
 #if defined (HAVE_CHOLMOD)
 
--- a/liboctave/numeric/sparse-chol.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-chol.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,9 +44,7 @@
 // of the matrix type.
 
 template <typename chol_type>
-class
-OCTAVE_API
-sparse_chol
+class OCTAVE_API sparse_chol
 {
 public:
 
--- a/liboctave/numeric/sparse-dmsolve.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-dmsolve.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -173,7 +173,7 @@
 dmsolve_insert (MArray<T>& a, const MArray<T>& b, const octave_idx_type *Q,
                 octave_idx_type r, octave_idx_type c)
 {
-  T *ax = a.fortran_vec ();
+  T *ax = a.rwdata ();
 
   const T *bx = b.data ();
 
@@ -299,7 +299,7 @@
 
   a.resize (dim_vector (b_nr, b_nc));
 
-  RT *Btx = a.fortran_vec ();
+  RT *Btx = a.rwdata ();
 
   for (octave_idx_type j = 0; j < b_nc; j++)
     {
--- a/liboctave/numeric/sparse-lu.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-lu.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -415,7 +415,7 @@
 
   // Setup the control parameters
   Matrix Control (UMFPACK_CONTROL, 1);
-  double *control = Control.fortran_vec ();
+  double *control = Control.rwdata ();
   umfpack_defaults<lu_elt_type> (control);
 
   double tmp = sparse_params::get_key ("spumoni");
@@ -466,7 +466,7 @@
 
   void *Symbolic;
   Matrix Info (1, UMFPACK_INFO);
-  double *info = Info.fortran_vec ();
+  double *info = Info.rwdata ();
   int status = umfpack_qsymbolic<lu_elt_type> (nr, nc, Ap, Ai, Ax, nullptr,
                &Symbolic, control, info);
 
@@ -552,10 +552,10 @@
               double *Rx = m_R.data ();
 
               m_P.resize (dim_vector (nr, 1));
-              octave_idx_type *p = m_P.fortran_vec ();
+              octave_idx_type *p = m_P.rwdata ();
 
               m_Q.resize (dim_vector (nc, 1));
-              octave_idx_type *q = m_Q.fortran_vec ();
+              octave_idx_type *q = m_Q.rwdata ();
 
               octave_idx_type do_recip;
               status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,
@@ -633,7 +633,7 @@
 
   // Setup the control parameters
   Matrix Control (UMFPACK_CONTROL, 1);
-  double *control = Control.fortran_vec ();
+  double *control = Control.rwdata ();
   umfpack_defaults<lu_elt_type> (control);
 
   double tmp = sparse_params::get_key ("spumoni");
@@ -691,7 +691,7 @@
 
   void *Symbolic;
   Matrix Info (1, UMFPACK_INFO);
-  double *info = Info.fortran_vec ();
+  double *info = Info.rwdata ();
   int status;
 
   // Null loop so that qinit is immediately deallocated when not needed
@@ -790,10 +790,10 @@
               double *Rx = m_R.data ();
 
               m_P.resize (dim_vector (nr, 1));
-              octave_idx_type *p = m_P.fortran_vec ();
+              octave_idx_type *p = m_P.rwdata ();
 
               m_Q.resize (dim_vector (nc, 1));
-              octave_idx_type *q = m_Q.fortran_vec ();
+              octave_idx_type *q = m_Q.rwdata ();
 
               octave_idx_type do_recip;
               status = umfpack_get_numeric<lu_elt_type> (Ltp, Ltj, Ltx,
--- a/liboctave/numeric/sparse-lu.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-lu.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,9 +44,7 @@
 // of the matrix type.
 
 template <typename lu_type>
-class
-OCTAVE_API
-sparse_lu
+class OCTAVE_API sparse_lu
 {
 public:
 
--- a/liboctave/numeric/sparse-qr.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-qr.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -43,15 +43,22 @@
 
 OCTAVE_BEGIN_NAMESPACE(math)
 
+#if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
+// Decide once at runtime whether Octave must workaround SuiteSparse library.
+static constexpr bool octave_suitesparse_ptr_size_mismatch
+  = (sizeof (octave_idx_type) != sizeof (SuiteSparse_long));
+
+static constexpr bool suitesparse_integer_long_mismatch
+  = (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long));
+#endif
+
 #if defined (HAVE_CXSPARSE)
 template <typename SPARSE_T>
-class
-cxsparse_types
+class cxsparse_types
 { };
 
 template <>
-class
-cxsparse_types<SparseMatrix>
+class cxsparse_types<SparseMatrix>
 {
 public:
   typedef CXSPARSE_DNAME (s) symbolic_type;
@@ -59,8 +66,7 @@
 };
 
 template <>
-class
-cxsparse_types<SparseComplexMatrix>
+class cxsparse_types<SparseComplexMatrix>
 {
 public:
   typedef CXSPARSE_ZNAME (s) symbolic_type;
@@ -219,10 +225,10 @@
 
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
-// Convert real sparse octave matrix to real sparse cholmod matrix.
+// Convert octave real sparse matrix to cholmod real sparse matrix.
 // Returns a "shallow" copy of a.
 static cholmod_sparse
-ros2rcs (const SparseMatrix& a)
+ors2crs (const SparseMatrix& a)
 {
   cholmod_sparse A;
 
@@ -240,7 +246,7 @@
   A.dtype = CHOLMOD_DOUBLE;
   A.nz = nullptr;
   A.z = nullptr;
-  if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long))
+  if (! octave_suitesparse_ptr_size_mismatch)
     {
       A.p = reinterpret_cast<SuiteSparse_long *> (a.cidx ());
       A.i = reinterpret_cast<SuiteSparse_long *> (a.ridx ());
@@ -263,10 +269,10 @@
   return A;
 }
 
-// Convert complex sparse octave matrix to complex sparse cholmod matrix.
+// Convert octave complex sparse matrix to cholmod complex sparse matrix.
 // Returns a "shallow" copy of a.
 static cholmod_sparse
-cos2ccs (const SparseComplexMatrix& a)
+ocs2ccs (const SparseComplexMatrix& a)
 {
   cholmod_sparse A;
 
@@ -284,7 +290,7 @@
   A.dtype = CHOLMOD_DOUBLE;
   A.nz = nullptr;
   A.z = nullptr;
-  if (sizeof (octave_idx_type) == sizeof (SuiteSparse_long))
+  if (! octave_suitesparse_ptr_size_mismatch)
     {
       A.p = reinterpret_cast<SuiteSparse_long *> (a.cidx ());
       A.i = reinterpret_cast<SuiteSparse_long *> (a.ridx ());
@@ -308,10 +314,10 @@
   return A;
 }
 
-// Convert real dense octave matrix to complex dense cholmod matrix.
+// Convert octave real dense matrix to cholmod complex dense matrix.
 // Returns a "deep" copy of a.
 static cholmod_dense *
-rod2ccd (const MArray<double>& a, cholmod_common *cc1)
+ord2ccd (const MArray<double>& a, cholmod_common *cc1)
 {
   cholmod_dense *A
     = cholmod_l_allocate_dense (a.rows (), a.cols (), a.rows(),
@@ -326,10 +332,10 @@
   return A;
 }
 
-// Convert real dense octave matrix to real dense cholmod matrix.
+// Convert octave real dense matrix to cholmod real dense matrix.
 // Returns a "shallow" copy of a.
 static cholmod_dense
-rod2rcd (const MArray<double>& a)
+ord2crd (const MArray<double>& a)
 {
   cholmod_dense A;
 
@@ -345,10 +351,10 @@
   return A;
 }
 
-// Convert complex dense octave matrix to complex dense cholmod matrix.
+// Convert octave complex dense matrix to cholmod complex dense matrix.
 // Returns a "shallow" copy of a.
 static cholmod_dense
-cod2ccd (const ComplexMatrix& a)
+ocd2ccd (const ComplexMatrix& a)
 {
   cholmod_dense A;
 
@@ -364,10 +370,10 @@
   return A;
 }
 
-// Convert real sparse cholmod matrix to real sparse octave matrix.
+// Convert cholmod real sparse matrix to octave real sparse matrix.
 // Returns a "shallow" copy of y.
 static SparseMatrix
-rcs2ros (cholmod_sparse *y, const cholmod_common *cc1)
+crs2ors (cholmod_sparse *y, const cholmod_common *cc1)
 {
   octave_idx_type nrow = from_size_t (y->nrow);
   octave_idx_type ncol = from_size_t (y->ncol);
@@ -391,10 +397,10 @@
   return ret;
 }
 
-// Convert complex sparse cholmod matrix to complex sparse octave matrix.
+// Convert cholmod complex sparse matrix to octave complex sparse matrix.
 // Returns a "deep" copy of a.
 static SparseComplexMatrix
-ccs2cos (cholmod_sparse *a, cholmod_common *cc1)
+ccs2ocs (cholmod_sparse *a, cholmod_common *cc1)
 {
   octave_idx_type nrow = from_size_t (a->nrow);
   octave_idx_type ncol = from_size_t (a->ncol);
@@ -416,10 +422,10 @@
   return ret;
 }
 
-// Convert real sparse octave matrix to complex sparse cholmod matrix.
+// Convert octave real sparse matrix to cholmod complex sparse matrix.
 // Returns a "deep" copy of a.
 static cholmod_sparse *
-ros2ccs (const SparseMatrix& a, cholmod_common *cc)
+ors2ccs (const SparseMatrix& a, cholmod_common *cc)
 {
   cholmod_sparse *A
     = cholmod_l_allocate_sparse (a.rows (), a.cols (), a.nnz (), 0, 1, 0,
@@ -516,14 +522,14 @@
       ("ordering %d is not supported by SPQR", order);
 
   cholmod_l_start (&m_cc);
-  cholmod_sparse A = ros2rcs (a);
+  cholmod_sparse A = ors2crs (a);
 
   SuiteSparseQR<double> (order, static_cast<double> (SPQR_DEFAULT_TOL),
                          static_cast<SuiteSparse_long> (A.nrow),
                          &A, &m_R, &m_E, &m_H, &m_HPinv, &m_Htau, &m_cc);
   spqr_error_handler (&m_cc);
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -593,7 +599,7 @@
 {
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
 
-  return rcs2ros (m_H, &m_cc);
+  return crs2ors (m_H, &m_cc);
 
 #elif defined (HAVE_CXSPARSE)
 
@@ -712,7 +718,7 @@
       ("sparse_qr: matrix dimension with negative size");
 
   cholmod_dense *QTB;  // Q' * B
-  cholmod_dense B = rod2rcd (b);
+  cholmod_dense B = ord2crd (b);
 
   QTB = SuiteSparseQR_qmult<double> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B,
                                      &m_cc);
@@ -720,7 +726,7 @@
 
   // copy QTB into ret
   double *QTB_x = reinterpret_cast<double *> (QTB->x);
-  double *ret_vec = reinterpret_cast<double *> (ret.fortran_vec ());
+  double *ret_vec = reinterpret_cast<double *> (ret.rwdata ());
   for (octave_idx_type j = 0; j < b_nc; j++)
     for (octave_idx_type i = 0; i < nr; i++)
       ret_vec[j * nr + i] = QTB_x[j * b_nr + i];
@@ -744,7 +750,7 @@
   const double *bvec = b.data ();
 
   Matrix ret (b_nr, b_nc);
-  double *vec = ret.fortran_vec ();
+  double *vec = ret.rwdata ();
 
   if (nr < 0 || nc < 0 || nr != b_nr)
     (*current_liboctave_error_handler) ("matrix dimension mismatch");
@@ -755,7 +761,7 @@
     {
       OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-      for (volatile octave_idx_type j = 0, idx = 0;
+      for (octave_idx_type j = 0, idx = 0;
            j < b_nc;
            j++, idx += b_nr)
         {
@@ -764,11 +770,11 @@
           for (octave_idx_type i = nr; i < S->m2; i++)
             buf[i] = 0.;
 
-          volatile octave_idx_type nm = (nr < nc ? nr : nc);
+          octave_idx_type nm = (nr < nc ? nr : nc);
 
           CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + idx, buf, b_nr);
 
-          for (volatile octave_idx_type i = 0; i < nm; i++)
+          for (octave_idx_type i = 0; i < nm; i++)
             {
               octave_quit ();
 
@@ -819,7 +825,7 @@
   spqr_error_handler (&m_cc);
 
   double *q_x = reinterpret_cast<double *> (q->x);
-  double *ret_vec = const_cast<double *> (ret.fortran_vec ());
+  double *ret_vec = const_cast<double *> (ret.rwdata ());
   for (octave_idx_type j = 0; j < nc; j++)
     for (octave_idx_type i = 0; i < nrows; i++)
       ret_vec[j * nrows + i] = q_x[j * nrows + i];
@@ -838,7 +844,7 @@
   octave_idx_type nc = N->L->n;
   octave_idx_type nr = nrows;
   Matrix ret (nr, nr);
-  double *ret_vec = ret.fortran_vec ();
+  double *ret_vec = ret.rwdata ();
 
   if (nr < 0 || nc < 0)
     (*current_liboctave_error_handler) ("matrix dimension mismatch");
@@ -854,7 +860,7 @@
 
       OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-      for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx += nr)
+      for (octave_idx_type j = 0, idx = 0; j < nr; j++, idx += nr)
         {
           octave_quit ();
 
@@ -862,11 +868,11 @@
           for (octave_idx_type i = nr; i < S->m2; i++)
             buf[i] = 0.;
 
-          volatile octave_idx_type nm = (nr < nc ? nr : nc);
+          octave_idx_type nm = (nr < nc ? nr : nc);
 
           CXSPARSE_DNAME (_ipvec) (S->pinv, bvec, buf, nr);
 
-          for (volatile octave_idx_type i = 0; i < nm; i++)
+          for (octave_idx_type i = 0; i < nm; i++)
             {
               octave_quit ();
 
@@ -913,12 +919,11 @@
     (*current_liboctave_error_handler) ("matrix dimension mismatch");
 
   cholmod_dense *QTB;  // Q' * B
-  cholmod_dense B = rod2rcd (b);
+  cholmod_dense B = ord2crd (b);
 
   // FIXME: Process b column by column as in the CXSPARSE version below.
   // This avoids a large dense matrix Q' * B in memory.
-  QTB = SuiteSparseQR_qmult<double> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B,
-                                     &m_cc);
+  QTB = SuiteSparseQR_qmult<double> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B, &m_cc);
 
   spqr_error_handler (&m_cc);
 
@@ -930,7 +935,7 @@
   R2.x = reinterpret_cast<double *> (m_R->x);
   suitesparse_integer *R2_p;
   suitesparse_integer *R2_i;
-  if (sizeof (suitesparse_integer) == sizeof (SuiteSparse_long))
+  if (! suitesparse_integer_long_mismatch)
     {
       R2.p = reinterpret_cast<suitesparse_integer *> (m_R->p);
       R2.i = reinterpret_cast<suitesparse_integer *> (m_R->i);
@@ -950,9 +955,9 @@
       R2.i = R2_i;
     }
   R2.nz = -1;
-  double *x_vec = const_cast<double *> (x.fortran_vec ());
+  double *x_vec = const_cast<double *> (x.rwdata ());
   suitesparse_integer *E;
-  if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long))
+  if (suitesparse_integer_long_mismatch)
     {
       E = new suitesparse_integer [ncols];
       for (octave_idx_type i = 0; i < ncols; i++)
@@ -960,7 +965,7 @@
     }
   else
     E = reinterpret_cast<suitesparse_integer *> (m_E);
-  for (volatile octave_idx_type j = 0; j < b_nc; j++)
+  for (octave_idx_type j = 0; j < b_nc; j++)
     {
       // fill x(:,j)
       // solve (m_R\(Q'*B(:,j)) and store result in QTB(:,j)
@@ -972,7 +977,7 @@
        &x_vec[j * ncols], ncols);
     }
 
-  if (sizeof (suitesparse_integer) != sizeof (SuiteSparse_long))
+  if (suitesparse_integer_long_mismatch)
     {
       delete [] R2_p;
       delete [] R2_i;
@@ -995,11 +1000,11 @@
   const double *bvec = b.data ();
 
   Matrix x (nc, b_nc);
-  double *vec = x.fortran_vec ();
+  double *vec = x.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
+  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
        i++, idx+=nc, bidx+=b_nr)
     {
       octave_quit ();
@@ -1009,7 +1014,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1054,13 +1059,13 @@
   const double *bvec = b.data ();
 
   Matrix x (nc, b_nc);
-  double *vec = x.fortran_vec ();
-
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  double *vec = x.rwdata ();
+
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
 
-  for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
+  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
        i++, idx+=nc, bidx+=b_nr)
     {
       octave_quit ();
@@ -1071,7 +1076,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, bvec + bidx, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -1112,13 +1117,13 @@
   SparseMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1130,7 +1135,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1198,14 +1203,14 @@
   SparseMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1218,7 +1223,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -1282,13 +1287,13 @@
   octave_idx_type b_nr = b.rows ();
 
   ComplexMatrix x (nc, b_nc);
-  Complex *vec = x.fortran_vec ();
+  Complex *vec = x.rwdata ();
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1304,7 +1309,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1319,7 +1324,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1366,15 +1371,15 @@
   octave_idx_type b_nr = b.rows ();
 
   ComplexMatrix x (nc, b_nc);
-  Complex *vec = x.fortran_vec ();
-
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  Complex *vec = x.rwdata ();
+
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1391,7 +1396,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -1406,7 +1411,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -1454,7 +1459,7 @@
       ("ordering %d is not supported by SPQR", order);
 
   cholmod_l_start (&m_cc);
-  cholmod_sparse A = cos2ccs (a);
+  cholmod_sparse A = ocs2ccs (a);
 
   SuiteSparseQR<Complex> (order, static_cast<double> (SPQR_DEFAULT_TOL),
                           static_cast<SuiteSparse_long> (A.nrow),
@@ -1462,7 +1467,7 @@
                           &m_HPinv, &m_Htau, &m_cc);
   spqr_error_handler (&m_cc);
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -1651,7 +1656,7 @@
       ("matrix dimension with negative size");
 
   cholmod_dense *QTB;  // Q' * B
-  cholmod_dense B = cod2ccd (b);
+  cholmod_dense B = ocd2ccd (b);
 
   QTB = SuiteSparseQR_qmult<Complex> (SPQR_QTX, m_H, m_Htau, m_HPinv, &B,
                                       &m_cc);
@@ -1659,7 +1664,7 @@
 
   // copy QTB into ret
   Complex *QTB_x = reinterpret_cast<Complex *> (QTB->x);
-  Complex *ret_vec = reinterpret_cast<Complex *> (ret.fortran_vec ());
+  Complex *ret_vec = reinterpret_cast<Complex *> (ret.rwdata ());
   for (octave_idx_type j = 0; j < b_nc; j++)
     for (octave_idx_type i = 0; i < nr; i++)
       ret_vec[j * nr + i] = QTB_x[j * b_nr + i];
@@ -1681,7 +1686,7 @@
   const cs_complex_t *bvec
     = reinterpret_cast<const cs_complex_t *> (b.data ());
   ComplexMatrix ret (b_nr, b_nc);
-  Complex *vec = ret.fortran_vec ();
+  Complex *vec = ret.rwdata ();
 
   if (nr < 0 || nc < 0 || nr != b_nr)
     (*current_liboctave_error_handler) ("matrix dimension mismatch");
@@ -1692,19 +1697,19 @@
     {
       OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2);
 
-      for (volatile octave_idx_type j = 0, idx = 0;
+      for (octave_idx_type j = 0, idx = 0;
            j < b_nc;
            j++, idx += b_nr)
         {
           octave_quit ();
 
-          volatile octave_idx_type nm = (nr < nc ? nr : nc);
+          octave_idx_type nm = (nr < nc ? nr : nc);
 
           CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + idx,
                                    reinterpret_cast<cs_complex_t *> (buf),
                                    b_nr);
 
-          for (volatile octave_idx_type i = 0; i < nm; i++)
+          for (octave_idx_type i = 0; i < nm; i++)
             {
               octave_quit ();
 
@@ -1757,7 +1762,7 @@
   spqr_error_handler (&m_cc);
 
   Complex *q_x = reinterpret_cast<Complex *> (q->x);
-  Complex *ret_vec = const_cast<Complex *> (ret.fortran_vec ());
+  Complex *ret_vec = const_cast<Complex *> (ret.rwdata ());
 
   for (octave_idx_type j = 0; j < nc; j++)
     for (octave_idx_type i = 0; i < nrows; i++)
@@ -1777,7 +1782,7 @@
   octave_idx_type nc = N->L->n;
   octave_idx_type nr = nrows;
   ComplexMatrix ret (nr, nr);
-  Complex *vec = ret.fortran_vec ();
+  Complex *vec = ret.rwdata ();
 
   if (nr < 0 || nc < 0)
     (*current_liboctave_error_handler) ("matrix dimension mismatch");
@@ -1793,19 +1798,19 @@
 
       OCTAVE_LOCAL_BUFFER (Complex, buf, S->m2);
 
-      for (volatile octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr)
+      for (octave_idx_type j = 0, idx = 0; j < nr; j++, idx+=nr)
         {
           octave_quit ();
 
           bvec[j] = 1.0;
 
-          volatile octave_idx_type nm = (nr < nc ? nr : nc);
+          octave_idx_type nm = (nr < nc ? nr : nc);
 
           CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec,
                                    reinterpret_cast<cs_complex_t *> (buf),
                                    nr);
 
-          for (volatile octave_idx_type i = 0; i < nm; i++)
+          for (octave_idx_type i = 0; i < nm; i++)
             {
               octave_quit ();
 
@@ -1851,14 +1856,14 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1874,7 +1879,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, Xx, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1889,7 +1894,7 @@
 
       CXSPARSE_DNAME (_ipvec) (S->pinv, Xz, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -1958,15 +1963,15 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (double, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, Xz, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (double, buf, nbuf);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -1983,7 +1988,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, Xx, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -1998,7 +2003,7 @@
       CXSPARSE_DNAME (_pvec) (S->q, Xz, buf, nr);
       CXSPARSE_DNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -2063,12 +2068,12 @@
   octave_idx_type b_nr = b.rows ();
 
   ComplexMatrix x (nc, b_nc);
-  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.fortran_vec ());
+  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());
 
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);
   OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2082,7 +2087,7 @@
                                reinterpret_cast<cs_complex_t *> (Xx),
                                buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -2127,9 +2132,9 @@
   octave_idx_type b_nr = b.rows ();
 
   ComplexMatrix x (nc, b_nc);
-  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.fortran_vec ());
-
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());
+
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);
   OCTAVE_LOCAL_BUFFER (Complex, Xx, b_nr);
@@ -2138,7 +2143,7 @@
   for (octave_idx_type i = 0; i < nr; i++)
     B[i] = N->B[i];
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2152,7 +2157,7 @@
                               buf, nr);
       CXSPARSE_ZNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -2195,13 +2200,13 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
 
   OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2215,7 +2220,7 @@
                                reinterpret_cast<cs_complex_t *> (Xx),
                                buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -2288,9 +2293,9 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);
@@ -2299,7 +2304,7 @@
   for (octave_idx_type i = 0; i < nr; i++)
     B[i] = N->B[i];
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2314,7 +2319,7 @@
                               buf, nr);
       CXSPARSE_ZNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -2385,11 +2390,11 @@
 
   ComplexMatrix x (nc, b_nc);
   cs_complex_t *vec = reinterpret_cast<cs_complex_t *>
-                      (x.fortran_vec ());
+                      (x.rwdata ());
 
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
+  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
        i++, idx+=nc, bidx+=b_nr)
     {
       octave_quit ();
@@ -2399,7 +2404,7 @@
 
       CXSPARSE_ZNAME (_ipvec) (S->pinv, bvec + bidx, buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -2447,9 +2452,9 @@
                              (b.data ());
 
   ComplexMatrix x (nc, b_nc);
-  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.fortran_vec ());
-
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  cs_complex_t *vec = reinterpret_cast<cs_complex_t *> (x.rwdata ());
+
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);
   OCTAVE_LOCAL_BUFFER (double, B, nr);
@@ -2457,7 +2462,7 @@
   for (octave_idx_type i = 0; i < nr; i++)
     B[i] = N->B[i];
 
-  for (volatile octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
+  for (octave_idx_type i = 0, idx = 0, bidx = 0; i < b_nc;
        i++, idx+=nc, bidx+=b_nr)
     {
       octave_quit ();
@@ -2468,7 +2473,7 @@
       CXSPARSE_ZNAME (_pvec) (S->q, bvec + bidx, buf, nr);
       CXSPARSE_ZNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -2511,13 +2516,13 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
 
   OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, S->m2);
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2531,7 +2536,7 @@
                                reinterpret_cast<cs_complex_t *> (Xx),
                                buf, nr);
 
-      for (volatile octave_idx_type j = 0; j < nc; j++)
+      for (octave_idx_type j = 0; j < nc; j++)
         {
           octave_quit ();
 
@@ -2604,9 +2609,9 @@
   SparseComplexMatrix x (nc, b_nc, b.nnz ());
   x.xcidx (0) = 0;
 
-  volatile octave_idx_type x_nz = b.nnz ();
-  volatile octave_idx_type ii = 0;
-  volatile octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
+  octave_idx_type x_nz = b.nnz ();
+  octave_idx_type ii = 0;
+  octave_idx_type nbuf = (nc > S->m2 ? nc : S->m2);
 
   OCTAVE_LOCAL_BUFFER (Complex, Xx, (b_nr > nc ? b_nr : nc));
   OCTAVE_LOCAL_BUFFER (cs_complex_t, buf, nbuf);
@@ -2615,7 +2620,7 @@
   for (octave_idx_type i = 0; i < nr; i++)
     B[i] = N->B[i];
 
-  for (volatile octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
+  for (octave_idx_type i = 0, idx = 0; i < b_nc; i++, idx+=nc)
     {
       octave_quit ();
 
@@ -2629,7 +2634,7 @@
                               buf, nr);
       CXSPARSE_ZNAME (_utsolve) (N->U, buf);
 
-      for (volatile octave_idx_type j = nr-1; j >= 0; j--)
+      for (octave_idx_type j = nr-1; j >= 0; j--)
         {
           octave_quit ();
 
@@ -2774,19 +2779,19 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = ros2rcs (a);
-  cholmod_dense B = rod2rcd (b);
+  cholmod_sparse A = ors2crs (a);
+  cholmod_dense B = ord2crd (b);
   cholmod_dense *X;
 
   X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);
   spqr_error_handler (&cc);
 
-  double *xdata = x.fortran_vec ();
-  for (volatile octave_idx_type i = 0; i < nc * b_nc; i++)
+  double *xdata = x.rwdata ();
+  for (octave_idx_type i = 0; i < nc * b_nc; i++)
     xdata[i] = reinterpret_cast<double *> (X->x)[i];
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -2809,17 +2814,17 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = ros2rcs (a);
-  cholmod_sparse B = ros2rcs (b);
+  cholmod_sparse A = ors2crs (a);
+  cholmod_sparse B = ors2crs (b);
   cholmod_sparse *X;
 
   X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);
   spqr_error_handler (&cc);
 
-  x = rcs2ros (X, &cc);
+  x = crs2ors (X, &cc);
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -2846,15 +2851,15 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse *A = ros2ccs (a, &cc);
-  cholmod_dense B = cod2ccd (b);
+  cholmod_sparse *A = ors2ccs (a, &cc);
+  cholmod_dense B = ocd2ccd (b);
   cholmod_dense *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc);
   spqr_error_handler (&cc);
 
-  Complex *xdata = x.fortran_vec ();
-  for (volatile octave_idx_type i = 0; i < nc * b_nc; i++)
+  Complex *xdata = x.rwdata ();
+  for (octave_idx_type i = 0; i < nc * b_nc; i++)
     xdata[i] = reinterpret_cast<Complex *> (X->x)[i];
   info = 0;
 
@@ -2876,17 +2881,17 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse *A = ros2ccs (a, &cc);
-  cholmod_sparse B = cos2ccs (b);
+  cholmod_sparse *A = ors2ccs (a, &cc);
+  cholmod_sparse B = ocs2ccs (b);
   cholmod_sparse *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc);
   spqr_error_handler (&cc);
 
-  SparseComplexMatrix ret = ccs2cos (X, &cc);
+  SparseComplexMatrix ret = ccs2ocs (X, &cc);
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (B.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (B.i);
@@ -2912,19 +2917,19 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = cos2ccs (a);
-  cholmod_dense B = cod2ccd (b);
+  cholmod_sparse A = ocs2ccs (a);
+  cholmod_dense B = ocd2ccd (b);
   cholmod_dense *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);
   spqr_error_handler (&cc);
 
-  Complex *xdata = x.fortran_vec ();
-  for (volatile octave_idx_type i = 0; i < nc * b_nc; i++)
+  Complex *xdata = x.rwdata ();
+  for (octave_idx_type i = 0; i < nc * b_nc; i++)
     xdata[i] = reinterpret_cast<Complex *> (X->x)[i];
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -2937,6 +2942,8 @@
 
 // FIXME: 2024/01/07: This template specialization does not appear to be
 // reachable from current Octave code calling qrsolve from sparse-dmsolve.cc.
+// It remains because liboctave may be used by other C++ code besides the
+// Octave interpreter.
 template <>
 template <>
 OCTAVE_API ComplexMatrix
@@ -2951,19 +2958,19 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = cos2ccs (a);
-  cholmod_dense *B = rod2ccd (b, &cc);
+  cholmod_sparse A = ocs2ccs (a);
+  cholmod_dense *B = ord2ccd (b, &cc);
   cholmod_dense *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc);
   spqr_error_handler (&cc);
 
-  Complex *xdata = x.fortran_vec ();
-  for (volatile octave_idx_type i = 0; i < nc * b_nc; i++)
+  Complex *xdata = x.rwdata ();
+  for (octave_idx_type i = 0; i < nc * b_nc; i++)
     xdata[i] = reinterpret_cast<Complex *> (X->x)[i];
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -2986,17 +2993,17 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = cos2ccs (a);
-  cholmod_sparse B = cos2ccs (b);
+  cholmod_sparse A = ocs2ccs (a);
+  cholmod_sparse B = ocs2ccs (b);
   cholmod_sparse *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc);
   spqr_error_handler (&cc);
 
-  SparseComplexMatrix ret = ccs2cos (X, &cc);
+  SparseComplexMatrix ret = ccs2ocs (X, &cc);
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -3011,6 +3018,8 @@
 
 // FIXME: 2024/01/07: This template specialization does not appear to be
 // reachable from current Octave code calling qrsolve from sparse-dmsolve.cc.
+// It remains because liboctave may be used by other C++ code besides the
+// Octave interpreter.
 template <>
 template <>
 OCTAVE_API SparseComplexMatrix
@@ -3022,17 +3031,17 @@
   cholmod_common cc;
 
   cholmod_l_start (&cc);
-  cholmod_sparse A = cos2ccs (a);
-  cholmod_sparse *B = ros2ccs (b, &cc);
+  cholmod_sparse A = ocs2ccs (a);
+  cholmod_sparse *B = ors2ccs (b, &cc);
   cholmod_sparse *X;
 
   X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc);
   spqr_error_handler (&cc);
 
-  SparseComplexMatrix ret = ccs2cos (X, &cc);
+  SparseComplexMatrix ret = ccs2ocs (X, &cc);
   info = 0;
 
-  if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long))
+  if (octave_suitesparse_ptr_size_mismatch)
     {
       delete [] reinterpret_cast<SuiteSparse_long *> (A.p);
       delete [] reinterpret_cast<SuiteSparse_long *> (A.i);
@@ -3051,16 +3060,14 @@
 // Bateman's original code.
 
 template <typename SPARSE_T>
-class
-cxsparse_defaults
+class cxsparse_defaults
 {
 public:
   enum { order = -1 };
 };
 
 template <>
-class
-cxsparse_defaults<SparseMatrix>
+class cxsparse_defaults<SparseMatrix>
 {
 public:
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
@@ -3071,8 +3078,7 @@
 };
 
 template <>
-class
-cxsparse_defaults<SparseComplexMatrix>
+class cxsparse_defaults<SparseComplexMatrix>
 {
 public:
 #if (defined (HAVE_SPQR) && defined (HAVE_CHOLMOD))
--- a/liboctave/numeric/sparse-qr.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/sparse-qr.h	Fri Apr 12 15:10:26 2024 +0200
@@ -44,8 +44,7 @@
 // of the matrix type.
 
 template <typename SPARSE_T>
-class
-sparse_qr
+class sparse_qr
 {
 public:
 
--- a/liboctave/numeric/svd.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/svd.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -27,8 +27,6 @@
 #  include "config.h"
 #endif
 
-#include <cassert>
-
 #include <algorithm>
 #include <unordered_map>
 
@@ -44,8 +42,7 @@
 
 // class to compute optimal work space size (lwork) for DGEJSV and SGEJSV
 template<typename T>
-class
-gejsv_lwork
+class gejsv_lwork
 {
 public:
 
@@ -706,7 +703,7 @@
     }
 
   T atmp = a;
-  P *tmp_data = atmp.fortran_vec ();
+  P *tmp_data = atmp.rwdata ();
 
   F77_INT min_mn = (m < n ? m : n);
 
@@ -745,10 +742,10 @@
   if (! (jobu == 'N' || jobu == 'O'))
     m_left_sm.resize (m, ncol_u);
 
-  P *u = m_left_sm.fortran_vec ();
+  P *u = m_left_sm.rwdata ();
 
   m_sigma.resize (nrow_s, ncol_s);
-  DM_P *s_vec = m_sigma.fortran_vec ();
+  DM_P *s_vec = m_sigma.rwdata ();
 
   if (! (jobv == 'N' || jobv == 'O'))
     {
@@ -758,7 +755,7 @@
         m_right_sm.resize (nrow_vt, n);
     }
 
-  P *vt = m_right_sm.fortran_vec ();
+  P *vt = m_right_sm.rwdata ();
 
   // Query _GESVD for the correct dimension of WORK.
 
@@ -775,7 +772,7 @@
            work, lwork, info);
   else if (m_driver == svd::Driver::GESDD)
     {
-      assert (jobu == jobv);
+      liboctave_panic_unless (jobu == jobv);
       char jobz = jobu;
 
       std::vector<F77_INT> iwork (8 * std::min (m, n));
@@ -799,11 +796,11 @@
           std::swap (jobu, jobv);
 
           atmp = atmp.hermitian ();
-          tmp_data = atmp.fortran_vec ();
+          tmp_data = atmp.rwdata ();
 
           // Swap pointers of U and V.
-          u  = m_right_sm.fortran_vec ();
-          vt = m_left_sm.fortran_vec ();
+          u  = m_right_sm.rwdata ();
+          vt = m_left_sm.rwdata ();
         }
 
       // translate jobu and jobv from gesvd to gejsv.
--- a/liboctave/numeric/svd.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/numeric/svd.h	Fri Apr 12 15:10:26 2024 +0200
@@ -35,9 +35,7 @@
 OCTAVE_BEGIN_NAMESPACE(math)
 
 template <typename T>
-class
-OCTAVE_API
-svd
+class OCTAVE_API svd
 {
 public:
 
--- a/liboctave/operators/Sparse-perm-op-defs.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/operators/Sparse-perm-op-defs.h	Fri Apr 12 15:10:26 2024 +0200
@@ -112,7 +112,7 @@
           r.xdata (k) = a.data (k_src);
         }
     }
-  assert (k_src == nent);
+  liboctave_panic_unless (k_src == nent);
 
   return r;
 }
@@ -132,7 +132,7 @@
       const octave_idx_type j_src = pcol[j];
       r.xcidx (j+1) = r.xcidx (j) + (a.cidx (j_src+1) - a.cidx (j_src));
     }
-  assert (r.xcidx (nc) == nent);
+  liboctave_panic_unless (r.xcidx (nc) == nent);
 
   octave_idx_type k = 0;
   for (octave_idx_type j = 0; j < nc; ++j)
@@ -147,7 +147,7 @@
           r.xdata (k) = a.data (k_src);
         }
     }
-  assert (k == nent);
+  liboctave_panic_unless (k == nent);
 
   return r;
 }
--- a/liboctave/operators/mx-inlines.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/operators/mx-inlines.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -471,7 +471,7 @@
                 void (*op) (std::size_t, R *, const X *))
 {
   Array<R> r (x.dims ());
-  op (r.numel (), r.fortran_vec (), x.data ());
+  op (r.numel (), r.rwdata (), x.data ());
   return r;
 }
 
@@ -496,7 +496,7 @@
 do_mx_inplace_op (Array<R>& r,
                   void (*op) (std::size_t, R *))
 {
-  op (r.numel (), r.fortran_vec ());
+  op (r.numel (), r.rwdata ());
   return r;
 }
 
@@ -508,12 +508,12 @@
                  void (*op2) (std::size_t, R *, const X *, Y),
                  const char *opname)
 {
-  dim_vector dx = x.dims ();
-  dim_vector dy = y.dims ();
+  const dim_vector &dx = x.dims ();
+  const dim_vector &dy = y.dims ();
   if (dx == dy)
     {
       Array<R> r (dx);
-      op (r.numel (), r.fortran_vec (), x.data (), y.data ());
+      op (r.numel (), r.rwdata (), x.data (), y.data ());
       return r;
     }
   else if (is_valid_bsxfun (opname, dx, dy))
@@ -530,7 +530,7 @@
                  void (*op) (std::size_t, R *, const X *, Y))
 {
   Array<R> r (x.dims ());
-  op (r.numel (), r.fortran_vec (), x.data (), y);
+  op (r.numel (), r.rwdata (), x.data (), y);
   return r;
 }
 
@@ -540,7 +540,7 @@
                  void (*op) (std::size_t, R *, X, const Y *))
 {
   Array<R> r (y.dims ());
-  op (r.numel (), r.fortran_vec (), x, y.data ());
+  op (r.numel (), r.rwdata (), x, y.data ());
   return r;
 }
 
@@ -551,10 +551,10 @@
                   void (*op1) (std::size_t, R *, X),
                   const char *opname)
 {
-  dim_vector dr = r.dims ();
-  dim_vector dx = x.dims ();
+  const dim_vector &dr = r.dims ();
+  const dim_vector &dx = x.dims ();
   if (dr == dx)
-    op (r.numel (), r.fortran_vec (), x.data ());
+    op (r.numel (), r.rwdata (), x.data ());
   else if (is_valid_inplace_bsxfun (opname, dr, dx))
     do_inplace_bsxfun_op (r, x, op, op1);
   else
@@ -568,7 +568,7 @@
 do_ms_inplace_op (Array<R>& r, const X& x,
                   void (*op) (std::size_t, R *, X))
 {
-  op (r.numel (), r.fortran_vec (), x);
+  op (r.numel (), r.rwdata (), x);
   return r;
 }
 
@@ -1561,7 +1561,7 @@
   dims.chop_trailing_singletons ();
 
   Array<R> ret (dims);
-  mx_red_op (src.data (), ret.fortran_vec (), l, n, u);
+  mx_red_op (src.data (), ret.rwdata (), l, n, u);
 
   return ret;
 }
@@ -1573,12 +1573,12 @@
                                  octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
-  dim_vector dims = src.dims ();
+  const dim_vector& dims = src.dims ();
   get_extent_triplet (dims, dim, l, n, u);
 
   // Cumulative operation doesn't reduce the array size.
   Array<R> ret (dims);
-  mx_cum_op (src.data (), ret.fortran_vec (), l, n, u);
+  mx_cum_op (src.data (), ret.rwdata (), l, n, u);
 
   return ret;
 }
@@ -1598,7 +1598,7 @@
   dims.chop_trailing_singletons ();
 
   Array<R> ret (dims);
-  mx_minmax_op (src.data (), ret.fortran_vec (), l, n, u);
+  mx_minmax_op (src.data (), ret.rwdata (), l, n, u);
 
   return ret;
 }
@@ -1620,7 +1620,7 @@
   Array<R> ret (dims);
   if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
 
-  mx_minmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
+  mx_minmax_op (src.data (), ret.rwdata (), idx.rwdata (),
                 l, n, u);
 
   return ret;
@@ -1633,11 +1633,11 @@
                                              octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
-  dim_vector dims = src.dims ();
+  const dim_vector& dims = src.dims ();
   get_extent_triplet (dims, dim, l, n, u);
 
   Array<R> ret (dims);
-  mx_cumminmax_op (src.data (), ret.fortran_vec (), l, n, u);
+  mx_cumminmax_op (src.data (), ret.rwdata (), l, n, u);
 
   return ret;
 }
@@ -1649,13 +1649,13 @@
                                              octave_idx_type, octave_idx_type, octave_idx_type))
 {
   octave_idx_type l, n, u;
-  dim_vector dims = src.dims ();
+  const dim_vector& dims = src.dims ();
   get_extent_triplet (dims, dim, l, n, u);
 
   Array<R> ret (dims);
   if (idx.dims () != dims) idx = Array<octave_idx_type> (dims);
 
-  mx_cumminmax_op (src.data (), ret.fortran_vec (), idx.fortran_vec (),
+  mx_cumminmax_op (src.data (), ret.rwdata (), idx.rwdata (),
                    l, n, u);
 
   return ret;
@@ -1689,7 +1689,7 @@
     }
 
   Array<R> ret (dims);
-  mx_diff_op (src.data (), ret.fortran_vec (), l, n, u, order);
+  mx_diff_op (src.data (), ret.rwdata (), l, n, u, order);
 
   return ret;
 }
--- a/liboctave/operators/mx-op-defs.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/operators/mx-op-defs.h	Fri Apr 12 15:10:26 2024 +0200
@@ -440,7 +440,7 @@
       octave::err_nonconformant ("operator *", m_nr, m_nc, dm_nr, dm_nc);       \
                                                                         \
     r = R (m_nr, dm_nc);                                                \
-    R::element_type *rd = r.fortran_vec ();                             \
+    R::element_type *rd = r.rwdata ();                             \
     const M::element_type *md = m.data ();                              \
     const DM::element_type *dd = dm.data ();                            \
                                                                         \
@@ -512,7 +512,7 @@
       octave::err_nonconformant ("operator *", dm_nr, dm_nc, m_nr, m_nc);       \
                                                                         \
     r = R (dm_nr, m_nc);                                                \
-    R::element_type *rd = r.fortran_vec ();                             \
+    R::element_type *rd = r.rwdata ();                             \
     const M::element_type *md = m.data ();                              \
     const DM::element_type *dd = dm.data ();                            \
                                                                         \
@@ -553,7 +553,7 @@
     r.resize (dm1_nr, dm1_nc);                                          \
                                                                         \
     if (dm1_nr > 0 && dm1_nc > 0)                                       \
-      F (dm1.length (), r.fortran_vec (), dm1.data (), dm2.data ());    \
+      F (dm1.length (), r.rwdata (), dm1.data (), dm2.data ());    \
                                                                         \
     return r;                                                           \
   }
--- a/liboctave/system/child-list.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/child-list.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 void
 child_list::child_list::insert (pid_t pid, child::child_event_handler f)
 {
-  m_list.append (child (pid, f));
+  m_list.push_back (child (pid, f));
 }
 
 void
--- a/liboctave/system/child-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/child-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,9 +30,9 @@
 
 #include <csignal>
 
-#include <sys/types.h>
+#include <list>
 
-#include "base-list.h"
+#include <sys/types.h>
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
@@ -88,7 +88,7 @@
 
 private:
 
-  base_list<child> m_list;
+  std::list<child> m_list;
 };
 
 OCTAVE_END_NAMESPACE(octave)
--- a/liboctave/system/dir-ops.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/dir-ops.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-dir_entry
+class OCTAVE_API dir_entry
 {
 
   // NOTE: This class cannot be used safely cross-platform (Windows) with
--- a/liboctave/system/file-stat.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/file-stat.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,9 +38,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-base_file_stat
+class OCTAVE_API base_file_stat
 {
 public:
 
@@ -208,9 +206,7 @@
   long m_blocks;
 };
 
-class
-OCTAVE_API
-file_stat : public base_file_stat
+class OCTAVE_API file_stat : public base_file_stat
 {
 public:
 
@@ -269,9 +265,7 @@
   void update_internal (bool force = false);
 };
 
-class
-OCTAVE_API
-file_fstat : public base_file_stat
+class OCTAVE_API file_fstat : public base_file_stat
 {
 public:
 
--- a/liboctave/system/lo-sysdep.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/lo-sysdep.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -239,7 +239,7 @@
       return false;
     }
 
-  unwind_action act ([=] ()
+  unwind_action act ([fptr, tmpname] ()
   {
     std::fclose (fptr);
     sys::unlink (tmpname);
--- a/liboctave/system/oct-env.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-env.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-env
+class OCTAVE_API env
 {
 protected:
 
--- a/liboctave/system/oct-group.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-group.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,9 +38,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-group
+class OCTAVE_API group
 {
 public:
 
--- a/liboctave/system/oct-password.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-password.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -120,7 +120,7 @@
 password
 password::getpwent (std::string& msg)
 {
-#if defined HAVE_GETPWENT
+#if defined (HAVE_GETPWENT)
   msg = "";
   return password (octave_getpwent_wrapper (), msg);
 #else
--- a/liboctave/system/oct-password.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-password.h	Fri Apr 12 15:10:26 2024 +0200
@@ -36,9 +36,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-password
+class OCTAVE_API password
 {
 public:
 
--- a/liboctave/system/oct-time.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-time.h	Fri Apr 12 15:10:26 2024 +0200
@@ -59,8 +59,7 @@
 
 class base_tm;
 
-class
-time
+class time
 {
 public:
 
@@ -193,8 +192,7 @@
                t1.usec () + t2.usec ());
 }
 
-class
-base_tm
+class base_tm
 {
 public:
 
@@ -306,8 +304,7 @@
   OCTAVE_API void init (void *p);
 };
 
-class
-localtime : public base_tm
+class localtime : public base_tm
 {
 public:
 
@@ -333,8 +330,7 @@
   OCTAVE_API void init (const time& ot);
 };
 
-class
-gmtime : public base_tm
+class gmtime : public base_tm
 {
 public:
 
@@ -351,8 +347,7 @@
   OCTAVE_API void init (const time& ot);
 };
 
-class
-strptime : public base_tm
+class strptime : public base_tm
 {
 public:
 
@@ -375,8 +370,7 @@
   OCTAVE_API void init (const std::string& str, const std::string& fmt);
 };
 
-class
-cpu_time
+class cpu_time
 {
 public:
 
@@ -422,8 +416,7 @@
   { }
 };
 
-class
-resource_usage
+class resource_usage
 {
 public:
 
--- a/liboctave/system/oct-uname.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/system/oct-uname.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(sys)
 
-class
-OCTAVE_API
-uname
+class OCTAVE_API uname
 {
 public:
 
--- a/liboctave/util/action-container.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/action-container.h	Fri Apr 12 15:10:26 2024 +0200
@@ -56,8 +56,7 @@
 
 OCTAVE_END_NAMESPACE(util)
 
-class
-action_container
+class action_container
 {
 public:
 
--- a/liboctave/util/base-list.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/base-list.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,6 +28,8 @@
 
 #include "octave-config.h"
 
+#warning "using <base-list.h> is discouraged - use <list> instead"
+
 #include <cstdlib>
 
 #include <list>
@@ -35,8 +37,7 @@
 OCTAVE_BEGIN_NAMESPACE(octave)
 
 template <typename elt_type>
-class
-base_list
+class base_list
 {
 public:
 
--- a/liboctave/util/cmd-edit.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/cmd-edit.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -69,8 +69,7 @@
 
 #if defined (USE_READLINE)
 
-class
-gnu_readline : public command_editor
+class gnu_readline : public command_editor
 {
 public:
 
@@ -929,8 +928,7 @@
 
 #endif
 
-class
-default_command_editor : public command_editor
+class default_command_editor : public command_editor
 {
 public:
 
--- a/liboctave/util/cmd-edit.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/cmd-edit.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-command_editor
+class OCTAVE_API command_editor
 {
 protected:
 
--- a/liboctave/util/cmd-hist.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/cmd-hist.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -56,8 +56,7 @@
 
 #if defined (USE_READLINE)
 
-class
-gnu_history : public command_history
+class gnu_history : public command_history
 {
 public:
 
--- a/liboctave/util/cmd-hist.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/cmd-hist.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-command_history
+class OCTAVE_API command_history
 {
 protected:
 
--- a/liboctave/util/data-conv.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/data-conv.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -391,8 +391,21 @@
         {
           if (s[pos] == '*')
             {
-              block_size = atoi (s.c_str ());
-              s = s.substr (pos+1);
+              try
+                {
+                  block_size = std::stoi (s);
+                  s = s.substr (pos+1);
+                }
+              catch (const std::invalid_argument&)
+                {
+                  (*current_liboctave_error_handler)
+                    ("invalid repeat count in '%s'", s.c_str ());
+                }
+              catch (const std::out_of_range&)
+                {
+                  (*current_liboctave_error_handler)
+                    ("repeat count out of range in '%s'", s.c_str ());
+                }
             }
           else
             (*current_liboctave_error_handler)
@@ -458,8 +471,21 @@
     {
       if (s[pos] == '*')
         {
-          block_size = atoi (s.c_str ());
-          s = s.substr (pos+1);
+          try
+            {
+              block_size = std::stoi (s);
+              s = s.substr (pos+1);
+            }
+          catch (const std::invalid_argument&)
+            {
+              (*current_liboctave_error_handler)
+                ("invalid repeat count in '%s'", s.c_str ());
+            }
+          catch (const std::out_of_range&)
+            {
+              (*current_liboctave_error_handler)
+                ("repeat count out of range in '%s'", s.c_str ());
+            }
         }
       else
         (*current_liboctave_error_handler)
--- a/liboctave/util/data-conv.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/data-conv.h	Fri Apr 12 15:10:26 2024 +0200
@@ -31,9 +31,7 @@
 #include "mach-info.h"
 #include "oct-inttypes-fwd.h"
 
-class
-OCTAVE_API
-oct_data_conv
+class OCTAVE_API oct_data_conv
 {
 public:
 
--- a/liboctave/util/glob-match.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/glob-match.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 #include "Array.h"
 #include "str-vec.h"
 
-class
-OCTAVE_API
-glob_match
+class OCTAVE_API glob_match
 {
 public:
 
@@ -96,9 +94,7 @@
   int opts_to_fnmatch_flags (unsigned int xopts) const;
 };
 
-class
-OCTAVE_API
-symbol_match
+class OCTAVE_API symbol_match
 {
 
 // This class is meant to provide a performant implementation for symbol
--- a/liboctave/util/lo-error.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-error.h	Fri Apr 12 15:10:26 2024 +0200
@@ -81,6 +81,28 @@
 extern OCTAVE_API void
 set_liboctave_warning_with_id_handler (liboctave_warning_with_id_handler f);
 
+// To allow the __FILE__ and __LINE__ macros to work as expected, the
+// liboctave_panic_impossible, liboctave_panic_if, and
+// liboctave_panic_unless symbols must be defined as macros.
+
+#if defined (NDEBUG)
+
+#  define liboctave_panic_impossible() do { } while (0)
+
+#  define liboctave_panic_if(cond) do { } while (0)
+
+#  define liboctave_panic_unless(cond) do { } while (0)
+
+#else
+
+#  define liboctave_panic_impossible() (*current_liboctave_error_handler) ("impossible state reached in file '%s' at line %d", __FILE__, __LINE__)
+
+#  define liboctave_panic_if(cond) do { if (cond) liboctave_panic_impossible (); } while (0)
+
+#  define liboctave_panic_unless(cond) liboctave_panic_if (! (cond))
+
+#endif
+
 #if defined (__cplusplus)
 }
 #endif
--- a/liboctave/util/lo-ieee.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-ieee.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -60,7 +60,7 @@
 {
   lo_ieee_double t;
   t.value = x;
-  return (__lo_ieee_isnan (x) && t.word[lo_ieee_hw] == LO_IEEE_NA_HW
+  return (std::isnan (x) && t.word[lo_ieee_hw] == LO_IEEE_NA_HW
           && t.word[lo_ieee_lw] == LO_IEEE_NA_LW) ? 1 : 0;
 }
 
@@ -93,7 +93,7 @@
 {
   lo_ieee_float t;
   t.value = x;
-  return (__lo_ieee_float_isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;
+  return (std::isnan (x) && (t.word == LO_IEEE_NA_FLOAT)) ? 1 : 0;
 }
 
 float
--- a/liboctave/util/lo-ieee.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-ieee.h	Fri Apr 12 15:10:26 2024 +0200
@@ -72,28 +72,44 @@
 extern OCTAVE_API void octave_ieee_init (void);
 
 #if defined (__cplusplus)
+OCTAVE_DEPRECATED (10, "use std::isnan instead")
 inline int __lo_ieee_isnan (double x) { return std::isnan (x); }
+OCTAVE_DEPRECATED (10, "use std::isfinite instead")
 inline int __lo_ieee_isfinite (double x) { return std::isfinite (x); }
+OCTAVE_DEPRECATED (10, "use std::isinf instead")
 inline int __lo_ieee_isinf (double x) { return std::isinf (x); }
 
+OCTAVE_DEPRECATED (10, "use std::signbit instead")
 inline int __lo_ieee_signbit (double x) { return std::signbit (x); }
 
+OCTAVE_DEPRECATED (10, "use std::isnan instead")
 inline int __lo_ieee_float_isnan (float x) { return std::isnan (x); }
+OCTAVE_DEPRECATED (10, "use std::isfinite instead")
 inline int __lo_ieee_float_isfinite (float x) { return std::isfinite (x); }
+OCTAVE_DEPRECATED (10, "use std::isinf instead")
 inline int __lo_ieee_float_isinf (float x) { return std::isinf (x); }
 
+OCTAVE_DEPRECATED (10, "use std::signbit instead")
 inline int __lo_ieee_float_signbit (float x) { return std::signbit (x); }
 #else
+OCTAVE_DEPRECATED (10, "use isnan instead")
 inline int __lo_ieee_isnan (double x) { return isnan (x); }
+OCTAVE_DEPRECATED (10, "use isfinite instead")
 inline int __lo_ieee_isfinite (double x) { return isfinite (x); }
+OCTAVE_DEPRECATED (10, "use isinf instead")
 inline int __lo_ieee_isinf (double x) { return isinf (x); }
 
+OCTAVE_DEPRECATED (10, "use signbit instead")
 inline int __lo_ieee_signbit (double x) { return signbit (x); }
 
+OCTAVE_DEPRECATED (10, "use isnan instead")
 inline int __lo_ieee_float_isnan (float x) { return isnan (x); }
+OCTAVE_DEPRECATED (10, "use isfinite instead")
 inline int __lo_ieee_float_isfinite (float x) { return isfinite (x); }
+OCTAVE_DEPRECATED (10, "use isinf instead")
 inline int __lo_ieee_float_isinf (float x) { return isinf (x); }
 
+OCTAVE_DEPRECATED (10, "use signbit instead")
 inline int __lo_ieee_float_signbit (float x) { return signbit (x); }
 #endif
 
--- a/liboctave/util/lo-regexp.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-regexp.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -48,7 +48,6 @@
 #endif
 
 #include "Matrix.h"
-#include "base-list.h"
 #include "lo-error.h"
 #include "oct-locbuf.h"
 #include "quit.h"
@@ -369,16 +368,15 @@
       octave_quit ();
 
 #if defined (HAVE_PCRE2)
-      pcre2_match_data *m_data
+      pcre2_match_data *tmp_match_data
         = pcre2_match_data_create_from_pattern (re, nullptr);
 
-      unwind_action cleanup_match_data
-      ([=] () { pcre2_match_data_free (m_data); });
+      unwind_action cleanup_match_data ([tmp_match_data] () { pcre2_match_data_free (tmp_match_data); });
 
       int matches = pcre2_match (re, reinterpret_cast<PCRE2_SPTR> (buffer.c_str ()),
                                  buffer.length (), idx,
                                  PCRE2_NO_UTF_CHECK | (idx ? PCRE2_NOTBOL : 0),
-                                 m_data, nullptr);
+                                 tmp_match_data, nullptr);
 
       if (matches < 0 && matches != PCRE2_ERROR_NOMATCH)
         (*current_liboctave_error_handler)
@@ -388,7 +386,7 @@
       if (matches == PCRE2_ERROR_NOMATCH)
         break;
 
-      OCTAVE_PCRE_SIZE *ovector = pcre2_get_ovector_pointer (m_data);
+      OCTAVE_PCRE_SIZE *ovector = pcre2_get_ovector_pointer (tmp_match_data);
 #else
       int matches = pcre_exec (re, nullptr, buffer.c_str (),
                                buffer.length (), idx,
--- a/liboctave/util/lo-regexp.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-regexp.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,14 +34,11 @@
 
 #include "Array.h"
 #include "Matrix.h"
-#include "base-list.h"
 #include "str-vec.h"
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-regexp
+class OCTAVE_API regexp
 {
 public:
 
@@ -196,16 +193,16 @@
     double m_end;
   };
 
-  class match_data : public base_list<match_element>
+  class match_data : public std::list<match_element>
   {
   public:
 
     match_data ()
-      : base_list<match_element> (), m_named_pats ()
+      : std::list<match_element> (), m_named_pats ()
     { }
 
     match_data (const std::list<match_element>& l, const string_vector& np)
-      : base_list<match_element> (l), m_named_pats (np)
+      : std::list<match_element> (l), m_named_pats (np)
     { }
 
     OCTAVE_DEFAULT_COPY_MOVE_DELETE (match_data)
--- a/liboctave/util/lo-utils.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/lo-utils.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -446,9 +446,9 @@
 {
   if (lo_ieee_is_NA (value))
     os << "NA";
-  else if (lo_ieee_isnan (value))
+  else if (math::isnan (value))
     os << "NaN";
-  else if (lo_ieee_isinf (value))
+  else if (math::isinf (value))
     os << (value < 0 ? "-Inf" : "Inf");
   else
     os << value;
@@ -474,9 +474,9 @@
 {
   if (lo_ieee_is_NA (value))
     os << "NA";
-  else if (lo_ieee_isnan (value))
+  else if (math::isnan (value))
     os << "NaN";
-  else if (lo_ieee_isinf (value))
+  else if (math::isinf (value))
     os << (value < 0 ? "-Inf" : "Inf");
   else
     os << value;
--- a/liboctave/util/oct-atomic.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-atomic.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 #include "octave-config.h"
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -38,7 +38,7 @@
   extern OCTAVE_API octave_idx_type
   octave_atomic_decrement (octave_idx_type *x);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/util/oct-base64.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-base64.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -88,7 +88,7 @@
     {
       octave_idx_type len = (outlen * sizeof (char)) / sizeof (double);
       retval.resize (dim_vector (1, len));
-      std::copy (out, out + len, retval.fortran_vec ());
+      std::copy (out, out + len, retval.rwdata ());
       ::free (out);
     }
 
@@ -116,7 +116,7 @@
       ("base64_decode: memory allocation error");
 
   retval.resize (dim_vector (1, outlen));
-  std::copy (out, out + outlen, retval.fortran_vec ());
+  std::copy (out, out + outlen, retval.rwdata ());
   ::free (out);
 
   return retval;
--- a/liboctave/util/oct-binmap.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-binmap.h	Fri Apr 12 15:10:26 2024 +0200
@@ -116,7 +116,7 @@
   const R *y = ya.data ();
 
   Array<U> result (ya.dims ());
-  U *p = result.fortran_vec ();
+  U *p = result.rwdata ();
 
   octave_idx_type i;
   for (i = 0; i < len - 3; i += 4)
@@ -147,7 +147,7 @@
   const R *x = xa.data ();
 
   Array<U> result (xa.dims ());
-  U *p = result.fortran_vec ();
+  U *p = result.rwdata ();
 
   octave_idx_type i;
   for (i = 0; i < len - 3; i += 4)
@@ -173,8 +173,8 @@
 Array<U>
 binmap (const Array<T>& xa, const Array<R>& ya, F fcn, const char *name)
 {
-  dim_vector xad = xa.dims ();
-  dim_vector yad = ya.dims ();
+  const dim_vector& xad = xa.dims ();
+  const dim_vector& yad = ya.dims ();
   if (xa.numel () == 1)
     return binmap<U, T, R, F> (xa(0), ya, fcn);
   else if (ya.numel () == 1)
@@ -197,7 +197,7 @@
   const T *y = ya.data ();
 
   Array<U> result (xa.dims ());
-  U *p = result.fortran_vec ();
+  U *p = result.rwdata ();
 
   octave_idx_type i;
   for (i = 0; i < len - 3; i += 4)
--- a/liboctave/util/oct-cmplx.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-cmplx.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -46,12 +46,12 @@
    template <typename T>                                                     \
    bool operator OP (const std::complex<T>& a, const std::complex<T>& b)     \
    {                                                                         \
-     OCTAVE_FLOAT_TRUNCATE const T ax = std::abs (a);                        \
-     OCTAVE_FLOAT_TRUNCATE const T bx = std::abs (b);                        \
+     const T ax = std::abs (a);                                              \
+     const T bx = std::abs (b);                                              \
      if (ax == bx)                                                           \
        {                                                                     \
-         OCTAVE_FLOAT_TRUNCATE const T ay = std::arg (a);                    \
-         OCTAVE_FLOAT_TRUNCATE const T by = std::arg (b);                    \
+         const T ay = std::arg (a);                                          \
+         const T by = std::arg (b);                                          \
          if (ay == static_cast<T> (-M_PI))                                   \
            {                                                                 \
              if (by != static_cast<T> (-M_PI))                               \
@@ -69,11 +69,11 @@
    template <typename T>                                                     \
    bool operator OP (const std::complex<T>& a, T b)                          \
    {                                                                         \
-     OCTAVE_FLOAT_TRUNCATE const T ax = std::abs (a);                        \
-     OCTAVE_FLOAT_TRUNCATE const T bx = std::abs (b);                        \
+     const T ax = std::abs (a);                                              \
+     const T bx = std::abs (b);                                              \
      if (ax == bx)                                                           \
        {                                                                     \
-         OCTAVE_FLOAT_TRUNCATE const T ay = std::arg (a);                    \
+         const T ay = std::arg (a);                                          \
          if (ay == static_cast<T> (-M_PI))                                   \
            return static_cast<T> (M_PI) OP 0;                                \
          return ay OP 0;                                                     \
@@ -84,11 +84,11 @@
    template <typename T>                                                     \
    bool operator OP (T a, const std::complex<T>& b)                          \
    {                                                                         \
-     OCTAVE_FLOAT_TRUNCATE const T ax = std::abs (a);                        \
-     OCTAVE_FLOAT_TRUNCATE const T bx = std::abs (b);                        \
+     const T ax = std::abs (a);                                              \
+     const T bx = std::abs (b);                                              \
      if (ax == bx)                                                           \
        {                                                                     \
-         OCTAVE_FLOAT_TRUNCATE const T by = std::arg (b);                    \
+         const T by = std::arg (b);                                          \
          if (by == static_cast<T> (-M_PI))                                   \
            return 0 OP static_cast<T> (M_PI);                                \
          return 0 OP by;                                                     \
@@ -116,12 +116,12 @@
      bool operator OP<float> (const std::complex<float>& a,                  \
                               const std::complex<float>& b)                  \
      {                                                                       \
-       OCTAVE_FLOAT_TRUNCATE const float ax = std::abs (a);                  \
-       OCTAVE_FLOAT_TRUNCATE const float bx = std::abs (b);                  \
+       const float ax = std::abs (a);                                        \
+       const float bx = std::abs (b);                                        \
        if (ax == bx)                                                         \
          {                                                                   \
-           OCTAVE_FLOAT_TRUNCATE const float ay = std::arg (a);              \
-           OCTAVE_FLOAT_TRUNCATE const float by = std::arg (b);              \
+           const float ay = std::arg (a);                                    \
+           const float by = std::arg (b);                                    \
            if (ay == -A_PI)                                                  \
              {                                                               \
                if (by != -A_PI)                                              \
@@ -139,11 +139,11 @@
      template <> OCTAVE_API                                                  \
      bool operator OP<float> (const std::complex<float>& a, float b)         \
      {                                                                       \
-       OCTAVE_FLOAT_TRUNCATE const float ax = std::abs (a);                  \
-       OCTAVE_FLOAT_TRUNCATE const float bx = std::abs (b);                  \
+       const float ax = std::abs (a);                                        \
+       const float bx = std::abs (b);                                        \
        if (ax == bx)                                                         \
          {                                                                   \
-           OCTAVE_FLOAT_TRUNCATE const float ay = std::arg (a);              \
+           const float ay = std::arg (a);                                    \
            if (ay == -A_PI)                                                  \
              return static_cast<float> (M_PI) OP 0;                          \
            return ay OP 0;                                                   \
@@ -154,11 +154,11 @@
      template <> OCTAVE_API                                                  \
      bool operator OP<float> (float a, const std::complex<float>& b)         \
      {                                                                       \
-       OCTAVE_FLOAT_TRUNCATE const float ax = std::abs (a);                  \
-       OCTAVE_FLOAT_TRUNCATE const float bx = std::abs (b);                  \
+       const float ax = std::abs (a);                                        \
+       const float bx = std::abs (b);                                        \
        if (ax == bx)                                                         \
          {                                                                   \
-           OCTAVE_FLOAT_TRUNCATE const float by = std::arg (b);              \
+           const float by = std::arg (b);                                    \
            if (by == -A_PI)                                                  \
              return 0 OP static_cast<float> (M_PI);                          \
            return 0 OP by;                                                   \
--- a/liboctave/util/oct-glob.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-glob.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -81,7 +81,7 @@
   void *glob_info = octave_create_glob_info_struct ();
 
   unwind_action cleanup_glob_info_struct
-  ([=] () { octave_destroy_glob_info_struct (glob_info); });
+  ([glob_info] () { octave_destroy_glob_info_struct (glob_info); });
 
   for (int i = 0; i < npat; i++)
     {
@@ -184,7 +184,7 @@
   if (h_find == INVALID_HANDLE_VALUE)
     return;
 
-  unwind_action close_h_find ([=] () { FindClose (h_find); });
+  unwind_action close_h_find ([h_find] () { FindClose (h_find); });
 
   // find all files that match pattern
   do
@@ -311,8 +311,7 @@
 
   void *glob_info = octave_create_glob_info_struct ();
 
-  unwind_action cleanup_glob_info_struct
-  ([=] () { octave_destroy_glob_info_struct (glob_info); });
+  unwind_action cleanup_glob_info_struct ([glob_info] () { octave_destroy_glob_info_struct (glob_info); });
 
   for (int i = 0; i < npat; i++)
     {
--- a/liboctave/util/oct-inttypes.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-inttypes.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -538,8 +538,8 @@
 OCTAVE_API octave_int64
 operator - (const double& x, const octave_int64& y)
 {
-  static const bool twosc = (std::numeric_limits<int64_t>::min ()
-                             < -std::numeric_limits<int64_t>::max ());
+  static constexpr bool twosc = (std::numeric_limits<int64_t>::min ()
+                                 < -std::numeric_limits<int64_t>::max ());
   // In case of symmetric integers (not two's complement), this will probably
   // be eliminated at compile time.
   if (twosc && y.value () == std::numeric_limits<int64_t>::min ())
--- a/liboctave/util/oct-inttypes.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-inttypes.h	Fri Apr 12 15:10:26 2024 +0200
@@ -123,16 +123,16 @@
   class prom
   {
     // Promote to int?
-    static const bool s_pint = (sizeof (T1) < sizeof (int)
-                                && sizeof (T2) < sizeof (int));
+    static constexpr bool s_pint = (sizeof (T1) < sizeof (int)
+                                    && sizeof (T2) < sizeof (int));
 
-    static const bool s_t1sig = std::numeric_limits<T1>::is_signed;
-    static const bool s_t2sig = std::numeric_limits<T2>::is_signed;
+    static constexpr bool s_t1sig = std::numeric_limits<T1>::is_signed;
+    static constexpr bool s_t2sig = std::numeric_limits<T2>::is_signed;
 
-    static const bool s_psig
+    static constexpr bool s_psig
       = (s_pint || (sizeof (T2) > sizeof (T1) && s_t2sig) || s_t1sig);
 
-    static const int s_psize
+    static constexpr int s_psize
       = (s_pint
          ? sizeof (int)
          : (sizeof (T2) > sizeof (T1) ? sizeof (T2) : sizeof (T1)));
@@ -185,8 +185,8 @@
   {                                                     \
   public:                                               \
                                                         \
-    static const bool ltval = (0 OP 1);                 \
-    static const bool gtval = (1 OP 0);                 \
+    static constexpr bool ltval = (0 OP 1);             \
+    static constexpr bool gtval = (1 OP 0);             \
                                                         \
     template <typename T>                               \
     static bool op (T x, T y) { return x OP y; }        \
@@ -209,8 +209,8 @@
   {                                             \
   public:                                       \
                                                 \
-    static const bool ltval = VALUE;            \
-    static const bool gtval = VALUE;            \
+    static constexpr bool ltval = VALUE;        \
+    static constexpr bool gtval = VALUE;        \
                                                 \
     template <typename T>                       \
       static bool op (T, T) { return VALUE; }   \
@@ -357,16 +357,16 @@
     // An exhaustive test whether the max and/or min check can be
     // omitted.
 
-    static const bool t_is_signed = std::numeric_limits<T>::is_signed;
-    static const bool s_is_signed = std::numeric_limits<S>::is_signed;
+    static constexpr bool t_is_signed = std::numeric_limits<T>::is_signed;
+    static constexpr bool s_is_signed = std::numeric_limits<S>::is_signed;
 
-    static const int t_size = sizeof (T);
-    static const int s_size = sizeof (S);
+    static constexpr int t_size = sizeof (T);
+    static constexpr int s_size = sizeof (S);
 
-    static const bool omit_chk_min
+    static constexpr bool omit_chk_min
       = (! s_is_signed || (t_is_signed && t_size >= s_size));
 
-    static const bool omit_chk_max
+    static constexpr bool omit_chk_max
       = (t_size > s_size
          || (t_size == s_size && (! t_is_signed || s_is_signed)));
 
@@ -779,9 +779,7 @@
 { };
 
 template <typename T>
-class
-OCTAVE_TEMPLATE_API
-octave_int : public octave_int_base<T>
+class OCTAVE_TEMPLATE_API octave_int : public octave_int_base<T>
 {
 public:
 
--- a/liboctave/util/oct-mutex.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-mutex.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -60,8 +60,7 @@
 
 #if defined (OCTAVE_USE_WINDOWS_API)
 
-class
-w32_mutex : public base_mutex
+class w32_mutex : public base_mutex
 {
 public:
   w32_mutex ()
@@ -110,8 +109,7 @@
 
 #elif defined (HAVE_PTHREAD_H)
 
-class
-pthread_mutex : public base_mutex
+class pthread_mutex : public base_mutex
 {
 public:
 
--- a/liboctave/util/oct-mutex.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-mutex.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 
 class mutex;
 
-class
-OCTAVE_API
-base_mutex
+class OCTAVE_API base_mutex
 {
 public:
   friend class mutex;
@@ -52,9 +50,7 @@
   virtual bool try_lock ();
 };
 
-class
-OCTAVE_API
-mutex
+class OCTAVE_API mutex
 {
 public:
   mutex ();
@@ -80,9 +76,7 @@
   std::shared_ptr<base_mutex> m_rep;
 };
 
-class
-OCTAVE_API
-autolock
+class OCTAVE_API autolock
 {
 public:
   autolock (const mutex& m, bool block = true)
@@ -117,9 +111,7 @@
 };
 
 
-class
-OCTAVE_API
-thread
+class OCTAVE_API thread
 {
 public:
 
--- a/liboctave/util/oct-shlib.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-shlib.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -37,7 +37,7 @@
 #    include <dlfcn.h>
 #  else
   extern void * dlopen (const char *, int);
-  extern const char * dlerror (void);
+  extern const char * dlerror ();
   extern void * dlsym (void *, const char *);
   extern int dlclose (void *);
 #  endif
@@ -173,8 +173,7 @@
 
 #if defined (HAVE_DLOPEN_API)
 
-class
-octave_dlopen_shlib : public dynamic_library::dynlib_rep
+class octave_dlopen_shlib : public dynamic_library::dynlib_rep
 {
 public:
 
@@ -275,8 +274,7 @@
 
 #elif defined (HAVE_LOADLIBRARY_API)
 
-class
-octave_w32_shlib: public dynamic_library::dynlib_rep
+class octave_w32_shlib: public dynamic_library::dynlib_rep
 {
 public:
 
--- a/liboctave/util/oct-shlib.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-shlib.h	Fri Apr 12 15:10:26 2024 +0200
@@ -38,8 +38,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-dynamic_library
+class dynamic_library
 {
 public: // FIXME: make this class private?
 
--- a/liboctave/util/oct-sort.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-sort.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -107,7 +107,6 @@
 // C++ source files that should have included config.h before including
 // this file.
 
-#include <cassert>
 #include <algorithm>
 #include <cstring>
 #include <stack>
@@ -1437,7 +1436,7 @@
               n = force;
             }
           /* Push run onto m_pending-runs stack, and maybe merge. */
-          assert (m_ms->m_n < MAX_MERGE_PENDING);
+          liboctave_panic_unless (m_ms->m_n < MAX_MERGE_PENDING);
           m_ms->m_pending[m_ms->m_n].m_base = lo;
           m_ms->m_pending[m_ms->m_n].m_len = n;
           m_ms->m_n++;
@@ -1497,7 +1496,7 @@
               n = force;
             }
           /* Push run onto m_pending-runs stack, and maybe merge. */
-          assert (m_ms->m_n < MAX_MERGE_PENDING);
+          liboctave_panic_unless (m_ms->m_n < MAX_MERGE_PENDING);
           m_ms->m_pending[m_ms->m_n].m_base = lo;
           m_ms->m_pending[m_ms->m_n].m_len = n;
           m_ms->m_n++;
@@ -1630,7 +1629,7 @@
       octave_idx_type ofs = runs.top ().ofs;
       octave_idx_type nel = runs.top ().nel;
       runs.pop ();
-      assert (nel > 1);
+      liboctave_panic_unless (nel > 1);
 
       T *lbuf = buf + ofs;
       const T *ldata = data + rows*col;
@@ -1705,7 +1704,7 @@
       if (lo < lastrow)
         {
           // Not the final column.
-          assert (n > 1);
+          liboctave_panic_unless (n > 1);
           const T *hi = lo + n;
           const T *lst = lo;
           for (lo++; lo < hi; lo++)
--- a/liboctave/util/oct-sort.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-sort.h	Fri Apr 12 15:10:26 2024 +0200
@@ -97,9 +97,7 @@
 enum sortmode { UNSORTED = 0, ASCENDING, DESCENDING };
 
 template <typename T>
-class
-OCTAVE_TEMPLATE_API
-octave_sort
+class OCTAVE_TEMPLATE_API octave_sort
 {
 public:
 
@@ -339,9 +337,7 @@
 };
 
 template <typename T>
-class
-OCTAVE_TEMPLATE_API
-vec_index
+class OCTAVE_TEMPLATE_API vec_index
 {
 public:
   T m_vec;
--- a/liboctave/util/oct-string.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-string.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -521,7 +521,7 @@
            who.c_str (), encoding.c_str (), std::strerror (errno));
     }
 
-  octave::unwind_action free_native_str ([=] () { ::free (native_str); });
+  octave::unwind_action free_native_str ([native_str] () { ::free (native_str); });
 
   std::string retval = std::string (native_str, length);
 
@@ -551,7 +551,7 @@
            who.c_str (), encoding.c_str (), std::strerror (errno));
     }
 
-  octave::unwind_action free_utf8_str ([=] () { ::free (utf8_str); });
+  octave::unwind_action free_utf8_str ([utf8_str] () { ::free (utf8_str); });
 
   std::string retval = std::string (reinterpret_cast<char *> (utf8_str), length);
 
@@ -597,8 +597,7 @@
                   ("%s: converting from codepage '%s' to UTF-8 failed: %s",
                    who.c_str (), fallback.c_str (), std::strerror (errno));
 
-              octave::unwind_action free_val_utf8
-                ([=] () { ::free (val_utf8); });
+              octave::unwind_action free_val_utf8 ([val_utf8] () { ::free (val_utf8); });
 
               out_str.append (reinterpret_cast<const char *> (val_utf8),
                               lengthp);
@@ -635,7 +634,7 @@
            who.c_str (), encoding.c_str (), std::strerror (errno));
     }
 
-  octave::unwind_action free_native_str ([=] () { ::free (native_str); });
+  octave::unwind_action free_native_str ([native_str] () { ::free (native_str); });
 
   std::string retval = std::string (native_str, length);
 
@@ -917,10 +916,11 @@
   if (len <= 0)
     len = 10;
 
-  static const T out_of_range_top
-    = static_cast<T> (std::numeric_limits<int>::max ()) + 1.;
-  static const T out_of_range_bottom
-    = static_cast<T> (std::numeric_limits<int>::min ()) - 1.;
+  static constexpr T out_of_range_top
+    = static_cast<T> (std::numeric_limits<int>::max ()) + 1.0;
+  static constexpr T out_of_range_bottom
+    = static_cast<T> (std::numeric_limits<int>::min ()) - 1.0;
+
   if (octave::math::isinf (val))
     {
       if (val > 0)
--- a/liboctave/util/oct-string.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/oct-string.h	Fri Apr 12 15:10:26 2024 +0200
@@ -179,9 +179,7 @@
   OCTAVE_DEFAULT_COPY_MOVE_DELETE (deletable_facet)
 };
 
-class
-OCTAVE_API
-codecvt_u8 : public std::codecvt<char, char, std::mbstate_t>
+class OCTAVE_API codecvt_u8 : public std::codecvt<char, char, std::mbstate_t>
 {
 public:
 
--- a/liboctave/util/octave-preserve-stream-state.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/octave-preserve-stream-state.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,8 +32,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-preserve_stream_state
+class preserve_stream_state
 {
 public:
 
--- a/liboctave/util/pathsearch.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/pathsearch.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -108,10 +108,35 @@
 
   if (! octave_kpse_initialized)
     {
-      std::string val = sys::env::getenv ("KPATHSEA_DEBUG");
+      std::string env_val = sys::env::getenv ("KPATHSEA_DEBUG");
+
+      if (! env_val.empty ())
+        {
+          unsigned int env_debug_flags = 0;
+
+          try
+            {
+              unsigned long val = std::stoul (env_val);
 
-      if (! val.empty ())
-        kpse_debug |= atoi (val.c_str ());
+              if (val > std::numeric_limits<unsigned int>::max ())
+                (*current_liboctave_warning_with_id_handler)
+                  ("Octave:kpathsea-debug-value-ignored", "directory_path::init: ignoring out of range KPATHSEA_DEBUG value '%s'", env_val.c_str ());
+              else
+                env_debug_flags = val;
+            }
+          catch (const std::invalid_argument&)
+              {
+                (*current_liboctave_warning_with_id_handler)
+                  ("Octave:kpathsea-debug-value-ignored", "directory_path::init: ignoring invalid KPATHSEA_DEBUG value '%s'", env_val.c_str ());
+              }
+            catch (const std::out_of_range&)
+              {
+                (*current_liboctave_warning_with_id_handler)
+                  ("Octave:kpathsea-debug-value-ignored", "directory_path::init: ignoring out of range KPATHSEA_DEBUG value '%s'", env_val.c_str ());
+              }
+
+          kpse_debug |= env_debug_flags;
+        }
 
       octave_kpse_initialized = true;
     }
--- a/liboctave/util/pathsearch.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/pathsearch.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,9 +33,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-directory_path
+class OCTAVE_API directory_path
 {
 public:
 
--- a/liboctave/util/quit.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/quit.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -38,7 +38,7 @@
 
 std::atomic<sig_atomic_t> octave_interrupt_state{0};
 
-volatile std::atomic<bool> octave_signal_caught{false};
+std::atomic<bool> octave_signal_caught{false};
 
 void (*octave_signal_hook) () = nullptr;
 void (*octave_interrupt_hook) () = nullptr;
--- a/liboctave/util/quit.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/quit.h	Fri Apr 12 15:10:26 2024 +0200
@@ -48,7 +48,7 @@
 {
 public:
 
-  frame_info (void) = default;
+  frame_info () = default;
 
   frame_info (const std::string& file_name, const std::string& fcn_name,
               int line, int column)
@@ -60,15 +60,15 @@
 
   frame_info& operator = (const frame_info&) = default;
 
-  ~frame_info (void) = default;
+  ~frame_info () = default;
 
-  std::string file_name (void) const { return m_file_name; }
+  std::string file_name () const { return m_file_name; }
 
-  std::string fcn_name (void) const { return m_fcn_name; }
+  std::string fcn_name () const { return m_fcn_name; }
 
-  int line (void) const { return m_line; }
+  int line () const { return m_line; }
 
-  int column (void) const { return m_column; }
+  int column () const { return m_column; }
 
 private:
 
@@ -107,35 +107,35 @@
 
   execution_exception& operator = (const execution_exception&) = default;
 
-  ~execution_exception (void) = default;
+  ~execution_exception () = default;
 
   void set_err_type (const std::string& et)
   {
     m_err_type = et;
   }
 
-  std::string err_type (void) const { return m_err_type; }
+  std::string err_type () const { return m_err_type; }
 
-  virtual std::string stack_trace (void) const;
+  virtual std::string stack_trace () const;
 
   void set_identifier (const std::string& id)
   {
     m_id = id;
   }
 
-  virtual std::string identifier (void) const { return m_id; }
+  virtual std::string identifier () const { return m_id; }
 
   void set_message (const std::string& msg)
   {
     m_message = msg;
   }
 
-  std::string message (void) const { return m_message; }
+  std::string message () const { return m_message; }
 
   // Provided for std::exception interface.
-  const char * what (void) const noexcept { return m_message.c_str (); }
+  const char * what () const noexcept { return m_message.c_str (); }
 
-  virtual stack_info_type stack_info (void) const
+  virtual stack_info_type stack_info () const
   {
     return m_stack_info;
   }
@@ -169,11 +169,11 @@
 
   OCTAVE_DEFAULT_COPY_MOVE_DELETE (exit_exception)
 
-  const char * what (void) const noexcept { return "exit exception"; }
+  const char * what () const noexcept { return "exit exception"; }
 
-  int exit_status (void) const { return m_exit_status; }
+  int exit_status () const { return m_exit_status; }
 
-  bool safe_to_return (void) const { return m_safe_to_return; }
+  bool safe_to_return () const { return m_safe_to_return; }
 
 private:
 
@@ -186,15 +186,15 @@
 {
 public:
 
-  interrupt_exception (void) = default;
+  interrupt_exception () = default;
 
   interrupt_exception (const interrupt_exception&) = default;
 
   interrupt_exception& operator = (const interrupt_exception&) = default;
 
-  ~interrupt_exception (void) = default;
+  ~interrupt_exception () = default;
 
-  const char * what (void) const noexcept { return "interrupt exception"; }
+  const char * what () const noexcept { return "interrupt exception"; }
 };
 
 OCTAVE_END_NAMESPACE(octave)
@@ -226,7 +226,7 @@
 
 extern OCTAVE_API std::atomic<int> octave_interrupt_state;
 
-extern OCTAVE_API volatile std::atomic<bool> octave_signal_caught;
+extern OCTAVE_API std::atomic<bool> octave_signal_caught;
 
 #endif
 
@@ -234,7 +234,7 @@
 
 #if defined (__cplusplus)
 
-inline void octave_quit (void)
+inline void octave_quit ()
 {
   bool expected = true;
 
@@ -286,8 +286,8 @@
 /* These should only be declared for C++ code, and should also be
    outside of any extern "C" block.  */
 
-extern OCTAVE_API void (*octave_signal_hook) (void);
-extern OCTAVE_API void (*octave_interrupt_hook) (void);
+extern OCTAVE_API void (*octave_signal_hook) ();
+extern OCTAVE_API void (*octave_interrupt_hook) ();
 
 #endif
 
--- a/liboctave/util/singleton-cleanup.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/singleton-cleanup.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,9 +30,7 @@
 
 #include <set>
 
-class
-OCTAVE_API
-singleton_cleanup_list
+class OCTAVE_API singleton_cleanup_list
 {
 protected:
 
--- a/liboctave/util/str-vec.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/str-vec.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -78,7 +78,7 @@
 {
   // Don't use Array<std::string>::sort () to allow sorting in place.
   octave_sort<std::string> lsort;
-  lsort.sort (m_data.fortran_vec (), numel ());
+  lsort.sort (m_data.rwdata (), numel ());
 
   if (make_uniq)
     uniq ();
--- a/liboctave/util/str-vec.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/str-vec.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,9 +34,7 @@
 
 #include "Array.h"
 
-class
-OCTAVE_API
-string_vector
+class OCTAVE_API string_vector
 {
 public:
 
--- a/liboctave/util/unwind-prot.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/unwind-prot.h	Fri Apr 12 15:10:26 2024 +0200
@@ -37,9 +37,7 @@
 
 OCTAVE_BEGIN_NAMESPACE(octave)
 
-class
-OCTAVE_API
-unwind_protect : public action_container
+class OCTAVE_API unwind_protect : public action_container
 {
 public:
 
@@ -92,9 +90,7 @@
 // of seeing an exception (or interrupt) in the cleanup actions.
 // Not that we can do much about it, but at least we won't crash.
 
-class
-OCTAVE_API
-unwind_protect_safe : public unwind_protect
+class OCTAVE_API unwind_protect_safe : public unwind_protect
 {
 private:
 
--- a/liboctave/util/url-transfer.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/url-transfer.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -425,7 +425,7 @@
   {
     struct curl_slist *slist = nullptr;
 
-    unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); });
+    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });
 
     std::string cmd = "rnfr " + oldname;
     slist = curl_slist_append (slist, cmd.c_str ());
@@ -597,7 +597,7 @@
 
     struct curl_slist *slist = nullptr;
 
-    unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); });
+    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });
 
     slist = curl_slist_append (slist, "pwd");
     SETOPTR (CURLOPT_POSTQUOTE, slist);
@@ -688,7 +688,7 @@
   {
     struct curl_slist *slist = nullptr;
 
-    unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); });
+    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });
 
     if (param.numel () >= 2)
       {
@@ -715,7 +715,7 @@
 
     SETOPT (CURLOPT_URL, m_host_or_url.c_str ());
 
-    unwind_action cleanup_mime ([=] () { curl_mime_free (mime); });
+    unwind_action cleanup_mime ([mime] () { curl_mime_free (mime); });
 
     if (param.numel () >= 2)
       {
@@ -890,7 +890,7 @@
   {
     struct curl_slist *slist = nullptr;
 
-    unwind_action cleanup_slist ([=] () { curl_slist_free_all (slist); });
+    unwind_action cleanup_slist ([slist] () { curl_slist_free_all (slist); });
 
     std::string cmd = action + ' ' + file_or_dir;
 
--- a/liboctave/util/url-transfer.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/util/url-transfer.h	Fri Apr 12 15:10:26 2024 +0200
@@ -51,9 +51,7 @@
   std::string CertificateFilename;
 };
 
-class
-OCTAVE_API
-base_url_transfer
+class OCTAVE_API base_url_transfer
 {
 public:
 
@@ -160,9 +158,7 @@
   std::ostream *m_curr_ostream;
 };
 
-class
-OCTAVE_API
-url_transfer
+class OCTAVE_API url_transfer
 {
 public:
 
--- a/liboctave/wrappers/areadlink-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/areadlink-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_areadlink_wrapper_h)
 #define octave_areadlink_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API char * octave_areadlink_wrapper (const char *name);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/async-system-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/async-system-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,13 +28,13 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API pid_t octave_async_system_wrapper (const char *cmd);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/base64-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/base64-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -33,7 +33,7 @@
 #  include <stddef.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -44,7 +44,7 @@
 octave_base64_decode_alloc_wrapper (const char *in, ptrdiff_t inlen,
                                     char **out, ptrdiff_t *outlen);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/canonicalize-file-name-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/canonicalize-file-name-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,14 +26,14 @@
 #if ! defined (octave_canonicalize_file_name_wrapper_h)
 #define octave_canonicalize_file_name_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API char *
 octave_canonicalize_file_name_wrapper (const char *name);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/dirent-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/dirent-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -30,7 +30,7 @@
 #  include <stdbool.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -44,7 +44,7 @@
 
 extern OCTAVE_API unsigned int octave_name_max_wrapper (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/fcntl-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/fcntl-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -67,7 +67,7 @@
 
 extern OCTAVE_API int octave_o_wronly_wrapper (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/filepos-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/filepos-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,13 +28,13 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 #  include <cstdio>
 #else
 #  include <stdio.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -43,7 +43,7 @@
 
 extern OCTAVE_API off_t octave_ftello_wrapper (FILE *fp);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/fpucw-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/fpucw-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_fpucw_wrappers_h)
 #define octave_fpucw_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -38,7 +38,7 @@
 
 extern OCTAVE_API void octave_end_long_double_rounding (unsigned int);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/gen-tempname-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/gen-tempname-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_gen_tempname_wrapper_h)
 #define octave_gen_tempname_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_gen_tempname_wrapper (char *tmpl);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/getopt-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/getopt-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_getopt_wrapper_h)
 #define octave_getopt_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -55,7 +55,7 @@
 extern OCTAVE_API int octave_get_opterr_wrapper (void);
 extern OCTAVE_API int octave_set_opterr_wrapper (int val);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/glob-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/glob-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_glob_wrappers_h)
 #define octave_glob_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -59,7 +59,7 @@
 
 extern OCTAVE_API int octave_fnm_period_wrapper (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/hash-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/hash-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 #  include <stddef.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -69,7 +69,7 @@
 extern OCTAVE_API void *
 octave_sha512_buffer_wrapper (const char *buf, size_t len, void *res);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/iconv-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/iconv-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_iconv_wrappers_h)
 #define octave_iconv_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -44,7 +44,7 @@
 extern OCTAVE_API const char *
 octave_iconv_canonicalize_wrapper (const char *name);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/intprops-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/intprops-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 #include "octave-config.h"
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -62,7 +62,7 @@
                                        unsigned long long int *r);
 #  endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/localcharset-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/localcharset-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_localcharset_wrapper_h)
 #define octave_localcharset_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API const char * octave_locale_charset_wrapper (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/math-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/math-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_math_wrappers_h)
 #define octave_math_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -34,7 +34,7 @@
 
 extern OCTAVE_API float octave_frexpf_wrapper (float x, int *expptr);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/mkostemp-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/mkostemp-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_mkostemp_wrapper_h)
 #define octave_mkostemp_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_mkostemp_wrapper (char *tmpl);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/mkostemps-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/mkostemps-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_mkostemps_wrapper_h)
 #define octave_mkostemps_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_mkostemps_wrapper (char *tmpl, int suffixlen);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/nanosleep-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/nanosleep-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 #  include <time.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -40,7 +40,7 @@
 octave_nanosleep_wrapper (const struct timespec *requested,
                           struct timespec *remaining);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/nproc-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/nproc-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_nproc_wrapper_h)
 #define octave_nproc_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -40,7 +40,7 @@
 extern OCTAVE_API unsigned long int
 octave_num_processors_wrapper (enum octave_nproc_query);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/octave-popen2.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/octave-popen2.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -40,7 +40,7 @@
 octave_popen2 (const char *cmd, char *const *args, bool sync_mode,
                int *fildes, const char **errmsg);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/putenv-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/putenv-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_putenv_wrapper_h)
 #define octave_putenv_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_putenv_wrapper (char *str);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/pwd-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/pwd-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -64,7 +64,7 @@
 octave_from_passwd (const struct passwd *pw,
                     struct octave_passwd_wrapper *oct_pw);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/set-program-name-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/set-program-name-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,14 +26,14 @@
 #if ! defined (octave_set_program_name_wrapper_h)
 #define octave_set_program_name_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API const char *
 octave_set_program_name_wrapper (const char *pname);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/signal-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/signal-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -102,7 +102,7 @@
 
 extern OCTAVE_API void octave_unblock_async_signals (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/stat-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/stat-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_stat_wrappers_h)
 #define octave_stat_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 #  include <ctime>
 #else
 #  include <stdbool.h>
@@ -35,7 +35,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -78,7 +78,7 @@
 extern OCTAVE_API bool octave_have_struct_stat_st_blksize (void);
 extern OCTAVE_API bool octave_have_struct_stat_st_blocks (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/strdup-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/strdup-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_strdup_wrapper_h)
 #define octave_strdup_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API char * octave_strdup_wrapper (const char *str);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/strftime-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/strftime-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_strftime_wrapper_h)
 #define octave_strftime_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 #  include <cstddef>
 #  include <ctime>
 #else
@@ -34,7 +34,7 @@
 #  include <time.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -42,7 +42,7 @@
 octave_strftime_wrapper (char *buf, size_t len, const char *fmt,
                          const struct tm *t);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/strmode-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/strmode-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -36,7 +36,7 @@
 
 extern OCTAVE_API void octave_strmode_wrapper (mode_t mode, char *buffer);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/strptime-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/strptime-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,14 +32,14 @@
 #  include <time.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API char *
 octave_strptime_wrapper (const char *p, const char *fmt, struct tm *t);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/time-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/time-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_time_wrappers_h)
 #define octave_time_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 #  include <ctime>
 #else
 #  include <time.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -57,7 +57,7 @@
 extern OCTAVE_API time_t
 octave_mktime_wrapper (struct tm *tp);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/uname-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/uname-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_uname_wrapper_h)
 #define octave_uname_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -34,7 +34,7 @@
 octave_uname_wrapper (char **sysname, char **nodename,
                       char **release, char **version, char **machine);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/unicase-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/unicase-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_unicase_wrappers_h)
 #define octave_unicase_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -40,7 +40,7 @@
                            const char *iso639_language,
                            uint8_t *resultbuf, size_t *lengthp);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/uniconv-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/uniconv-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -34,7 +34,7 @@
 #  include <stdint.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -87,7 +87,7 @@
 
 extern OCTAVE_API wchar_t * u8_to_wchar (const char *u8_char);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/unictype-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/unictype-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -28,7 +28,7 @@
 
 typedef uint32_t ucs4_t;
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -56,7 +56,7 @@
 
 extern OCTAVE_API bool octave_uc_is_xdigit_wrapper (ucs4_t uc);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/unistd-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/unistd-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -104,7 +104,7 @@
 
 extern OCTAVE_API bool octave_have_vfork (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/unistr-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/unistr-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,7 +26,7 @@
 #if ! defined (octave_unistr_wrappers_h)
 #define octave_unistr_wrappers_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -57,7 +57,7 @@
 octave_u8_to_u32_wrapper (const uint8_t *src, size_t src_len,
                           uint32_t *result_buf, size_t *lengthp);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/unsetenv-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/unsetenv-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_unsetenv_wrapper_h)
 #define octave_unsetenv_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_unsetenv_wrapper (const char *name);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/vasprintf-wrapper.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/vasprintf-wrapper.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,20 +26,20 @@
 #if ! defined (octave_vasprintf_wrapper_h)
 #define octave_vasprintf_wrapper_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 #  include <cstdarg>
 #else
 #  include <stdarg.h>
 #endif
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int
 octave_vasprintf_wrapper (char **buf, const char *fmt, va_list args);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/wait-for-input.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/wait-for-input.h	Fri Apr 12 15:10:26 2024 +0200
@@ -26,13 +26,13 @@
 #if ! defined (octave_wait_for_input_h)
 #define octave_wait_for_input_h 1
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
 extern OCTAVE_API int octave_wait_for_input (int fid);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/liboctave/wrappers/wait-wrappers.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/liboctave/wrappers/wait-wrappers.h	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,7 @@
 
 #include <sys/types.h>
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 extern "C" {
 #endif
 
@@ -61,7 +61,7 @@
 
 extern OCTAVE_API int octave_wuntraced_wrapper (void);
 
-#if defined __cplusplus
+#if defined (__cplusplus)
 }
 #endif
 
--- a/m4/acinclude.m4	Sat Apr 06 14:43:10 2024 +0200
+++ b/m4/acinclude.m4	Fri Apr 12 15:10:26 2024 +0200
@@ -1999,15 +1999,6 @@
   warn_qt_abstract_item_model=""
   warn_qt_opengl=""
 
-  if test $build_qt_gui = yes && test "$qt_version" -eq 6; then
-    ## Ensure that the C++ compiler fully supports C++17.
-    ## Preferably with GNU extensions if flags are required.
-    if test $HAVE_CXX17 -eq 0; then
-      build_qt_gui=no
-      warn_qt_cxx17="compiler doesn't support C++17; disabling Qt GUI"
-    fi
-  fi
-
   if test $build_qt_gui = yes; then
     ## Check for Qt libraries
     case "$qt_version" in
--- a/oct-conf-post-public.in.h	Sat Apr 06 14:43:10 2024 +0200
+++ b/oct-conf-post-public.in.h	Fri Apr 12 15:10:26 2024 +0200
@@ -150,7 +150,7 @@
 #  define OCTAVE_EXCEPTION_API OCTAVE_EXPORT
 #  if defined (_WIN32) || defined (__CYGWIN__)
 #    define OCTAVE_TEMPLATE_API
-#    if defined(__MINGW32__)
+#    if defined (__MINGW32__)
 #      define OCTAVE_EXTERN_TEMPLATE_API OCTAVE_EXPORT
 #      define OCTAVE_CLASS_TEMPLATE_INSTANTIATION_API
 #    else
@@ -183,7 +183,7 @@
 #  define OCTINTERP_EXCEPTION_API OCTAVE_EXPORT
 #  if defined (_WIN32) || defined (__CYGWIN__)
 #    define OCTINTERP_TEMPLATE_API
-#    if defined(__MINGW32__)
+#    if defined (__MINGW32__)
 #      define OCTINTERP_EXTERN_TEMPLATE_API OCTAVE_EXPORT
 #      define OCTINTERP_CLASS_TEMPLATE_INSTANTIATION_API
 #    else
@@ -216,7 +216,7 @@
 #  define OCTARRAY_EXCEPTION_API OCTAVE_EXPORT
 #  if defined (_WIN32) || defined (__CYGWIN__)
 #    define OCTARRAY_TEMPLATE_API
-#    if defined(__MINGW32__)
+#    if defined (__MINGW32__)
 #      define OCTARRAY_EXTERN_TEMPLATE_API OCTAVE_EXPORT
 #      define OCTARRAY_CLASS_TEMPLATE_INSTANTIATION_API
 #    else
@@ -249,7 +249,7 @@
 #  define OCTGRAPHICS_EXCEPTION_API OCTAVE_EXPORT
 #  if defined (_WIN32) || defined (__CYGWIN__)
 #    define OCTGRAPHICS_TEMPLATE_API
-#    if defined(__MINGW32__)
+#    if defined (__MINGW32__)
 #      define OCTGRAPHICS_EXTERN_TEMPLATE_API OCTAVE_EXPORT
 #      define OCTGRAPHICS_CLASS_TEMPLATE_INSTANTIATION_API
 #    else
@@ -282,7 +282,7 @@
 #  define OCTGUI_EXCEPTION_API OCTAVE_EXPORT
 #  if defined (_WIN32) || defined (__CYGWIN__)
 #    define OCTGUI_TEMPLATE_API
-#    if defined(__MINGW32__)
+#    if defined (__MINGW32__)
 #      define OCTGUI_EXTERN_TEMPLATE_API OCTAVE_EXPORT
 #      define OCTGUI_CLASS_TEMPLATE_INSTANTIATION_API
 #    else
@@ -419,9 +419,3 @@
 #if defined (OCTAVE_ENABLE_OPENMP)
 #  define HAVE_OPENMP 1
 #endif
-
-#if defined (OCTAVE_ENABLE_FLOAT_TRUNCATE)
-#  define OCTAVE_FLOAT_TRUNCATE volatile
-#else
-#  define OCTAVE_FLOAT_TRUNCATE
-#endif
--- a/scripts/deprecated/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/deprecated/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -1,9 +1,7 @@
 FCN_FILE_DIRS += %reldir%
 
 %canon_reldir%_FCN_FILES = \
-  %reldir%/.oct-config \
-  %reldir%/shift.m \
-  %reldir%/sparse_auto_mutate.m
+  %reldir%/.oct-config
 
 %canon_reldir%dir = $(fcnfiledir)/deprecated
 
--- a/scripts/deprecated/shift.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,115 +0,0 @@
-########################################################################
-##
-## Copyright (C) 1995-2024 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{y} =} shift (@var{x}, @var{b})
-## @deftypefnx {} {@var{y} =} shift (@var{x}, @var{b}, @var{dim})
-##
-## @code{shift} is deprecated and will be removed in Octave version 10.  Use
-## @code{circshift} instead.
-##
-## If @var{x} is a vector, perform a circular shift of length @var{b} of
-## the elements of @var{x}.
-##
-## If @var{x} is a matrix, do the same for each column of @var{x}.
-##
-## If the optional @var{dim} argument is given, operate along this dimension.
-## @seealso{circshift}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 10.
-
-function y = shift (x, b, dim)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "shift is deprecated and will be removed from a future version of Octave, please use circshift instead\n");
-  endif
-
-  if (nargin < 2)
-    print_usage ();
-  endif
-
-  if (numel (x) < 1)
-    error ("shift: X must not be empty");
-  elseif (! (isscalar (b) && b == fix (b)))
-    error ("shift: B must be an integer");
-  endif
-
-  nd = ndims (x);
-  sz = size (x);
-
-  if (nargin == 3)
-    if (!(isscalar (dim) && dim == fix (dim))
-        || !(1 <= dim && dim <= nd))
-      error ("shift: DIM must be an integer and a valid dimension");
-    endif
-  else
-    ## Find the first non-singleton dimension.
-    (dim = find (sz > 1, 1)) || (dim = 1);
-  endif
-
-  d = sz(dim);
-
-  idx = repmat ({':'}, nd, 1);
-  if (b > 0)
-    b = rem (b, d);
-    idx{dim} = [d-b+1:d, 1:d-b];
-  elseif (b < 0)
-    b = rem (abs (b), d);
-    idx{dim} = [b+1:d, 1:b];
-  endif
-
-  y = x(idx{:});
-
-endfunction
-
-
-%!test
-%! a = [1, 2, 3];
-%! b = [4, 5, 6];
-%! c = [7, 8, 9];
-%!
-%! r = [a, b, c];
-%! m = [a; b; c];
-%!
-%! assert (shift (r, 0), r);
-%! assert (shift (r, 3), [c, a, b]);
-%! assert (shift (r, -6), [c, a, b]);
-%! assert (shift (r, -3), [b, c, a]);
-%! assert (shift (m, 1), [c; a; b]);
-%! assert (shift (m, -2), [c; a; b]);
-
-## Test input validation
-%!error <Invalid call> shift ()
-%!error <Invalid call> shift (1)
-%!error <X must not be empty> shift ([], 1)
-%!error <B must be an integer> shift (ones (2), ones (2))
-%!error <B must be an integer> shift (ones (2), 1.5)
-%!error <DIM must be an integer> shift (1, 1, 1.5)
-%!error <DIM must be .* a valid dimension> shift (1, 1, 0)
-%!error <DIM must be .* a valid dimension> shift (1, 1, 3)
--- a/scripts/deprecated/sparse_auto_mutate.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2022-2024 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} =} sparse_auto_mutate ()
-## @deftypefnx {} {@var{old_val} =} sparse_auto_mutate (@var{new_val})
-## @deftypefnx {} {@var{old_val} =} sparse_auto_mutate (@var{new_val}, "local")
-##
-## @code{sparse_auto_mutate} is deprecated and will be removed in Octave
-## version 10.
-##
-## The @code{sparse_auto_mutate} function no longer has any effect on Octave's
-## behavior.  Previously, after calling @code{sparse_auto_mutate (true)},
-## Octave would automatically convert sparse matrices to full when a sparse
-## matrix required more memory than simply using full matrix storage.  This
-## setting was false by default for compatibility with @sc{matlab}.  Now you
-## must manually convert to full storage when desired (use @code{full}).
-## @seealso{full}
-## @end deftypefn
-
-## FIXME: DEPRECATED: Remove in version 10.
-
-function retval = sparse_auto_mutate (val, opt)
-
-  persistent warned = false;
-  if (! warned)
-    warned = true;
-    warning ("Octave:deprecated-function",
-             "sparse_auto_mutate is obsolete, has no effect, and will be removed from a future version of Octave\n");
-  endif
-
-  if (nargin == 0 || nargout > 0)
-    retval = false;  # Always false now.
-    return;
-  endif
-
-  if (nargin == 2)
-    if (! (ischar (opt) && strcmp (opt, "local")))
-      error ('sparse_auto_mutate: second argument must be "local"');
-    endif
-    nargin = 1;
-  endif
-
-  ## Don't bother warning that "local" is invalid outside of a function.
-  if (nargin > 1)
-    print_usage ();
-  endif
-
-  if (! islogical (val))
-    error ("sparse_auto_mutate: argument must be a logical value");
-  endif
-
-endfunction
--- a/scripts/general/nextpow2.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/general/nextpow2.m	Fri Apr 12 15:10:26 2024 +0200
@@ -25,16 +25,17 @@
 
 ## -*- texinfo -*-
 ## @deftypefn {} {@var{n} =} nextpow2 (@var{x})
-## Compute the exponent for the smallest power of two larger than the input.
+## Compute the exponent of the next power of two not smaller than the input.
 ##
-## For each element in the input array @var{x}, return the first integer
+## For each element in the input array @var{x}, return the smallest integer
 ## @var{n} such that
 ## @tex
 ## $2^n \ge |x|$.
 ## @end tex
 ## @ifnottex
-## 2^n @geq{} abs (x).
+## @code{2^@var{n} @geq{} abs (@var{x})}.
 ## @end ifnottex
+## For input elements equal to zero, return zero.
 ##
 ## @seealso{pow2, log2}
 ## @end deftypefn
@@ -47,10 +48,23 @@
 
   if (! isnumeric (x))
     error ("nextpow2: X must be numeric");
+  elseif (! isreal (x))
+    error ("nextpow2: X must be real");
   endif
 
-  n = ceil (log2 (abs (x)));
-  n(x == 0) = 0;  # special case
+  [f, n] = log2 (abs (x));
+  n(f == 0.5)--;
+
+  if (isfloat (x))
+    idx_nan = isnan (x);
+    n(idx_nan) = x(idx_nan);
+    n(isinf (x)) = Inf;
+  else
+    n = cast (n, class (x));
+    if (intmax (x) > flintmax ())
+      n((2 .^ n) < abs (x))++;
+    endif
+  endif
 
 endfunction
 
@@ -70,8 +84,75 @@
 %!assert (nextpow2 (Inf), Inf)
 %!assert (nextpow2 (-Inf), Inf)
 %!assert (nextpow2 (NaN), NaN)
-%!assert (nextpow2 ([1, Inf, 3, -Inf, 9, NaN]), [0, Inf, 2, Inf, 4, NaN])
+%!assert (nextpow2 (NA), NA)
+%!assert (nextpow2 ([1, Inf, 3, -Inf, 9, NaN, NA]), ...
+%!                  [0, Inf, 2,  Inf, 4, NaN, NA])
+
+%!test
+%! p = (-1074:1023).';
+%! x = 2 .^ p;
+%! x = [x, x + eps(x)];
+%! x = [x, -x];
+%! n = nextpow2 (x);
+%! assert (n(:, 1), p);
+%! assert (n(:, 3), p);
+%! assert (n(:, 2), p + 1);
+%! assert (n(:, 4), p + 1);
+
+%!assert (nextpow2 (realmax ()), 1024)
+%!assert (nextpow2 (-realmax ()), 1024)
+
+%!test
+%! p = single (-149:127).';
+%! x = 2 .^ p;
+%! x = [x, x + eps(x)];
+%! x = [x, -x];
+%! n = nextpow2 (x);
+%! assert (n(:, 1), p);
+%! assert (n(:, 3), p);
+%! assert (n(:, 2), p + 1);
+%! assert (n(:, 4), p + 1);
+
+%!assert (nextpow2 (realmax ('single')), single (128))
+%!assert (nextpow2 (-realmax ('single')), single (128))
+
+%!test
+%! p = int32 (0:30).';
+%! x = 2 .^ p;
+%! x = [x, x + 1];
+%! x = [x, -x];
+%! n = nextpow2 (x);
+%! assert (n(:, 1), p);
+%! assert (n(:, 3), p);
+%! assert (n(:, 2), p + 1);
+%! assert (n(:, 4), p + 1);
+
+%!assert (nextpow2 (int32 (0)), int32 (0))
+%!assert (nextpow2 (intmin ('int32')), int32 (31))
+%!assert (nextpow2 (intmax ('int32')), int32 (31))
+
+%!assert (nextpow2 (uint32 (0)), uint32 (0))
+%!assert (nextpow2 (intmax ('uint32')), uint32 (32))
+
+%!test
+%! p = int64 (0:62).';
+%! x = 2 .^ p;
+%! x = [x, x + 1];
+%! x = [x, -x];
+%! n = nextpow2 (x);
+%! assert (n(:, 1), p);
+%! assert (n(:, 3), p);
+%! assert (n(:, 2), p + 1);
+%! assert (n(:, 4), p + 1);
+
+%!assert (nextpow2 (int64 (0)), int64 (0))
+%!assert (nextpow2 (intmin ('int64')), int64 (63))
+%!assert (nextpow2 (intmax ('int64')), int64 (63))
+
+%!assert (nextpow2 (uint64 (0)), uint64 (0))
+%!assert (nextpow2 (intmax ('uint64')), uint64 (64))
 
 ## Test input validation
 %!error <Invalid call> nextpow2 ()
 %!error <X must be numeric> nextpow2 ("t")
+%!error <X must be real> nextpow2 (1 + 2i)
--- a/scripts/geometry/griddata.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/geometry/griddata.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,9 +40,10 @@
 ## @code{meshgrid} and @var{z} is a 2-D matrix matching the resulting size of
 ## the X-Y grid.
 ##
-## The interpolation points are (@var{xi}, @var{yi}).  If, and only if,
-## @var{xi} is a row vector and @var{yi} is a column vector, then
-## @code{meshgrid} will be used to create a mesh of interpolation points.
+## The interpolation points are (@var{xi}, @var{yi}).  If either @var{xi} or
+## @var{y} is a row vector and the other is a column vector, then
+## @code{meshgrid (@var{xi}, @var{yi})} will be used to create a mesh of
+## interpolation points.
 ##
 ## For 3-D interpolation, the inputs @var{x}, @var{y}, and @var{z} define the
 ## points where the function @code{@var{v} = f (@var{x}, @var{y}, @var{z})}
@@ -51,6 +52,10 @@
 ## a 3-D grid with @code{meshgrid}.  The size of the input @var{v} must match
 ## the size of the original data, either as a vector or a matrix.
 ##
+## The outputs @var{zi} (for 2-D) or @var{vi} (for 3-D) will contain the
+## interpolated values of @var{z} or @var{v}, respectively, with the output
+## size matching that of the interpolation points.
+##
 ## The optional input interpolation @var{method} can be @qcode{"nearest"},
 ## @qcode{"linear"}, or for 2-D data @qcode{"v4"}.  When the method is
 ## @qcode{"nearest"}, the output @var{vi} will be the closest point in the
@@ -110,18 +115,15 @@
       error ("griddata: lengths of X, Y must match the columns and rows of Z");
     endif
 
-    ## Meshgrid xi and yi if they are a row and column vector, but not
-    ## if they are simply vectors of the same size (for compatibility).
-    if (isrow (xi) && iscolumn (yi))
+    ## Meshgrid xi and yi if one is a row vector and the other is a column
+    ## vector, but not if they are vectors with the same orientation.
+    if ((isrow (xi) && iscolumn (yi)) || (iscolumn (xi) && isrow (yi)))
       [xi, yi] = meshgrid (xi, yi);
-    elseif (isvector (xi) && isvector (yi))
-      ## Otherwise, convert to column vectors
-      xi = xi(:);
-      yi = yi(:);
-    endif
-
-    if (! size_equal (xi, yi))
-      error ("griddata: XI and YI must be vectors or matrices of same size");
+    else
+      ## Ensure vector and matrix query point inputs are identically sized.
+      if (! size_equal (xi, yi))
+        error ("griddata: XI and YI must be vectors or matrices of same size");
+      endif
     endif
 
     if (nargin == 6)
@@ -334,12 +336,36 @@
 %!testif HAVE_QHULL <*65146> # Ensure correct output for 3-point queries.
 %! xi = [1 2 3];
 %! a = griddata (xi, xi, xi .* xi', xi, xi, "linear");
-%! assert (a, [1, 4, 9]', 10*eps);
+%! assert (a, [1, 4, 9], 10*eps);
 %! a = griddata (xi, xi, xi .* xi', xi', xi', "linear");
 %! assert (a, [1, 4, 9]', 10*eps);
 %! a = griddata (xi, xi, xi .* xi', [xi; xi], [xi; xi], "linear");
 %! assert (a, [1, 4, 9; 1, 4, 9], 10*eps);
 
+## Verify output orientation for various input vector shape combinations
+%!testif HAVE_QHULL <*65134>
+%! x = [1:10];
+%! y = [1:10];
+%! z = x .* y';
+%! xi = [1, 5, 10];
+%! yi = [1, 5];
+%! [xx, yy, vv] = griddata (x, y, z, xi, xi, 'nearest'); # Row, Row
+%! assert (xx, xi);
+%! assert (yy, xi);
+%! assert (size (vv), [1, 3]);
+%! [xx, yy, vv] = griddata (x, y, z, xi', xi', 'nearest'); # Col, Col
+%! assert (xx, xi');
+%! assert (yy, xi');
+%! assert (size (vv), [3, 1]);
+%! [xx, yy, vv] = griddata (x, y, z, xi, yi', 'nearest'); # Row, Col
+%! assert (xx, [xi; xi]);
+%! assert (yy, [yi', yi', yi']);
+%! assert (vv, [1, 5, 10; 5, 25, 50]);
+%! [xx, yy, vv] = griddata (x, y, z, xi', yi, 'nearest'); # Col, Row
+%! assert (xx, [xi; xi]);
+%! assert (yy, [yi', yi', yi']);
+%! assert (vv, [1, 5, 10; 5, 25, 50]);
+
 ## Test input validation
 %!error <Invalid call> griddata ()
 %!error <Invalid call> griddata (1)
@@ -354,6 +380,8 @@
 %!error <the columns and rows of Z> griddata (1:4, 1:3, ones (3,5), 1:3, 1:3)
 %!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:4, 1:3)
 %!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, 1:3, 1:4)
+%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, [1:4]', [1:3]')
+%!error <XI and YI .* matrices of same size> griddata (1:3, 1:3, 1:3, [1:3]', [1:4]')
 %!error <METHOD must be a string> griddata (1,2,3,4,5, {"linear"})
 %!error <"cubic" .* not yet implemented> griddata (1,2,3,4,5, "cubic")
 %!error <"natural" .* not yet implemented> griddata (1,2,3,4,5, "natural")
--- a/scripts/gui/uifigure.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/gui/uifigure.m	Fri Apr 12 15:10:26 2024 +0200
@@ -37,6 +37,9 @@
 ## @ref{Figure Properties}.  This function differs from @code{figure} in that
 ## the created figure is optimized for application development, rather than
 ## plotting.  This means features such as menubars and toolbars are turned off.
+## This is not perfect replacement for the @sc{matlab} uifigure object as the
+## properties @qcode{"AutoResizeChildren"}, @qcode{"Icon"}, and
+## @qcode{"Scrollable"} are not implemented.
 ## @seealso{uipanel, uibuttongroup}
 ## @end deftypefn
 
@@ -47,33 +50,43 @@
 
 function h = uifigure (varargin)
 
-  if (mod (nargin, 2) != 0)
+  if (rem (nargin, 2) != 0)
     error ("uifigure: PROPERTY/VALUE parameters must occur in pairs");
   endif
 
+  strfcn = @(s) any (strcmpi (s, {'AutoResizeChildren', 'Icon', 'Scrollable'}));
+  idx = cellfun (strfcn, varargin (1:2:end));
+  if (any (idx))
+    idx = repelem (idx, 2); 
+    props = varargin(idx);  # save special props for applying later
+    varargin(idx) = [];     # remove special props from varargin
+  endif
+
   h = __go_figure__ (NaN, "handlevisibility", "off",
                           "numbertitle", "off", "integerhandle", "off",
-                          "menubar", "none", "toolbar", "none");
+                          "menubar", "none", "toolbar", "none",
+                          varargin{:});
 
   ## Add uifigure-specific properties on top of regular figure graphics object
   ## FIXME: There is no implementation behind these properties.
   addproperty ("AutoResizeChildren", h, "boolean", "on");
+  addproperty ("Icon", h, "data", []);
   addproperty ("Scrollable", h, "boolean", "off");
 
-  ## Apply any overrides.
-  if (! isempty (varargin))
-    set (h, varargin{:});
+  ## Set values for special properties added above
+  if (! isempty (props))
+    set (h, props{:});
   endif
 
 endfunction
 
 
 %!test
-%! hf = uifigure ("visible", "off");
+%! hf = uifigure ("visible", "off", "Icon", magic (3));
 %! unwind_protect
 %!   assert (isfigure (hf));
-%!   assert (get (hf, {"numbertitle", "menubar", "scrollable"}),
-%!                    {"off", "none", "off"});
+%!   assert (get (hf, {"numbertitle", "menubar", "icon", "scrollable"}),
+%!                    {"off", "none", magic(3), "off"});
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/help/error_ids.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/help/error_ids.m	Fri Apr 12 15:10:26 2024 +0200
@@ -46,6 +46,9 @@
 ## @item Octave:invalid-input-arg
 ## Indicates that a function was called with invalid input arguments.
 ##
+## @item Octave:parse-error
+## The interpreter failed to parse (read) specified code.
+##
 ## @item Octave:undefined-function
 ## Indicates a call to a function that is not defined.  The function may exist
 ## but Octave is unable to find it in the search path.
--- a/scripts/image/autumn.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/autumn.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## This colormap ranges from red through orange to yellow.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = autumn (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("autumn: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("autumn: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -71,3 +72,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (autumn ()), [256, 3])
+%!assert (size (autumn (16)), [16, 3])
+
+%!assert (autumn (1), [1, 0, 0])
+%!assert (autumn (true), double ([1, 0, 0]))
+%!assert (autumn (char (1)), double ([1, 0, 0]))
+%!assert (autumn (int32 (1)), double ([1, 0, 0]))
+
+%!assert (autumn (0), zeros (0, 3))
+%!assert (autumn (-1), zeros (0, 3))
+
+%!assert (autumn (11), [ones(1,11); [0:0.1:1]; zeros(1,11)]', eps)
+
+## Input validation
+%!error <N must be a scalar integer> autumn ("foo")
+%!error <N must be a scalar integer> autumn ([1, 2, 3])
+%!error <N must be a scalar integer> autumn ({1, 2, 3})
--- a/scripts/image/bone.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/bone.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## gray-blue shades.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = bone (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("bone: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("bone: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -98,3 +99,29 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (bone ()), [256, 3])
+%!assert (size (bone (16)), [16, 3])
+
+%!assert (bone (1), [1/8, 1/8, 1/8])
+%!assert (bone (true), double ([1/8, 1/8, 1/8]))
+%!assert (bone (char (1)), double ([1/8, 1/8, 1/8]))
+%!assert (bone (int32 (1)), double ([1/8, 1/8, 1/8]))
+%!assert (bone (2), [1/16, 1/8, 1/8; 1 ,1, 1])
+
+%!assert (bone (0), zeros (0, 3))
+%!assert (bone (-1), zeros (0, 3))
+
+%!test
+%! a = [    0,     0,   1/8;
+%!       7/32, 11/32, 11/32;
+%!      23/48,  9/16,  9/16;
+%!      71/96, 25/32, 25/32;
+%!          1,     1,     1];
+%! assert (bone (5), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> bone ("foo")
+%!error <N must be a scalar integer> bone ([1, 2, 3])
+%!error <N must be a scalar integer> bone ({1, 2, 3})
--- a/scripts/image/colorcube.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/colorcube.m	Fri Apr 12 15:10:26 2024 +0200
@@ -34,16 +34,25 @@
 ## blue, and gray.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = colorcube (n)
 
-  if (nargin == 0)
-    n = rows (colormap);
-  elseif (! isscalar (n))
-    error ("colorcube: N must be a scalar");
+  if (nargin == 1)
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("colorcube: N must be a scalar integer");
+    endif
+    n = double (n);
+  else
+    hf = get (0, "currentfigure");
+    if (! isempty (hf))
+      n = rows (get (hf, "colormap"));
+    else
+      n = 256;
+    endif
   endif
 
   if (n < 9)
@@ -99,3 +108,37 @@
 %! axis ([1, 64, 0, 1], "xy");
 %! set (gca, "xtick", []);
 %! colormap (colorcube (64));
+
+
+%!assert (size (colorcube ()), [256, 3])
+%!assert (size (colorcube (16)), [16, 3])
+
+%!assert (colorcube (1), [0, 0, 0])
+%!assert (colorcube (true), double ([0, 0, 0]))
+%!assert (colorcube (char (1)), double ([0, 0, 0]))
+%!assert (colorcube (int32 (1)), double ([0, 0, 0]))
+
+%!assert (colorcube (0), zeros (0, 3))
+%!assert (colorcube (-1), zeros (0, 3))
+
+%!assert (colorcube (8), gray (8))
+
+%!test
+%! a = [1,   1,   0;
+%!      0,   1,   1;
+%!      1,   0,   1;
+%!      0.5, 0,   0;
+%!      1,   0,   0;
+%!      0,   0.5, 0;
+%!      0,   1,   0;
+%!      0,   0,   0.5;
+%!      0,   0,   1;
+%!      0,   0,   0;
+%!      0.5, 0.5, 0.5;
+%!      1,   1,   1];
+%! assert (colorcube (12), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> colorcube ("foo")
+%!error <N must be a scalar integer> colorcube ([1, 2, 3])
+%!error <N must be a scalar integer> colorcube ({1, 2, 3})
--- a/scripts/image/colormap.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/colormap.m	Fri Apr 12 15:10:26 2024 +0200
@@ -32,7 +32,9 @@
 ## @deftypefnx {} {} colormap @var{map_name}
 ## Query or set the current colormap.
 ##
-## With no input arguments, @code{colormap} returns the current color map.
+## With no input arguments, @code{colormap} returns the current color map.  If
+## there is no current figure, a new figure will be opened and the default
+## color map will be returned.
 ##
 ## @code{colormap (@var{map})} sets the current colormap to @var{map}.  The
 ## colormap should be an @var{n} row by 3 column matrix.  The columns
@@ -40,7 +42,7 @@
 ## must be between 0 and 1 inclusive.  The new colormap is returned.
 ##
 ## @code{colormap (@qcode{"default"})} restores the default colormap (the
-## @code{viridis} map with 64 entries).  The default colormap is returned.
+## @code{viridis} map with 256 entries).  The default colormap is returned.
 ##
 ## The map may also be specified by a string, @var{map_name}, which
 ## is the name of a function that returns a colormap.
@@ -108,7 +110,7 @@
     if (ischar (map))
       map = lower (map);
       if (strcmp (map, "default"))
-        map = viridis (64);
+        map = viridis (256);
       else
         try
           map = feval (map);
@@ -169,9 +171,9 @@
 %!   cmap = (get (gcf, "colormap"));
 %!   assert (cmap, cmaptst);
 %!   colormap ("default");
-%!   assert (colormap (), viridis (64));
+%!   assert (colormap (), viridis (256));
 %!   colormap ("ocean");
-%!   assert (colormap, ocean (64));
+%!   assert (colormap, ocean (256));
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
--- a/scripts/image/cool.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/cool.m	Fri Apr 12 15:10:26 2024 +0200
@@ -29,15 +29,16 @@
 ## Create color colormap.  The colormap varies from cyan to magenta.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = cool (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("cool: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("cool: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -45,7 +46,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -70,3 +71,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (cool ()), [256, 3])
+%!assert (size (cool (16)), [16, 3])
+
+%!assert (cool (1), [0, 1, 1])
+%!assert (cool (true), double ([0, 1, 1]))
+%!assert (cool (char (1)), double ([0, 1, 1]))
+%!assert (cool (int32 (1)), double ([0, 1, 1]))
+
+%!assert (cool (0), zeros (0, 3))
+%!assert (cool (-1), zeros (0, 3))
+
+%!assert (cool (11), [[0:0.1:1]; [1:-0.1:0]; ones(1,11)]', eps)
+
+## Input validation
+%!error <N must be a scalar integer> cool ("foo")
+%!error <N must be a scalar integer> cool ([1, 2, 3])
+%!error <N must be a scalar integer> cool ({1, 2, 3})
--- a/scripts/image/copper.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/copper.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## tone.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = copper (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("copper: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("copper: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -73,3 +74,25 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (copper ()), [256, 3])
+%!assert (size (copper (16)), [16, 3])
+
+%!assert (copper (1), [0, 0, 0])
+%!assert (copper (true), double ([0, 0, 0]))
+%!assert (copper (char (1)), double ([0, 0, 0]))
+%!assert (copper (int32 (1)), double ([0, 0, 0]))
+
+%!assert (copper (0), zeros (0, 3))
+%!assert (copper (-1), zeros (0, 3))
+
+%!test
+%! a = [0.25, 0.15624, 0.0995] .* [0:5]';
+%! a(6) = 1;
+%! assert (copper (6), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> copper ("foo")
+%!error <N must be a scalar integer> copper ([1, 2, 3])
+%!error <N must be a scalar integer> copper ({1, 2, 3})
--- a/scripts/image/cubehelix.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/cubehelix.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,8 @@
 ## @end example
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ##
 ## Reference: Green, D. A., 2011,
 ## @cite{A @nospell{colour} scheme for the display of astronomical intensity
@@ -52,8 +53,8 @@
 function map = cubehelix (n, start = 0.5, rots = -1.5, hue = 1, gamma = 1)
 
   if (nargin > 0)
-    if (! isscalar (n))
-      error ("cubehelix: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("cubehelix: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -61,7 +62,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -96,3 +97,33 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (cubehelix ()), [256, 3])
+%!assert (size (cubehelix (16)), [16, 3])
+
+%!assert (cubehelix (1), [0,0,0])
+%!assert (cubehelix (true), double ([0,0,0]))
+%!assert (cubehelix (char (1)), double ([0,0,0]))
+%!assert (cubehelix (int32 (1)), double ([0,0,0]))
+
+%!assert (cubehelix (0), zeros (0, 3))
+%!assert (cubehelix (-1), zeros (0, 3))
+
+%!assert (cubehelix (2), [0, 0, 0; 1, 1, 1])
+%!assert ([cubehelix]([1,end],:), [0, 0, 0; 1, 1, 1])
+
+%!shared a
+%! a = [0,                   0,                   0;
+%!      0.17004232121057959, 0.43679759647517287, 0.22372555555555556;
+%!      0.82995767878942041, 0.56320240352482713, 0.77627444444444445;
+%!      1,                   1,                   1];
+
+%!assert (cubehelix (4), a, eps)
+
+%!shared  # Clear shared varibles to avoid echo on unrelated test errors.
+
+## Input validation
+%!error <N must be a scalar integer> cubehelix ("foo")
+%!error <N must be a scalar integer> cubehelix ([1, 2, 3])
+%!error <N must be a scalar integer> cubehelix ({1, 2, 3})
--- a/scripts/image/flag.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/flag.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## black with each index change.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = flag (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("flag: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("flag: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   if (n == 1)
@@ -68,3 +69,36 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+
+%!assert (size (flag ()), [256, 3])
+%!assert (size (flag (16)), [16, 3])
+
+%!assert (flag (1), [1, 0, 0])
+%!assert (flag (true), double ([1, 0, 0]))
+%!assert (flag (char (1)), double ([1, 0, 0]))
+%!assert (flag (int32 (1)), double ([1, 0, 0]))
+
+%!assert (flag (0), zeros (0, 3))
+%!assert (flag (-1), zeros (0, 3))
+
+%!test
+%! a = [1,   0,   0;
+%!      1,   1,   1;
+%!      0,   0,   1;
+%!      0,   0,   0;
+%!      1,   0,   0;
+%!      1,   1,   1;
+%!      0,   0,   1;
+%!      0,   0,   0;
+%!      1,   0,   0;
+%!      1,   1,   1;
+%!      0,   0,   1;
+%!      0,   0,   0];
+%! assert (flag (12), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> flag ("foo")
+%!error <N must be a scalar integer> flag ([1, 2, 3])
+%!error <N must be a scalar integer> flag ({1, 2, 3})
--- a/scripts/image/gray.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/gray.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## of gray.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = gray (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("gray: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("gray: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -69,3 +70,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (gray ()), [256, 3])
+%!assert (size (gray (16)), [16, 3])
+
+%!assert (gray (1), [0, 0, 0])
+%!assert (gray (true), double ([0, 0, 0]))
+%!assert (gray (char (1)), double ([0, 0, 0]))
+%!assert (gray (int32 (1)), double ([0, 0, 0]))
+
+%!assert (gray (0), zeros (0, 3))
+%!assert (gray (-1), zeros (0, 3))
+
+%!assert (gray (11), [0:.1:1]' .* [1, 1, 1], eps)
+
+## Input validation
+%!error <N must be a scalar integer> gray ("foo")
+%!error <N must be a scalar integer> gray ([1, 2, 3])
+%!error <N must be a scalar integer> gray ({1, 2, 3})
--- a/scripts/image/hot.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/hot.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## red, orange, yellow, to white.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = hot (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("hot: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("hot: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   if (n == 1)
@@ -86,3 +87,35 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+%!assert (size (hot ()), [256, 3])
+%!assert (size (hot (16)), [16, 3])
+
+%!assert (hot (1), [1, 1, 1])
+%!assert (hot (true), double ([1, 1, 1]))
+%!assert (hot (char (1)), double ([1, 1, 1]))
+%!assert (hot (int32 (1)), double ([1, 1, 1]))
+%!assert (hot (2), [1, 1, 1/2; 1, 1, 1])
+%!assert (hot (3), [1, 0, 0; 1, 1, 0; 1 1 1])
+
+%!assert (hot (0), zeros (0, 3))
+%!assert (hot (-1), zeros (0, 3))
+
+%!test
+%! a = [0.25, 0,    0;
+%!      0.50, 0,    0;
+%!      0.75, 0,    0;
+%!      1,    0,    0;
+%!      1,    0.25, 0;
+%!      1,    0.50, 0;
+%!      1,    0.75, 0;
+%!      1,    1,    0;
+%!      1,    1,    1/3;
+%!      1,    1,    2/3;
+%!      1,    1,    1];
+%! assert (hot (11), a, eps);
+
+## Input validation
+%!error <N must be a scalar integer> hot ("foo")
+%!error <N must be a scalar integer> hot ([1, 2, 3])
+%!error <N must be a scalar integer> hot ({1, 2, 3})
--- a/scripts/image/hsv.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/hsv.m	Fri Apr 12 15:10:26 2024 +0200
@@ -35,15 +35,16 @@
 ## @code{hsv2rgb ([(0:N-1)'/N, ones(N,2)])}.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = hsv (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("hsv: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("hsv: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -51,7 +52,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -75,3 +76,21 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+%!assert (size (hsv ()), [256, 3])
+%!assert (size (hsv (16)), [16, 3])
+
+%!assert (hsv (1), [1, 0, 0])
+%!assert (hsv (true), double ([1, 0, 0]))
+%!assert (hsv (char (1)), double ([1, 0, 0]))
+%!assert (hsv (int32 (1)), double ([1, 0, 0]))
+
+%!assert (hsv (0), zeros (0, 3))
+%!assert (hsv (-1), zeros (0, 3))
+
+%!assert (hsv (6)(:), [1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1]')
+
+## Input validation
+%!error <N must be a scalar integer> hsv ("foo")
+%!error <N must be a scalar integer> hsv ([1, 2, 3])
+%!error <N must be a scalar integer> hsv ({1, 2, 3})
--- a/scripts/image/image.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/image.m	Fri Apr 12 15:10:26 2024 +0200
@@ -186,15 +186,6 @@
       if (isempty (get (hax, "children")))
         axis (hax, "tight");
       endif
-
-      if (ndims (img) == 3)
-        if (isinteger (img))
-          mn = intmin (img);
-          mx = intmax (img);
-          set (hax, "clim", double ([mn, mx]));
-        endif
-      endif
-
     endif  # ! isempty (img)
 
     set (hax, "view", [0, 90], "ydir", "reverse", "layer", "top", "box", "on");
--- a/scripts/image/imagesc.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/imagesc.m	Fri Apr 12 15:10:26 2024 +0200
@@ -55,7 +55,7 @@
 ## and inserts it in the current axes.  The full list of properties is
 ## documented at @ref{Image Properties}.
 ##
-## @seealso{image, imshow, caxis}
+## @seealso{image, imshow, clim}
 ## @end deftypefn
 
 function h = imagesc (varargin)
--- a/scripts/image/jet.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/jet.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,7 +30,8 @@
 ## cyan, green, yellow, red, to dark red.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ##
 ## Programming Note: The @code{jet} colormap is not perceptually uniform.
 ## Try the @code{viridis} colormap if that is important.  For a drop-in
@@ -42,8 +43,8 @@
 function map = jet (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("jet: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("jet: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -51,7 +52,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   if (n == 1)
@@ -110,3 +111,28 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (jet ()), [256, 3])
+%!assert (size (jet (16)), [16, 3])
+
+%!assert (jet (1), [0, 1, 1])
+%!assert (jet (true), double ([0, 1, 1]))
+%!assert (jet (char (1)), double ([0, 1, 1]))
+%!assert (jet (int32 (1)), double ([0, 1, 1]))
+%!assert (jet (2), [0, 0, 1; 0, 1, 1])
+
+%!assert (jet (0), zeros (0, 3))
+%!assert (jet (-1), zeros (0, 3))
+
+%!test
+%! a = zeros(15, 3);
+%! a([3:13],2) = [0.25, 0.5, 0.75, 1, 1, 1, 1, 1, 0.75, 0.5, 0.25];
+%! a([7:15], 1) = a([3:11], 2);
+%! a(:,3) = flipud (a(:,1));
+%! assert (jet (15), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> jet ("foo")
+%!error <N must be a scalar integer> jet ([1, 2, 3])
+%!error <N must be a scalar integer> jet ({1, 2, 3})
--- a/scripts/image/lines.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/lines.m	Fri Apr 12 15:10:26 2024 +0200
@@ -31,7 +31,8 @@
 ## orange, yellow, purple, green, light blue, and dark red.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
@@ -39,15 +40,15 @@
 
   hf = get (groot, "currentfigure");
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("lines: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("lines: N must be a scalar integer");
     endif
     n = double (n);
   else
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -76,3 +77,25 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (lines ()), [256, 3])
+%!assert (size (lines (16)), [16, 3])
+
+%!assert (lines (1), [0, 0, 1])
+%!assert (lines (true), double ([0, 0, 1]))
+%!assert (lines (char (1)), double ([0, 0, 1]))
+%!assert (lines (int32 (1)), double ([0, 0, 1]))
+
+%!assert (lines (0), zeros (0, 3))
+%!assert (lines (-1), zeros (0, 3))
+
+%!test
+%! a = get (groot, "defaultaxescolororder");
+%! nr = rows (a);
+%! assert (lines (3*nr), [a;a;a]);
+
+## Input validation
+%!error <N must be a scalar integer> lines ("foo")
+%!error <N must be a scalar integer> lines ([1, 2, 3])
+%!error <N must be a scalar integer> lines ({1, 2, 3})
--- a/scripts/image/movie.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/movie.m	Fri Apr 12 15:10:26 2024 +0200
@@ -106,7 +106,7 @@
       error ("movie: N must be a nonzero integer");
     endif
 
-    if (! isscalar (n))
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
       idx = n(2:end)(:)';
       n = n(1);
       if (! isindex (idx, numel (mov)))
--- a/scripts/image/ocean.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/ocean.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## of blue.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = ocean (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("ocean: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("ocean: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -78,3 +79,30 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (ocean ()), [256, 3])
+%!assert (size (ocean (16)), [16, 3])
+
+%!assert (ocean (1), [0, 0, 0])
+%!assert (ocean (true), double ([0, 0, 0]))
+%!assert (ocean (char (1)), double ([0, 0, 0]))
+%!assert (ocean (int32 (1)), double ([0, 0, 0]))
+
+%!assert (ocean (0), zeros (0, 3))
+%!assert (ocean (-1), zeros (0, 3))
+
+%!assert (ocean()(1,:), [0, 0, 0])
+%!assert (ocean()(end,:), [1, 1, 1])
+
+%!test
+%! a = zeros (11, 3);
+%! a([9:11],1) = [1/3, 2/3, 1];
+%! a([6:11], 2) = 1/6:1/6:1;
+%! a(:, 3) = 0:.1:1;
+%! assert (ocean (11), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> ocean ("foo")
+%!error <N must be a scalar integer> ocean ([1, 2, 3])
+%!error <N must be a scalar integer> ocean ({1, 2, 3})
--- a/scripts/image/pink.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/pink.m	Fri Apr 12 15:10:26 2024 +0200
@@ -32,15 +32,16 @@
 ## This colormap gives a sepia tone when used on grayscale images.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = pink (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("pink: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("pink: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -48,7 +49,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   if (n == 1)
@@ -88,3 +89,29 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (pink ()), [256, 3])
+%!assert (size (pink (16)), [16, 3])
+
+%!assert (pink (1), sqrt ([1/3, 1/3, 1/3]), eps)
+%!assert (pink (true), double (sqrt ([1/3, 1/3, 1/3])), eps)
+%!assert (pink (char (1)), double (sqrt ([1/3, 1/3, 1/3])), eps)
+%!assert (pink (int32 (1)), double (sqrt ([1/3, 1/3, 1/3])), eps)
+%!assert (pink (2), sqrt ([1/3, 1/3, 1/6; 1, 1, 1]))
+
+%!assert (pink (0), zeros (0, 3))
+%!assert (pink (-1), zeros (0, 3))
+%!assert (pink()(end,:), [1 1 1], eps)
+
+%!test
+%! a = sqrt ([1/3, 0,   0;
+%!            5/9, 5/9, 2/9;
+%!            7/9, 7/9, 11/18;
+%!            1,   1,   1]);
+%! assert (pink (4), a, eps)
+
+## Input validation
+%!error <N must be a scalar integer> pink ("foo")
+%!error <N must be a scalar integer> pink ([1, 2, 3])
+%!error <N must be a scalar integer> pink ({1, 2, 3})
--- a/scripts/image/prism.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/prism.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,15 +30,16 @@
 ## green, blue and violet with each index change.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = prism (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("prism: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("prism: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -46,7 +47,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   if (n == 1)
@@ -68,3 +69,25 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (prism ()), [256, 3])
+%!assert (size (prism (16)), [16, 3])
+
+%!assert (prism (1), [1, 0, 0])
+%!assert (prism (true), double ([1, 0, 0]))
+%!assert (prism (char (1)), double ([1, 0, 0]))
+%!assert (prism (int32 (1)), double ([1, 0, 0]))
+
+%!assert (prism (0), zeros (0, 3))
+%!assert (prism (-1), zeros (0, 3))
+
+%!test
+%! a = [1, 0, 0; 1, 1/2, 0; 1, 1, 0; 0, 1, 0; 0, 0, 1; 2/3, 0, 1];
+%! nr = rows (a);
+%! assert (prism (3*nr), [a;a;a]);
+
+## Input validation
+%!error <N must be a scalar integer> prism ("foo")
+%!error <N must be a scalar integer> prism ([1, 2, 3])
+%!error <N must be a scalar integer> prism ({1, 2, 3})
--- a/scripts/image/rainbow.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/rainbow.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,7 +30,8 @@
 ## yellow, green, blue, to violet.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
@@ -40,8 +41,8 @@
 function map = rainbow (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("rainbow: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("rainbow: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -49,7 +50,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -84,3 +85,21 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+%!assert (size (rainbow ()), [256, 3])
+%!assert (size (rainbow (16)), [16, 3])
+
+%!assert (rainbow (1), [1, 0, 0])
+%!assert (rainbow (true), double ([1, 0, 0]))
+%!assert (rainbow (char (1)), double ([1, 0, 0]))
+%!assert (rainbow (int32 (1)), double ([1, 0, 0]))
+
+%!assert (rainbow (0), zeros (0, 3))
+%!assert (rainbow (-1), zeros (0, 3))
+
+%!assert (rainbow (6)(:), [1, 1, 1, 0, 0, 2/3, 0, 0.5, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1]', 3*eps)
+
+## Input validation
+%!error <N must be a scalar integer> rainbow ("foo")
+%!error <N must be a scalar integer> rainbow ([1, 2, 3])
+%!error <N must be a scalar integer> rainbow ({1, 2, 3})
--- a/scripts/image/spring.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/spring.m	Fri Apr 12 15:10:26 2024 +0200
@@ -29,15 +29,16 @@
 ## Create color colormap.  This colormap varies from magenta to yellow.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = spring (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("spring: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("spring: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -45,7 +46,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -70,3 +71,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (spring ()), [256, 3])
+%!assert (size (spring (16)), [16, 3])
+%!assert (all ((spring ()(:, 1)) == 1), true)
+%!assert (spring (11)(:,2:3), [[0:0.1:1]; [1:-0.1:0]]', eps)
+
+%!assert (spring (1), [1, 0, 1])
+%!assert (spring (true), double ([1, 0, 1]))
+%!assert (spring (char (1)), double ([1, 0, 1]))
+%!assert (spring (int32 (1)), double ([1, 0, 1]))
+
+%!assert (spring (0), zeros (0, 3))
+%!assert (spring (-1), zeros (0, 3))
+
+## Input validation
+%!error <N must be a scalar integer> spring ("foo")
+%!error <N must be a scalar integer> spring ([1, 2, 3])
+%!error <N must be a scalar integer> spring ({1, 2, 3})
--- a/scripts/image/summer.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/summer.m	Fri Apr 12 15:10:26 2024 +0200
@@ -29,15 +29,16 @@
 ## Create color colormap.  This colormap varies from green to yellow.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = summer (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("summer: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("summer: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -45,7 +46,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -70,3 +71,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (summer ()), [256, 3])
+%!assert (size (summer (16)), [16, 3])
+
+%!assert (summer (1), [0, 0.5, 0.4])
+%!assert (summer (true), double ([0, 0.5, 0.4]))
+%!assert (summer (char (1)), double ([0, 0.5, 0.4]))
+%!assert (summer (int32 (1)), double ([0, 0.5, 0.4]))
+
+%!assert (summer (0), zeros (0, 3))
+%!assert (summer (-1), zeros (0, 3))
+
+%!assert (summer (11), [[0:0.1:1]; [0.5:0.05:1]; 0.4 * ones(1,11)]', eps)
+
+## Input validation
+%!error <N must be a scalar integer> summer ("foo")
+%!error <N must be a scalar integer> summer ([1, 2, 3])
+%!error <N must be a scalar integer> summer ({1, 2, 3})
--- a/scripts/image/turbo.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/turbo.m	Fri Apr 12 15:10:26 2024 +0200
@@ -31,7 +31,8 @@
 ## uniform.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
@@ -42,8 +43,8 @@
 function map = turbo (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("turbo: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("turbo: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -51,7 +52,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -325,3 +326,29 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (turbo ()), [256, 3])
+%!assert (size (turbo (16)), [16, 3])
+
+%!assert (turbo(0), zeros (0, 3))
+%!assert (turbo(-1), zeros (0, 3))
+
+%!shared a
+%! a = [0.18995, 0.07176, 0.23217;
+%!      0.10342, 0.89600, 0.71500;
+%!      0.98000, 0.73000, 0.22161;
+%!      0.47960, 0.01583, 0.01055];
+
+%!assert (turbo (1), a(4,:))
+%!assert (turbo (true), double (a(4,:)))
+%!assert (turbo (char (1)), double (a(4,:)))
+%!assert (turbo (int32 (1)), double (a(4,:)))
+%!assert (turbo (4), a, eps)
+
+%!shared  # Clear shared varibles to avoid echo on unrelated test errors.
+
+## Input validation
+%!error <N must be a scalar integer> turbo ("foo")
+%!error <N must be a scalar integer> turbo ([1, 2, 3])
+%!error <N must be a scalar integer> turbo ({1, 2, 3})
--- a/scripts/image/viridis.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/viridis.m	Fri Apr 12 15:10:26 2024 +0200
@@ -30,7 +30,8 @@
 ## blue, green, to yellow.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
@@ -41,8 +42,8 @@
 function map = viridis (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("viridis: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("viridis: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -50,9 +51,10 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
+
   ## FIXME: Is there no algorithmic definition of the viridis colormap?
   persistent viridi = [0.26700401  0.00487433  0.32941519
                        0.26851048  0.00960483  0.33542652
@@ -325,3 +327,28 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+%!assert (size (viridis ()), [256, 3])
+%!assert (size (viridis (16)), [16, 3])
+
+%!assert (viridis (0), zeros (0, 3))
+%!assert (viridis (-1), zeros (0, 3))
+
+%!shared a
+%! a = [0.26700401, 0.00487433, 0.32941519;
+%!      0.19063135, 0.40706148, 0.55608907;
+%!      0.20803045, 0.71870095, 0.47287330;
+%!      0.99324789, 0.90615657, 0.14393620];
+
+%!assert (viridis (1), a(4,:))
+%!assert (viridis (true), double (a(4,:)))
+%!assert (viridis (char (1)), double (a(4,:)))
+%!assert (viridis (int32 (1)), double (a(4,:)))
+%!assert (viridis (4), a, eps)
+
+%!shared  # Clear shared varibles to avoid echo on unrelated test errors.
+
+## Input validation
+%!error <N must be a scalar integer> viridis ("foo")
+%!error <N must be a scalar integer> viridis ([1, 2, 3])
+%!error <N must be a scalar integer> viridis ({1, 2, 3})
--- a/scripts/image/white.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/white.m	Fri Apr 12 15:10:26 2024 +0200
@@ -29,15 +29,16 @@
 ## Create color colormap.  This colormap is completely white.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = white (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("white: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("white: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -45,7 +46,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
   map = ones (n, 3);
@@ -60,3 +61,20 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+%!assert (size (white ()), [256, 3])
+%!assert (size (white (16)), [16, 3])
+%!assert (all ((white ()(:)) == 1), true)
+
+%!assert (white (1), [1, 1, 1])
+%!assert (white (true), double ([1, 1, 1]))
+%!assert (white (char (1)), double ([1, 1, 1]))
+%!assert (white (int32 (1)), double ([1, 1, 1]))
+%!assert (white (0), zeros (0, 3))
+%!assert (white (-1), zeros (0, 3))
+
+
+## Input validation
+%!error <N must be a scalar integer> white ("foo")
+%!error <N must be a scalar integer> white ([1, 2, 3])
+%!error <N must be a scalar integer> white ({1, 2, 3})
--- a/scripts/image/winter.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/image/winter.m	Fri Apr 12 15:10:26 2024 +0200
@@ -29,15 +29,16 @@
 ## Create color colormap.  This colormap varies from blue to green.
 ##
 ## The argument @var{n} must be a scalar.
-## If unspecified, the length of the current colormap, or 64, is used.
+## If @var{n} is not specified the length of the current colormap is used.  If
+## there is no current colormap the default value of 256 is used.
 ## @seealso{colormap}
 ## @end deftypefn
 
 function map = winter (n)
 
   if (nargin == 1)
-    if (! isscalar (n))
-      error ("winter: N must be a scalar");
+    if (! (isscalar (n) && isreal (n) && n == fix (n)))
+      error ("winter: N must be a scalar integer");
     endif
     n = double (n);
   else
@@ -45,7 +46,7 @@
     if (! isempty (hf))
       n = rows (get (hf, "colormap"));
     else
-      n = 64;
+      n = 256;
     endif
   endif
 
@@ -70,3 +71,22 @@
 %!  rgbplot (cmap, "composite");
 %! subplot (2, 1, 2);
 %!  rgbplot (cmap);
+
+
+%!assert (size (winter ()), [256, 3])
+%!assert (size (winter (16)), [16, 3])
+
+%!assert (winter (1), [0, 0, 1])
+%!assert (winter (true), double ([0, 0, 1]))
+%!assert (winter (char (1)), double ([0, 0, 1]))
+%!assert (winter (int32 (1)), double ([0, 0, 1]))
+
+%!assert (winter (0), zeros (0, 3))
+%!assert (winter (-1), zeros (0, 3))
+
+%!assert (winter (11), [zeros(1,11); [0:0.1:1]; [1:-0.05:0.5]]', eps)
+
+## Input validation
+%!error <N must be a scalar integer> winter ("foo")
+%!error <N must be a scalar integer> winter ([1, 2, 3])
+%!error <N must be a scalar integer> winter ({1, 2, 3})
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/legacy/caxis.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,133 @@
+########################################################################
+##
+## Copyright (C) 2007-2024 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  {} {} caxis ([cmin cmax])
+## @deftypefnx {} {} caxis ("auto")
+## @deftypefnx {} {} caxis ("manual")
+## @deftypefnx {} {} caxis (@var{hax}, @dots{})
+## @deftypefnx {} {@var{limits} =} caxis ()
+##
+## This function is not recommended.  Use @code{clim} instead.
+##
+## Query or set color axis limits for plots.
+##
+## The limits argument should be a 2-element vector specifying the lower and
+## upper limits to assign to the first and last value in the colormap.  Data
+## values outside this range are clamped to the first and last colormap
+## entries.
+##
+## If the @qcode{"auto"} option is given then automatic colormap limits are
+## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
+## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
+## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
+## numeric values in the @qcode{"clim"} property are used for limits.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axes rather than the current axes returned by @code{gca}.
+##
+## Called without arguments the current color axis limits are returned.
+##
+## Programming Note: The color axis affects the display of image, patch, and
+## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
+## has indexed data and the @qcode{"cdatamapping"} property is set to
+## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
+## @qcode{"direct"} @code{cdatamapping} are not affected.
+## @seealso{clim, colormap, axis}
+## @end deftypefn
+
+function limits = caxis (varargin)
+
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("caxis", varargin{:});
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
+  unwind_protect
+    if (isempty (hax))
+      hax = gca ();
+    endif
+    if (nargin == 0)
+      limits = get (hax, "clim");
+    else
+      arg1 = varargin{1};
+      if (ischar (arg1))
+        if (strcmpi (arg1, "auto"))
+          set (hax, "climmode", "auto");
+        elseif (strcmpi (arg1, "manual"))
+          set (hax, "climmode", "manual");
+        else
+          error ("caxis: invalid mode '%s'", arg1);
+        endif
+      elseif (isvector (arg1))
+        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
+          error ("caxis: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
+        endif
+        set (hax, "clim", arg1);
+      else
+        print_usage ();
+      endif
+    endif
+  unwind_protect_cleanup
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
+    endif
+  end_unwind_protect
+
+endfunction
+
+
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   caxis ([e, pi]);
+%!   assert (caxis (), [e, pi]);
+%!   caxis (hax, [-1, 1]);
+%!   assert (caxis (hax), [-1, 1]);
+%!   assert (get (hax, "climmode"), "manual");
+%!   caxis ("auto");
+%!   assert (get (hax, "climmode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error caxis (1,2,3)
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("caxis ('foo')", "invalid mode 'foo'");
+%!   fail ("caxis ([1 2 3])", "2-element vector");
+%!   fail ("caxis ({1 2 3})", "numeric 2-element vector");
+%!   fail ("caxis ([1 0])", "LIM1 < LIM2");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/legacy/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/legacy/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -3,6 +3,7 @@
 %canon_reldir%_FCN_FILES = \
   %reldir%/.oct-config \
   %reldir%/__vectorize__.m \
+  %reldir%/caxis.m \
   %reldir%/findstr.m \
   %reldir%/flipdim.m \
   %reldir%/genvarname.m \
--- a/scripts/linear-algebra/cross.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/linear-algebra/cross.m	Fri Apr 12 15:10:26 2024 +0200
@@ -68,15 +68,17 @@
   nd = ndims (x);
 
   if (nargin < 3 && nd < 3 && ndims (y) < 3)
-    ## COMPATIBILITY -- opposite behavior for cross(row,col)
-    ## Swap x and y in the assignments below to get the matlab behavior.
-    ## Better yet, fix the calling code so that it uses conformant vectors.
+    ## COMPATIBILITY -- mixed row/column vector inputs
+    ## Transpose x and y in the assignments below to get row output to match
+    ## matlab behavior (verified version: 2023b).
+    ## Recommend users instead ensure calling code has matched vectors to
+    ## remove any ambiguity in output form.
     if (columns (x) == 1 && rows (y) == 1)
-      warning ("cross: taking cross product of column by row");
-      y = y.';
+      warning ("cross: cross product of column by row produces row output");
+      x = x.';
     elseif (rows (x) == 1 && columns (y) == 1)
-      warning ("cross: taking cross product of row by column");
-      x = x.';
+      warning ("cross: cross product of row by column produces row output");
+      y = y.';
     endif
   endif
 
@@ -138,6 +140,29 @@
 %! assert (cross (x, y, 2), r, eps);
 %! assert (cross (x, y, 1), -r, eps);
 
+%!test
+%! x = [1, 0, 0; 0, 1, 0; 0, 0, 1];
+%! x = cat (3, x, x);
+%! y = [0, 1, 0; 0, 0, 1; 1, 0, 0];
+%! y = cat (3, y, y);
+%! r = [0, 0, 1; 1, 0, 0; 0, 1, 0];
+%! r = cat (3, r, r);
+%! assert (cross (x, y, 2), r, eps);
+%! assert (cross (x, y, 1), -r, eps);
+%! fail ("cross (x, y, 3)", "X and Y must have three elements");
+
+## Test mixed vector inputs
+%!test <*61295>
+%! x = [1, 0, 0];
+%! y = [0, 1, 0];
+%! r = [0, 0, 1];
+%! warning ("off", "all", "local");
+%! assert (cross (x, y), r, eps);
+%! assert (cross (x', y'), r', eps);
+%! assert (cross (x', y), r, eps);
+%! assert (cross (x, y'), r, eps);
+
+
 ## Test input validation
 %!error <Invalid call> cross ()
 %!error <Invalid call> cross (1)
@@ -157,8 +182,8 @@
 %!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], 1.5)
 %!error <DIM must be a positive scalar whole number> cross ([1, 2, 3], [4, 5, 6], 2i)
 %!error <X and Y must have the same dimensions> cross ([1, 2, 3], [3, 4])
-%!warning <taking cross product of column by row> cross ([1, 2, 3]', [4, 5, 6]);
-%!warning <taking cross product of row by column> cross ([1, 2, 3], [4, 5, 6]');
+%!warning <cross product of column by row> cross ([1, 2, 3]', [4, 5, 6]);
+%!warning <cross product of row by column> cross ([1, 2, 3], [4, 5, 6]');
 
 %!test
 %! x = cat (3, [1, 1, 1]', [1, 1, 1]');
--- a/scripts/miscellaneous/inputname.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2004-2024 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/>.
-##
-########################################################################
-##
-## Original version by Paul Kienzle distributed as free software in the
-## public domain.
-
-## -*- texinfo -*-
-## @deftypefn  {} {@var{namestr} =} inputname (@var{n})
-## @deftypefnx {} {@var{namestr} =} inputname (@var{n}, @var{ids_only})
-## Return the name of the @var{n}-th argument to the calling function.
-##
-## If the argument is not a simple variable name, return an empty string.
-## Examples which will return @qcode{""} are numbers (@code{5.1}),
-## expressions (@code{@var{y}/2}), and cell or structure indexing
-## (@code{@var{c}@{1@}} or @code{@var{s}.@var{field}}).
-##
-## @code{inputname} is only useful within a function.  When used at the command
-## line or within a script it always returns an empty string.
-##
-## By default, return an empty string if the @var{n}-th argument is not a valid
-## variable name.  If the optional argument @var{ids_only} is false, return the
-## text of the argument even if it is not a valid variable name.  This is an
-## Octave extension that allows the programmer to view exactly how the function
-## was invoked even when the inputs are complex expressions.
-## @seealso{nargin, narginchk}
-## @end deftypefn
-
-## FIXME: Actually, it probably *isn't* worth fixing, but there are small
-## differences between Octave and Matlab.
-##
-## 1) When called from the top-level or a script, Matlab throws an error
-##
-##   inputname (1)   % at command prompt
-##   % Octave returns "", Matlab throws an error
-##
-## 2) cell or struct indexing causes all further names to be returned as ""
-##
-##   c = {'a', 'b'}
-##   y = 1; z = 2;
-##   fcn (c, y, z)
-##   % inputname() would return 'c', 'y', 'z' for the inputs.
-##   fcn (c{1}, y, z)
-##   % inputname() would return '', '', '' for the inputs.
-##
-## 3) If inputname is not called from a function, Matlab walks up the stack
-##    until it finds some valid code and then works from there.  This could
-##    be relevant for mex files or anonymous functions.
-##
-##   f = @(x) inputname (x);
-##   a = 1:4;
-##   arrayfun (fn, a, 'uniformoutput', false)
-##   % output is {'fn', 'a', '', ''}
-
-function namestr = inputname (n, ids_only = true)
-
-  if (nargin < 1)
-    print_usage ();
-  endif
-
-  if (! isscalar (n) || ! isindex (n))
-    error ("inputname: N must be a scalar index");
-  endif
-
-  try
-    namestr = evalin ("caller", sprintf ("__varval__ ('.argn.'){%d}", n));
-  catch
-    namestr = "";
-    return;
-  end_try_catch
-
-  ## For compatibility with Matlab, return empty string if argument name is
-  ## not a valid identifier.
-  if (ids_only && ! isvarname (namestr))
-    namestr = "";
-  elseif (ids_only)
-    ## More complicated checking is required to verify name (bug #59103).
-    ## NAME may be text, like "Inf", which is an acceptable variable name
-    ## that passes isvarname(), but that does not mean it is an actual
-    ## variable name, rather than a function or IEEE number.
-    try
-      v = evalin ("caller",
-                  sprintf ("evalin ('caller', '__varval__ (\"%s\")')", namestr));
-    catch
-      namestr = "";
-    end_try_catch
-  endif
-
-endfunction
-
-
-%!function name = __iname1__ (arg1, arg2, arg3)
-%!  name = inputname (1);
-%!endfunction
-
-%!function name = __iname1_ID__ (arg1, arg2, arg3)
-%!  name = inputname (1, false);
-%!endfunction
-
-%!function name = __iname2__ (arg1, arg2, arg3)
-%!  name = inputname (2);
-%!endfunction
-
-%!function names = __iname3__ (arg1, arg2, arg3)
-%!  names = cell (1, 3);
-%!  for i = 1:3
-%!    names{i} = inputname (i);
-%!  endfor
-%!endfunction
-
-%!test
-%! assert (__iname1__ ('xvar'), "");
-%! xvar = 1;
-%! assert (__iname1__ (xvar), "xvar");
-
-%!test
-%! xvar = 1;  yvar = 2;
-%! assert (__iname2__ (xvar), "");
-%! assert (__iname2__ (xvar, yvar), "yvar");
-
-%!test
-%! xvar = 1;  yvar = 2;
-%! assert (__iname3__ (xvar), {"xvar", "", ""});
-%! assert (__iname3__ (xvar, yvar), {"xvar", "yvar", ""});
-%! assert (__iname3__ (xvar, 3, yvar), {"xvar", "", "yvar"});
-
-## Test numbers, expressions, indexing operations
-%!test
-%! assert (__iname1__ (1.0), "");
-%! x = 1;
-%! assert (__iname1__ (x / 2), "");
-%! assert (__iname1__ (Inf), "");
-
-%!test
-%! assert (__iname1_ID__ (1.0), "1.0");
-%! x = 1;
-%! assert (__iname1_ID__ (x / 2), "x / 2");
-%! assert (__iname1_ID__ (Inf), "Inf");
-
-%!error <Invalid call> inputname ()
-%!error <N must be a scalar> inputname (ones (2,2))
-%!error <N must be a scalar index> inputname (-1)
--- a/scripts/miscellaneous/mex.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/miscellaneous/mex.m	Fri Apr 12 15:10:26 2024 +0200
@@ -45,7 +45,7 @@
   [out, sts] = mkoctfile ("--mex", varargin{:});
 
   if (! isempty (out))
-    printf ("%s", out);
+    printf ("%s\n", out);
   endif
   if (nargout > 0)
     status = sts;
--- a/scripts/miscellaneous/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/miscellaneous/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -34,7 +34,6 @@
   %reldir%/gunzip.m \
   %reldir%/info.m \
   %reldir%/inputParser.m \
-  %reldir%/inputname.m \
   %reldir%/isdeployed.m \
   %reldir%/isfile.m \
   %reldir%/isfolder.m \
--- a/scripts/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -151,7 +151,7 @@
 	    ! $(GREP) -q -E '^  *\<function\>' $$m || continue; \
 	    ! (echo $$m | $(GREP) -q __splinefit__.m) || continue; \
 	    echo "source ('$$m');"; \
-	  done ) | $(SHELL) run-octave --norc --silent --no-history
+	  done ) | $(SHELL) run-octave --norc --quiet --no-history
 .PHONY: check-missing-semicolon
 
 ## Include m-files in list of sources when building tag files.
--- a/scripts/optimization/fminbnd.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/optimization/fminbnd.m	Fri Apr 12 15:10:26 2024 +0200
@@ -111,7 +111,13 @@
     print_usage ();
   endif
 
-  if (a > b)
+  if (! (isscalar (a) && isfloat (a) && isfinite (a)))
+    error ("Octave:invalid-input-arg",
+           "fminbnd: endpoint A must be a finite floating point scalar");
+  elseif (! (isscalar (b) && isfloat (b) && isfinite (b)))
+    error ("Octave:invalid-input-arg",
+           "fminbnd: endpoint B must be a finite floating point scalar");
+  elseif (a > b)
     error ("Octave:invalid-input-arg",
            "fminbnd: the lower bound cannot be greater than the upper one");
   endif
@@ -340,4 +346,12 @@
 %!assert (fminbnd (@(x) x > 0.3, 0, 1) < 0.3)
 %!assert (fminbnd (@(x) sin (x), 0, 0), 0, eps)
 
+## Test input validation
+%!error <Invalid call> fminbnd (1)
+%!error <A must be a finite floating point scalar> fminbnd (1, [2, 3], 4)
+%!error <A must be a finite floating point scalar> fminbnd (1, int8 (2), 3)
+%!error <A must be a finite floating point scalar> fminbnd (1, Inf, 3)
+%!error <B must be a finite floating point scalar> fminbnd (1, 2, [3, 4])
+%!error <B must be a finite floating point scalar> fminbnd (1, 2, int8 (3))
+%!error <B must be a finite floating point scalar> fminbnd (1, 2, Inf)
 %!error <lower bound cannot be greater> fminbnd (@(x) sin (x), 0, -pi)
--- a/scripts/optimization/fminsearch.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/optimization/fminsearch.m	Fri Apr 12 15:10:26 2024 +0200
@@ -122,11 +122,10 @@
 ## probably better to use @code{fminbnd}.
 ## @item
 ## The legacy, undocumented syntax for passing parameters to @var{fcn} by
-## appending them to the input argument list after @var{options} is
-## discouraged and will be completely removed in Octave 10.  The
-## preferred, cross-platform compatible method of passing parameters to
-## @var{fcn} is through use of @ref{Anonymous Functions}.  For specific
-## examples of doing so for @code{fminsearch} and other minimization
+## appending them to the input argument list after @var{options} has been
+## removed in Octave 10.  The cross-platform compatible method of passing
+## parameters to @var{fcn} is through use of @ref{Anonymous Functions}.  For
+## specific examples of doing so for @code{fminsearch} and other minimization
 ## functions see the @ref{Minimizers} section of the GNU Octave manual.
 ## @end enumerate
 ## @seealso{fminbnd, fminunc, optimset}
@@ -139,7 +138,7 @@
 
 function [x, fval, exitflag, output] = fminsearch (varargin)
 
-  if (nargin < 1)
+  if (nargin < 1 || nargin > 3)
     print_usage ();
   endif
 
@@ -188,10 +187,10 @@
     options = struct ();
   endif
 
-  [x, exitflag, output] = nmsmax (fcn, x0, options, varargin{:});
+  [x, exitflag, output] = nmsmax (fcn, x0, options);
 
   if (nargout > 1)
-    fval = feval (fcn, x, varargin{:});
+    fval = feval (fcn, x);
   endif
 
 endfunction
@@ -282,16 +281,16 @@
 
 endfunction
 
-function [x, exitflag, output] = nmsmax (fcn, x, options, varargin)
+function [x, exitflag, output] = nmsmax (fcn, x, options)
 
   [stopit, savit, dirn, trace, tol, maxiter, tol_f, outfcn] = ...
                                                     parse_options (options, x);
 
   if (strcmpi (optimget (options, "FunValCheck", "off"), "on"))
     ## Replace fcn with a guarded version.
-    fcn = @(x) guarded_eval (fcn, x, varargin{:});
+    fcn = @(x) guarded_eval (fcn, x);
   else
-    fcn = @(x) real (fcn (x, varargin{:}));
+    fcn = @(x) real (fcn (x));
   endif
 
   x0 = x(:);  # Work with column vector internally.
@@ -509,9 +508,9 @@
 endfunction
 
 ## A helper function that evaluates a function and checks for bad results.
-function y = guarded_eval (fcn, x, varargin)
+function y = guarded_eval (fcn, x)
 
-  y = fcn (x, varargin{:});
+  y = fcn (x);
 
   if (! (isreal (y)))
     error ("fminsearch:notreal", "fminsearch: non-real value encountered");
@@ -559,14 +558,6 @@
 %! c = 1.5;
 %! assert (fminsearch (@(x) x(1).^2 + c*x(2).^2, [1;1]), [0;0], 1e-4);
 
-## additional input argument
-%!test
-%! x1 = fminsearch (@(x, c) x(1).^2 + c*x(2).^2, [1;1], [], 1.5);
-%! assert (x1, [0;0], 1e-4);
-%! x1 = fminsearch (@(x, c) c(1)*x(1).^2 + c(2)*x(2).^2, [1;1], ...
-%!                  optimset ("Display", "none"), [1 1.5]);
-%! assert (x1, [0;0], 1e-4);
-
 ## all output arguments
 %!test
 %! options = optimset ("Display", "none", "TolX", 1e-4, "TolFun", 1e-7);
@@ -592,4 +583,15 @@
 
 ## Test input validation
 %!error <Invalid call> fminsearch ()
-%!error fminsearch (1)
+%!error <Invalid call> fminsearch (1, 2, 3, 4)
+%!error <PROBLEM must be a structure> fminsearch (1)
+%!test <*55742>
+%! problem.objective = @sin;
+%! problem.x0 = 3;
+%! problem.solver = "foo";
+%! fail ("fminsearch (problem)","problem.solver must be set to");
+
+## additional input argument - no longer supported.  nargin > 3 should fail.
+%!test <*55742>
+%! fail ("fminsearch (@(x, c) x(1).^2 + c*x(2).^2, [1;1], [], 1.5)", "Invalid call");
+%! fail ("fminsearch (@(x, c) c(1)*x(1).^2 + c(2)*x(2).^2, [1;1], optimset ('Display', 'none'), [1 1.5])", "Invalid call");
--- a/scripts/plot/appearance/axis.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/appearance/axis.m	Fri Apr 12 15:10:26 2024 +0200
@@ -158,7 +158,7 @@
 ## axis ("tic", "labely");
 ## @end example
 ##
-## @seealso{xlim, ylim, zlim, caxis, daspect, pbaspect, box, grid}
+## @seealso{xlim, ylim, zlim, clim, daspect, pbaspect, box, grid}
 ## @end deftypefn
 
 function limits = axis (varargin)
@@ -390,7 +390,7 @@
       endif
 
       if (len > 7)
-        caxis (ca, opt(7:8));
+        clim (ca, opt(7:8));
       endif
 
     else
--- a/scripts/plot/appearance/caxis.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2007-2024 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  {} {} caxis ([cmin cmax])
-## @deftypefnx {} {} caxis ("auto")
-## @deftypefnx {} {} caxis ("manual")
-## @deftypefnx {} {} caxis (@var{hax}, @dots{})
-## @deftypefnx {} {@var{limits} =} caxis ()
-## Query or set color axis limits for plots.
-##
-## The limits argument should be a 2-element vector specifying the lower and
-## upper limits to assign to the first and last value in the colormap.  Data
-## values outside this range are clamped to the first and last colormap
-## entries.
-##
-## If the @qcode{"auto"} option is given then automatic colormap limits are
-## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
-## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
-## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
-## numeric values in the @qcode{"clim"} property are used for limits.
-##
-## If the first argument @var{hax} is an axes handle, then operate on
-## this axes rather than the current axes returned by @code{gca}.
-##
-## Called without arguments the current color axis limits are returned.
-##
-## Programming Note: The color axis affects the display of image, patch, and
-## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
-## has indexed data and the @qcode{"cdatamapping"} property is set to
-## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
-## @qcode{"direct"} @code{cdatamapping} are not affected.
-## @seealso{colormap, axis}
-## @end deftypefn
-
-function limits = caxis (varargin)
-
-  [hax, varargin, nargin] = __plt_get_axis_arg__ ("caxis", varargin{:});
-
-  if (nargin > 1)
-    print_usage ();
-  endif
-
-  oldfig = [];
-  if (! isempty (hax))
-    oldfig = get (0, "currentfigure");
-  endif
-  unwind_protect
-    if (isempty (hax))
-      hax = gca ();
-    endif
-    if (nargin == 0)
-      limits = get (hax, "clim");
-    else
-      arg1 = varargin{1};
-      if (ischar (arg1))
-        if (strcmpi (arg1, "auto"))
-          set (hax, "climmode", "auto");
-        elseif (strcmpi (arg1, "manual"))
-          set (hax, "climmode", "manual");
-        else
-          error ("caxis: invalid mode '%s'", arg1);
-        endif
-      elseif (isvector (arg1))
-        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
-          error ("caxis: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
-        endif
-        set (hax, "clim", arg1);
-      else
-        print_usage ();
-      endif
-    endif
-  unwind_protect_cleanup
-    if (! isempty (oldfig))
-      set (0, "currentfigure", oldfig);
-    endif
-  end_unwind_protect
-
-endfunction
-
-
-%!test
-%! hf = figure ("visible", "off");
-%! hax = gca ();
-%! unwind_protect
-%!   caxis ([e, pi]);
-%!   assert (caxis (), [e, pi]);
-%!   caxis (hax, [-1, 1]);
-%!   assert (caxis (hax), [-1, 1]);
-%!   assert (get (hax, "climmode"), "manual");
-%!   caxis ("auto");
-%!   assert (get (hax, "climmode"), "auto");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
-
-## Test input validation
-%!error caxis (1,2,3)
-%!test
-%! hf = figure ("visible", "off");
-%! unwind_protect
-%!   fail ("caxis ('foo')", "invalid mode 'foo'");
-%!   fail ("caxis ([1 2 3])", "2-element vector");
-%!   fail ("caxis ({1 2 3})", "numeric 2-element vector");
-%!   fail ("caxis ([1 0])", "LIM1 < LIM2");
-%! unwind_protect_cleanup
-%!   close (hf);
-%! end_unwind_protect
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/clim.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,130 @@
+########################################################################
+##
+## Copyright (C) 2024 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  {} {} clim ([cmin cmax])
+## @deftypefnx {} {} clim ("auto")
+## @deftypefnx {} {} clim ("manual")
+## @deftypefnx {} {} clim (@var{hax}, @dots{})
+## @deftypefnx {} {@var{limits} =} clim ()
+## Query or set color axis limits for plots.
+##
+## The limits argument should be a 2-element vector specifying the lower and
+## upper limits to assign to the first and last value in the colormap.  Data
+## values outside this range are clamped to the first and last colormap
+## entries.
+##
+## If the @qcode{"auto"} option is given then automatic colormap limits are
+## applied.  The automatic algorithm sets @var{cmin} to the minimum data value
+## and @var{cmax} to the maximum data value.  If @qcode{"manual"} is specified
+## then the @qcode{"climmode"} property is set to @qcode{"manual"} and the
+## numeric values in the @qcode{"clim"} property are used for limits.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axes rather than the current axes returned by @code{gca}.
+##
+## Called without arguments the current color axis limits are returned.
+##
+## Programming Note: The color axis affects the display of image, patch, and
+## surface graphics objects, but @strong{only} if the @qcode{"cdata"} property
+## has indexed data and the @qcode{"cdatamapping"} property is set to
+## @qcode{"scaled"}.  Graphic objects with true color @code{cdata}, or
+## @qcode{"direct"} @code{cdatamapping} are not affected.
+## @seealso{colormap, axis}
+## @end deftypefn
+
+function limits = clim (varargin)
+
+  [hax, varargin, nargin] = __plt_get_axis_arg__ ("clim", varargin{:});
+
+  if (nargin > 1)
+    print_usage ();
+  endif
+
+  oldfig = [];
+  if (! isempty (hax))
+    oldfig = get (0, "currentfigure");
+  endif
+  unwind_protect
+    if (isempty (hax))
+      hax = gca ();
+    endif
+    if (nargin == 0)
+      limits = get (hax, "clim");
+    else
+      arg1 = varargin{1};
+      if (ischar (arg1))
+        if (strcmpi (arg1, "auto"))
+          set (hax, "climmode", "auto");
+        elseif (strcmpi (arg1, "manual"))
+          set (hax, "climmode", "manual");
+        else
+          error ("clim: invalid mode '%s'", arg1);
+        endif
+      elseif (isvector (arg1))
+        if (numel (arg1) != 2 || ! isnumeric (arg1) || arg1(1) >= arg1(2))
+          error ("clim: LIMITS must be a numeric 2-element vector where LIM1 < LIM2");
+        endif
+        set (hax, "clim", arg1);
+      else
+        print_usage ();
+      endif
+    endif
+  unwind_protect_cleanup
+    if (! isempty (oldfig))
+      set (0, "currentfigure", oldfig);
+    endif
+  end_unwind_protect
+
+endfunction
+
+
+%!test
+%! hf = figure ("visible", "off");
+%! hax = gca ();
+%! unwind_protect
+%!   clim ([e, pi]);
+%!   assert (clim (), [e, pi]);
+%!   clim (hax, [-1, 1]);
+%!   assert (clim (hax), [-1, 1]);
+%!   assert (get (hax, "climmode"), "manual");
+%!   clim ("auto");
+%!   assert (get (hax, "climmode"), "auto");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+## Test input validation
+%!error clim (1,2,3)
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   fail ("clim ('foo')", "invalid mode 'foo'");
+%!   fail ("clim ([1 2 3])", "2-element vector");
+%!   fail ("clim ({1 2 3})", "numeric 2-element vector");
+%!   fail ("clim ([1 0])", "LIM1 < LIM2");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/appearance/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/appearance/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -24,8 +24,8 @@
   %reldir%/camup.m \
   %reldir%/camva.m \
   %reldir%/camzoom.m \
-  %reldir%/caxis.m \
   %reldir%/clabel.m \
+  %reldir%/clim.m \
   %reldir%/daspect.m \
   %reldir%/datetick.m \
   %reldir%/diffuse.m \
@@ -38,10 +38,12 @@
   %reldir%/orient.m \
   %reldir%/pbaspect.m \
   %reldir%/rticks.m \
+  %reldir%/rticklabels.m \
   %reldir%/shading.m \
   %reldir%/specular.m \
   %reldir%/text.m \
   %reldir%/thetaticks.m \
+  %reldir%/tticklabels.m \
   %reldir%/title.m \
   %reldir%/view.m \
   %reldir%/whitebg.m \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/rticklabels.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,258 @@
+########################################################################
+##
+## Copyright (C) 2017-2024 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{labels} =} rticklabels
+## @deftypefnx {} {} rticklabels (@var{tickval})
+## @deftypefnx {} {@dots{} =} rticklabels (@var{hax}, @dots{})
+## Query or set the tick labels on the r-axis of a polar plot.
+##
+## When called without an argument, return a cell array of strings of the
+## current rtick labels.
+##
+## When called with the argument @var{tickval} being a vector of numbers or
+## a cell array of strings and/or numbers, the labels will be changed to
+## match these new values. Note that the center point of the plots made by
+## @code{polar} are never labeled, so the first specified label will be
+## applied to the second rtick location and subesquent labels will progress
+## outward.
+##
+## If fewer labels are specified than the current number of tick marks, those
+## labels will be applied starting with the innermost tick labels, and blank
+## labels will be appended to the remainder.  If the specified label count
+## exceeds the number of tick labels, the excess labels are ignored.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## Requesting a return value when calling @code{rticklabels} to set a property
+## value will result in an error.
+##
+## Compatability Note:  The 'mode' property for rticklabels has not yet been
+##                      implemented.
+##
+## @seealso{polar, rticks, tticklabels, xticklabels, yticklabels, zticklabels,
+## get, set}
+## @end deftypefn
+
+## FIXME:  Octave's polar plot implementation does not currently create the
+##         properties rticklabel, rticklabelmode, and rtickmode.  Fully
+##         implemented versions of those proporties could simplify much of the
+##         code below, which could then mimick much the behavior of the
+##         equivalent Cartesian functions.
+
+function labels = rticklabels (varargin)
+  [hax, varargin, nargs] = __plt_get_axis_arg__ ("rticklabels", varargin{:});
+
+  if (nargs > 1)
+    print_usage;
+  endif
+
+  returnlabels = true;
+
+  ## Check first input for axes handle and remove from argument list.
+  if (nargs > 0)
+    ## Single remaining input must be tick labels and should be a numeric
+    ## vector or a cell vector of numbers and strings.
+
+    ## Error if trying to request and set values simultaneously.
+    if (nargout > 0)
+      error ("rticklabels: cannot set and return labels simultaneously");
+    endif
+
+    returnlabels = false;
+    arg = varargin{1};
+
+    if (isnumeric (arg))
+      ## All inputs handled the same way as cells. (:) permits nonvectors.
+      cellarg_num = ones (1, numel (arg));
+      cellarg_char = zeros (1, numel (arg));
+      arg = num2cell (arg(:));
+
+    elseif (iscell (arg))
+
+      if (! all ((cellarg_num = cellfun ('isnumeric', arg))
+                           | (cellarg_char = cellfun ('ischar', arg))))
+        error ("rticklabels: TICKVAL cell must contain numbers or strings");
+      endif
+
+    else
+      error (["rticklabels: TICKVAL must be numeric or a cell ", ...
+              "containing numbers and strings"]);
+    endif
+
+  ## Finish converting TICVAL into a cellstr.
+
+  ## Convert numeric elements to characters and make it a 1-D cell array.
+  arg(cellarg_num) = cellfun (@num2str, arg(cellarg_num), ...
+                                "UniformOutput", false);
+  arg = arg(:);
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  endif
+
+  ## Error if the remaining input
+  polarhandle = findall (hax, "tag", "polar_grid");
+
+  ## Error if hax does not point to a polar plot with r elements.
+  if (isempty (polarhandle))
+    error ("rticklabels: rticklabels can only be used on a polar plot");
+  elseif (! isfield (get (hax), "rtick") )
+    error ("rticklabels: rtick property not defined for current axes");
+  endif
+
+  ## Get count of radius and theta curves.
+  nr = numel (get (hax, "rtick")); # Must check if it includes unlabeled center.
+  nt = numel (get (hax, "ttick"));
+  rt_label_handles = get (polarhandle, "children");
+
+  ## Center is never labeled in polar plots.
+  ## If rtick does not include unlabled center, label_count = 2*nr+2*nt-1,
+  ## otherwise label_count = 2*nr+2*nt+1 and nr should be reduced by 1
+  ## to prevent attempts to get label value from nonlabel handle.
+  if (2 * (nr + nt) + 1 > numel (rt_label_handles))
+    nr--;
+  endif
+
+  ## rtick and ttick object ordering:
+  ##  1:nt = text handles containing theta labels (reverse order)
+  ##  nt+1:2*nt = line object handles for ttick radial grid lines
+  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)
+  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles
+  ##  end = patch object handle for darker outside border
+
+  rlabelrange = 2*nt + [nr:-1:1]; # Flip back to increasing order.
+
+  if (nargs == 0)
+    ## Get radius labels.
+    labels = get (rt_label_handles(rlabelrange), "string");
+
+  else
+    ## Set new label values.
+
+    if isempty (arg)
+      ## If an empty cell or array is set, set all labels to "".
+      arg = cell (nr, 1);
+      arg(:) = {""};
+
+    else
+      ## Pad and trim arg as needed to match number of labels.
+      if (nr < numel (arg))
+        arg (nr + 1 : end) = [];
+      else
+        arg(end + 1 : nr) = {""};
+      endif
+    endif
+
+    ## Replace labels with values from arg, ensure column vector.
+    set (rt_label_handles(rlabelrange), {"string"}, arg(:));
+  endif
+
+endfunction
+
+%!test
+%! t = [0:15:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   rticks (hax, [0, 0.5, 1]);
+%!   assert (rticklabels (hax), {"0.5"; "1"});
+%!   rticklabels (hax, [1 2]);
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, [3 4]');
+%!   assert (rticklabels (hax), {"3"; "4"});
+%!   rticklabels (hax, {5, 6});
+%!   assert (rticklabels (hax), {"5"; "6"});
+%!   rticklabels (hax, {"a", "bee"});
+%!   assert (rticklabels (hax), {"a"; "bee"});
+%!   rticklabels (hax, {1, "two"});
+%!   assert (rticklabels (hax), {"1"; "two"});
+%!   rticklabels (hax, {1, 2, 3, 4});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, [5, 6, 7, 8]);
+%!   assert (rticklabels (hax), {"5"; "6"});
+%!   rticklabels (hax, {1});
+%!   assert (rticklabels (hax), {"1"; ""});
+%!   rticklabels (hax, {1,2});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, []);
+%!   assert (rticklabels (hax), {""; ""});
+%!   rticklabels (hax, {1,2});
+%!   assert (rticklabels (hax), {"1"; "2"});
+%!   rticklabels (hax, {});
+%!   assert (rticklabels (hax), {""; ""});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+
+## Test input validation
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("rticklabels (1,2,3)", "Invalid call");
+%!   fail ("rticklabels (-1, 2)", "Invalid call");
+%!   fail ("rticklabels (hax, 2, 3)", "Invalid call");
+%!   fail ("rticklabels (hf, 2)", "Invalid call");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tmp = rticklabels ([1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tmp = rticklabels (hax, [1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("rticklabels (hax, {{1}, 'two', 3})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, {1, 'two', false})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, {1, struct()})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("rticklabels (hax, struct())", "TICKVAL must be numeric or a cell containing");
+%!   fail ("rticklabels (hax, [true false])", "TICKVAL must be numeric or a cell containing");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! t = [0:45:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = plot (t, r);
+%!   hax = gca ();
+%!   fail ("rticklabels (hax, 1)", "rticklabels can only be used on a polar plot");
+%!   fail ("rticklabels ({1})", "rticklabels can only be used on a polar plot");
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   delete (findall (hax, "tag", "polar_grid"));
+%!   fail ("rticklabels (hax, 1)", "rticklabels can only be used on a polar plot");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/appearance/text.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/appearance/text.m	Fri Apr 12 15:10:26 2024 +0200
@@ -280,7 +280,7 @@
 %!                    "edgecolor", "k", ...
 %!                    "verticalalignment", "bottom");
 %! endfor
-%! caxis ([-100 100]);
+%! clim ([-100 100]);
 %! title ("Vertically Aligned at Bottom");
 
 %!demo
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/plot/appearance/tticklabels.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,247 @@
+########################################################################
+##
+## Copyright (C) 2017-2024 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{labels} =} tticklabels
+## @deftypefnx {} {} tticklabels (@var{tickval})
+## @deftypefnx {} {@dots{} =} tticklabels (@var{hax}, @dots{})
+## Query or set the tick labels on the theta-axis of a polar plot.
+##
+## When called without an argument, return a cell array of strings of the
+## current ttick labels.
+##
+## When called with the argument @var{tickval} being a vector of numbers or
+## a cell array of strings and/or numbers, the labels will be changed to
+## match these new values.  Values will be applied starting with the
+## zero-degree tick mark and will progress counter-clockwise.
+##
+## If fewer labels are specified than the current number of theta tick marks,
+## those labels will be applied starting at the zero-degree tick mark and
+## blank labels will be appended to the remainder.  If the specified label
+## count exceeds the number of tick labels, the excess labels are ignored.
+##
+## If the first argument @var{hax} is an axes handle, then operate on
+## this axis rather than the current axes returned by @code{gca}.
+##
+## Requesting a return value when calling @code{tticklabels} to set a property
+## value will result in an error.
+##
+## Compatability Note:  The 'mode' property for tticklabels has not yet been
+##                      implemented.
+##
+## @seealso{polar, thetaticks, rticklabels, xticklabels, yticklabels,
+## zticklabels, get, set}
+## @end deftypefn
+
+## FIXME:  Octave's polar plot implementation does not currently create the
+##         properties tticklabel, tticklabelmode, and ttickmode.  Fully
+##         implemented versions of those proporties could simplify much of the
+##         code below, which could then mimick much the behavior of the
+##         equivalent Cartesian functions.
+
+function labels = tticklabels (varargin)
+  [hax, varargin, nargs] = __plt_get_axis_arg__ ("tticklabels", varargin{:});
+
+  if (nargs > 1)
+    print_usage;
+  endif
+
+  returnlabels = true;
+
+  ## Check first input for axes handle and remove from argument list.
+  if (nargs > 0)
+    ## Single remaining input must be tick labels and should be a numeric
+    ## vector or a cell vector of numbers and strings.
+
+    ## Error if trying to request and set values simultaneously.
+    if (nargout > 0)
+      error ("tticklabels: cannot set and return labels simultaneously");
+    endif
+
+    returnlabels = false;
+    arg = varargin{1};
+
+    if (isnumeric (arg))
+      ## All inputs handled the same way as cells. (:) permits nonvectors.
+      cellarg_num = ones (1, numel (arg));
+      cellarg_char = zeros (1, numel (arg));
+      arg = num2cell (arg(:));
+
+    elseif (iscell (arg))
+
+      if (! all ((cellarg_num = cellfun ('isnumeric', arg))
+                           | (cellarg_char = cellfun ('ischar', arg))))
+        error ("tticklabels: TICKVAL cell must contain numbers or strings");
+      endif
+
+    else
+      error (["tticklabels: TICKVAL must be numeric or a cell ", ...
+              "containing numbers and strings"]);
+    endif
+
+  ## Finish converting TICVAL into a cellstr.
+
+  ## Convert numeric elements to characters and make it a 1-D cell array.
+  arg(cellarg_num) = cellfun (@num2str, arg(cellarg_num), ...
+                                "UniformOutput", false);
+  arg = arg(:);
+  endif
+
+  if (isempty (hax))
+    hax = gca ();
+  endif
+
+  ## Error if the remaining input
+  polarhandle = findall (hax, "tag", "polar_grid");
+
+  ## Error if hax does not point to a polar plot with theta elements.
+  if (isempty (polarhandle))
+    error ("tticklabels: tticklabels can only be used on a polar plot");
+  elseif (! isfield (get (hax), "ttick") )
+    error ("tticklabels: ttick property not defined for current axes");
+  endif
+
+  ## Get theta curves count.
+  nt = numel (get (hax, "ttick"));
+
+  ## rtick and ttick object ordering:
+  ##  1:nt = text handles containing theta labels (reverse order)
+  ##  nt+1:2*nt = line object handles for ttick radial grid lines
+  ##  2*nt+1:2*nt+nr = text handles containing nr rtick labels (reverse order)
+  ##  2*nt+nr+1:2*nt+2*nr = line object handles for rtick circles
+  ##  end = patch object handle for darker outside border
+
+  ## Get theta label handles, reverse order so output is in increasing.
+  tlabel_handles = get (polarhandle, "children")(nt:-1:1);
+
+  if (nargs == 0)
+    ## Just return theta labels.
+    labels = get (tlabel_handles, "string");
+
+  else
+    ## Set new label values.
+
+    if isempty (arg)
+      ## If an empty cell or array is set, set all labels to "".
+      arg = cell (nt, 1);
+      arg(:) = {""};
+
+    else
+      ## Pad and trim arg as needed to match number of labels.
+      if (nt < numel (arg))
+        arg (nt + 1 : end) = [];
+      else
+        arg(end + 1 : nt) = {""};
+      endif
+    endif
+
+    ## Replace labels with values from arg, ensure column vector.
+    set (tlabel_handles, {"string"}, arg(:));
+  endif
+
+endfunction
+
+%!test
+%! t = [0:15:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   thetaticks (hax, [0:60:300]);
+%!   assert (tticklabels (hax), {"0"; "60"; "120"; "180"; "240"; "300"});
+%!   tticklabels (hax, [0:20:100]);
+%!   assert (tticklabels (hax), {"0"; "20"; "40"; "60"; "80"; "100"});
+%!   tticklabels (hax, [0:-20:-100]');
+%!   assert (tticklabels (hax), {"0"; "-20"; "-40"; "-60"; "-80"; "-100"});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, {"a", "bee", "c", "d", "eeee", "f"});
+%!   assert (tticklabels (hax), {"a"; "bee"; "c"; "d"; "eeee"; "f"});
+%!   tticklabels (hax, {1, "two", 3, "4", 5, "six"}');
+%!   assert (tticklabels (hax), {"1"; "two"; "3"; "4"; "5"; "six"});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6, 7});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, [5, 6, 7, 8, 9, 10, 11]);
+%!   assert (tticklabels (hax), {"5"; "6"; "7"; "8"; "9"; "10"});
+%!   tticklabels (hax, {1});
+%!   assert (tticklabels (hax), {"1"; ""; ""; ""; ""; ""});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, []);
+%!   assert (tticklabels (hax), {""; ""; ""; ""; ""; ""});
+%!   tticklabels (hax, {1, 2, 3, 4, 5 ,6});
+%!   assert (tticklabels (hax), {"1"; "2"; "3"; "4"; "5"; "6"});
+%!   tticklabels (hax, {});
+%!   assert (tticklabels (hax), {""; ""; ""; ""; ""; ""});
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+
+## Test input validation
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tticklabels (1,2,3)", "Invalid call");
+%!   fail ("tticklabels (-1, 2)", "Invalid call");
+%!   fail ("tticklabels (hax, 2, 3)", "Invalid call");
+%!   fail ("tticklabels (hf, 2)", "Invalid call");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hax = gca ();
+%!   fail ("tmp = tticklabels ([1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tmp = tticklabels (hax, [1, 2, 3])", "cannot set and return labels simultaneously");
+%!   fail ("tticklabels (hax, {{1}, 'two', 3})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, {1, 'two', false})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, {1, struct()})", "TICKVAL cell must contain numbers or strings");
+%!   fail ("tticklabels (hax, struct())", "TICKVAL must be numeric or a cell containing");
+%!   fail ("tticklabels (hax, [true false])", "TICKVAL must be numeric or a cell containing");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
+
+%!test
+%! t = [0:45:180] * pi / 180;
+%! r = sin (t);
+%! hf = figure ("visible", "off");
+%! unwind_protect
+%!   hp = plot (t, r);
+%!   hax = gca ();
+%!   fail ("tticklabels (hax, 1)", "tticklabels can only be used on a polar plot");
+%!   fail ("tticklabels ({1})", "tticklabels can only be used on a polar plot");
+%!   hp = polar (t, r);
+%!   hax = gca ();
+%!   delete (findall (hax, "tag", "polar_grid"));
+%!   fail ("tticklabels (hax, 1)", "tticklabels can only be used on a polar plot");
+%! unwind_protect_cleanup
+%!   close (hf);
+%! end_unwind_protect
--- a/scripts/plot/draw/contour.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/contour.m	Fri Apr 12 15:10:26 2024 +0200
@@ -62,7 +62,7 @@
 ## @end example
 ##
 ## @seealso{ezcontour, contourc, contourf, contour3, clabel, meshc, surfc,
-## caxis, colormap, plot}
+## clim, colormap, plot}
 ##
 ## @end deftypefn
 
--- a/scripts/plot/draw/contour3.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/contour3.m	Fri Apr 12 15:10:26 2024 +0200
@@ -66,7 +66,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{contour, contourc, contourf, clabel, meshc, surfc, caxis, colormap,
+## @seealso{contour, contourc, contourf, clabel, meshc, surfc, clim, colormap,
 ## plot}
 ## @end deftypefn
 
--- a/scripts/plot/draw/contourf.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/contourf.m	Fri Apr 12 15:10:26 2024 +0200
@@ -62,7 +62,7 @@
 ## @end group
 ## @end example
 ## @seealso{ezcontourf, contour, contourc, contour3, clabel, meshc, surfc,
-## caxis, colormap, plot}
+## clim, colormap, plot}
 ## @end deftypefn
 
 function [c, h] = contourf (varargin)
--- a/scripts/plot/draw/fill.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/fill.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 ## is a single color specification such as a @code{plot} format or an
 ## RGB-triple.  In this case the polygon(s) will have one unique color.  If
 ## @var{c} is a vector or matrix then the color data is first scaled using
-## @code{caxis} and then indexed into the current colormap.  A row vector will
+## @code{clim} and then indexed into the current colormap.  A row vector will
 ## color each polygon (a column from matrices @var{x} and @var{y}) with a
 ## single computed color.  A matrix @var{c} of the same size as @var{x} and
 ## @var{y} will compute the color of each vertex and then interpolate the face
@@ -70,7 +70,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{patch, fill3, caxis, colormap}
+## @seealso{patch, fill3, clim, colormap}
 ## @end deftypefn
 
 function h = fill (varargin)
--- a/scripts/plot/draw/fill3.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/fill3.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 ## is a single color specification such as a @code{plot} format or an
 ## RGB-triple.  In this case the polygon(s) will have one unique color.  If
 ## @var{c} is a vector or matrix then the color data is first scaled using
-## @code{caxis} and then indexed into the current colormap.  A row vector will
+## @code{clim} and then indexed into the current colormap.  A row vector will
 ## color each polygon (a column from matrices @var{x}, @var{y}, and @var{z})
 ## with a single computed color.  A matrix @var{c} of the same size as @var{x},
 ## @var{y}, and @var{z} will compute the color of each vertex and then
@@ -72,7 +72,7 @@
 ## @end group
 ## @end example
 ##
-## @seealso{patch, fill, caxis, colormap}
+## @seealso{patch, fill, clim, colormap}
 ## @end deftypefn
 
 function h = fill3 (varargin)
--- a/scripts/plot/draw/hist.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/hist.m	Fri Apr 12 15:10:26 2024 +0200
@@ -84,8 +84,8 @@
 ## @var{nn} (numbers of elements) and @var{xx} (bin centers) such that
 ## @code{bar (@var{xx}, @var{nn})} will plot the histogram.  If @var{y} is a
 ## vector, @var{nn} and @var{xx} will be row vectors.  If @var{y} is an array,
-## @var{nn} will be an array with one column of element counts for each column
-## in @var{y}, and @var{xx} will be a column vector of bin centers.
+## @var{nn} will be a 2-D array with one column of element counts for each
+## column in @var{y}, and @var{xx} will be a column vector of bin centers.
 ##
 ## @seealso{histc, bar, pie, rose}
 ## @end deftypefn
@@ -106,10 +106,6 @@
     error ("hist: Y must be real-valued");
   endif
 
-  if (ndims (y) > 2)
-    error ("hist: Y must be a 2-D array");
-  endif
-
   arg_is_vector = isvector (y);
   if (arg_is_vector)
     y = y(:);
@@ -197,6 +193,11 @@
     norm = norm (:).';  # Ensure vector orientation.
   endif
 
+  ## Flatten y from N-D to 2-D array
+  if (ndims (y) > 2)
+    y = y(:,:);
+  endif
+
   ## Perform histogram calculation
   cutoff = (x(1:end-1,:) + x(2:end,:)) / 2;
 
@@ -413,6 +414,21 @@
 %! [nn, xx] = hist (double (1:10), single ([1, 5, 10]));
 %! assert (isa (xx, "single"));
 
+## Test N-D arrays produce the same result as 2-D arrays
+%!test <*65478>  # Small n
+%! a = magic (4);
+%! b = permute (a, [1, 3, 2]);
+%! [na, xa] = hist (a);
+%! [nb, xb] = hist (b);
+%! assert ({na, xa}, {nb, xb});
+
+%!test <*65478>  # Large n
+%! a = magic (4);
+%! b = permute (a, [1, 3, 2]);
+%! [na, xa] = hist (a, 30);
+%! [nb, xb] = hist (b, 30);
+%! assert ({na, xa}, {nb, xb});
+
 ## Test input validation
 %!error <Invalid call> hist ()
 %!error <Y must be real-valued> hist (2+i)
--- a/scripts/plot/draw/mesh.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/mesh.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## surface object.
 ##
 ## @seealso{ezmesh, meshc, meshz, trimesh, contour, surf, surface, meshgrid,
-## hidden, shading, colormap, caxis}
+## hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = mesh (varargin)
--- a/scripts/plot/draw/meshc.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/meshc.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## handle to the created surface object and to the created contour plot.
 ##
 ## @seealso{ezmeshc, mesh, meshz, contour, surfc, surface, meshgrid, hidden,
-## shading, colormap, caxis}
+## shading, colormap, clim}
 ## @end deftypefn
 
 function h = meshc (varargin)
--- a/scripts/plot/draw/meshz.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/meshz.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -59,7 +59,7 @@
 ## surface object.
 ##
 ## @seealso{mesh, meshc, contour, surf, surface, waterfall, meshgrid, hidden,
-## shading, colormap, caxis}
+## shading, colormap, clim}
 ## @end deftypefn
 
 function h = meshz (varargin)
--- a/scripts/plot/draw/patch.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/patch.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,11 +42,11 @@
 ##
 ## The color argument @var{c} can take many forms.  To create polygons
 ## which all share a single color use a string value (e.g., @qcode{"r"} for
-## red), a scalar value which is scaled by @code{caxis} and indexed into the
+## red), a scalar value which is scaled by @code{clim} and indexed into the
 ## current colormap, or a 3-element RGB vector with the precise TrueColor.
 ##
 ## If @var{c} is a vector of length N then the ith polygon will have a color
-## determined by scaling entry @var{c}(i) according to @code{caxis} and then
+## determined by scaling entry @var{c}(i) according to @code{clim} and then
 ## indexing into the current colormap.  More complicated coloring situations
 ## require directly manipulating patch property/value pairs.
 ##
--- a/scripts/plot/draw/pcolor.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/pcolor.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 ##
 ## The values in @var{c} are scaled to span the range of the current
 ## colormap.  Limits may be placed on the color axis by the command
-## @code{caxis}, or by setting the @code{clim} property of the parent axis.
+## @code{clim}, or by setting the @code{clim} property of the parent axis.
 ##
 ## The face color of each cell of the mesh is determined by interpolating
 ## the values of @var{c} for each of the cell's vertices; Contrast this with
@@ -58,7 +58,7 @@
 ## The optional return value @var{h} is a graphics handle to the created
 ## surface object.
 ##
-## @seealso{caxis, shading, meshgrid, contour, imagesc}
+## @seealso{clim, shading, meshgrid, contour, imagesc}
 ## @end deftypefn
 
 function h = pcolor (varargin)
--- a/scripts/plot/draw/polar.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/polar.m	Fri Apr 12 15:10:26 2024 +0200
@@ -173,7 +173,7 @@
   set (hax, "xlim", [-maxr maxr], "ylim", [-maxr maxr]);
 
   xtick = get (hax, "xtick");
-  minidx = find (xtick > 0, 1);
+  minidx = find (xtick >= 0, 1);
   maxidx = find (xtick >= maxr, 1);
   if (! isempty (maxidx))
     rtick = xtick(minidx:maxidx);
@@ -557,7 +557,7 @@
 %!   assert (vertcat (linedata.ydata)', rm .* sin (tv1'), eps);
 %!   assert (isempty (vertcat (linedata.zdata)));
 %!
-%!   h = polar (hax, tv1', rm); # Verify orientation independence.
+%!   h = polar (hax, tv1', rm);  # Verify orientation independence.
 %!   linedata = get (h);
 %!   assert (numel (linedata), 3);
 %!   assert (vertcat (linedata.xdata)', rm .* cos (tv1'), eps);
@@ -571,13 +571,13 @@
 %!   assert (vertcat (linedata.ydata), rm .* sin (tv2), eps);
 %!   assert (isempty (vertcat (linedata.zdata)));
 %!
-%!   h = polar (hax, tv2', rm); # Verify orientation independence.
+%!   h = polar (hax, tv2', rm);  # Verify orientation independence.
 %!   linedata = get (h);
 %!   assert (numel (linedata), 2);
 %!   assert (vertcat (linedata.xdata), rm .* cos (tv2), eps);
 %!   assert (vertcat (linedata.ydata), rm .* sin (tv2), eps);
 %!   assert (isempty (vertcat (linedata.zdata)));
-
+%!
 %!   h = polar (hax, tm, rv1);
 %!   linedata = get (h);
 %!   assert (numel (linedata), 3);
@@ -585,7 +585,7 @@
 %!   assert (vertcat (linedata.ydata)', rv1' .* sin (tm), eps);
 %!   assert (isempty (vertcat (linedata.zdata)));
 %!
-%!   h = polar (hax, tm, rv1'); # Verify orientation independence.
+%!   h = polar (hax, tm, rv1');  # Verify orientation independence.
 %!   linedata = get (h);
 %!   assert (vertcat (linedata.xdata)', rv1' .* cos (tm), eps);
 %!   assert (vertcat (linedata.ydata)', rv1' .* sin (tm), eps);
@@ -598,7 +598,7 @@
 %!   assert (vertcat (linedata.ydata), rv2 .* sin (tm), eps);
 %!   assert (isempty (vertcat (linedata.zdata)));
 %!
-%!   h = polar (hax, tm, rv2'); # Verify orientation independence.
+%!   h = polar (hax, tm, rv2');  # Verify orientation independence.
 %!   linedata = get (h);
 %!   assert (numel (linedata), 2);
 %!   assert (vertcat (linedata.xdata), rv2 .* cos (tm), eps);
@@ -621,7 +621,7 @@
 %!   haxtr = get (hax);
 %!   linetr = get (h);
 %!
-%!   haxtr.children = []; # Clear child handles that should be unique.
+%!   haxtr.children = [];  # Clear child handles that should be unique.
 %!   haxtr.xlabel= [];
 %!   haxtr.ylabel= [];
 %!   haxtr.zlabel= [];
@@ -632,26 +632,26 @@
 %!   haxcplx.zlabel = [];
 %!   haxcplx.title = [];
 %!
-%!   assert (isequaln (haxcplx, haxtr)); # Check parent objects.
-%!   assert (isequaln (linecplx, linetr)); # Check actual data objects.
+%!   assert (isequaln (haxcplx, haxtr));    # Check parent objects.
+%!   assert (isequaln (linecplx, linetr));  # Check actual data objects.
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
 
-##Test rtick, ttick being properly set
-%!test
+##Test rtick, ttick being set - including the unlabeled 0 (bug #64991)
+%!test <*64991>
 %! hf = figure ("visible", "off");
 %! hax = gca ();
 %! unwind_protect
 %!   polar (hax, [1 2 3], [4 5 6]);
 %!   haxdata = get (hax);
-%!   assert (haxdata.rtick, [2 4 6]);
+%!   assert (haxdata.rtick, [0 2 4 6]);
 %!   assert (haxdata.ttick, [0:30:330]);
 %! unwind_protect_cleanup
 %!   close (hf);
 %! end_unwind_protect
 
-##Test FMT string inputs
+## Test FMT string inputs
 %!test
 %! hf = figure ("visible", "off");
 %! hax = gca ();
@@ -680,7 +680,7 @@
 %!   close (hf);
 %! end_unwind_protect
 
-##Test input validation
+## Test input validation
 %!error <Invalid call> polar ()
 %!test
 %! hf = figure ("visible", "off");
@@ -695,7 +695,7 @@
 %!   fail ("polar (hax, [1 2 3], [1 2; 3 4])", "THETA vector and RHO matrix sizes must match");
 %!   fail ("polar (hax, [1 2; 3 4], [1 2 3])", "THETA matrix and RHO vector sizes must match");
 %!   fail ("polar (hax, [1 2; 3 4], [1 2 3; 4 5 6])", "THETA and RHO matrix dimensions must match");
-%!   h = polar (hax, 1, 2); # Generates line object handle.
+%!   h = polar (hax, 1, 2);  # Generates line object handle.
 %!   fail ("polar (h, 1, 2)", "first argument must be axes handle");
 %! unwind_protect_cleanup
 %!   close (hf);
--- a/scripts/plot/draw/surf.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/surf.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the surface is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the surface can be specified independently of
@@ -62,7 +62,7 @@
 ## @code{shading} command or by using @code{set} to control surface object
 ## properties.
 ## @seealso{ezsurf, surfc, surfl, surfnorm, trisurf, contour, mesh, surface,
-## meshgrid, hidden, shading, colormap, caxis}
+## meshgrid, hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surf (varargin)
--- a/scripts/plot/draw/surfc.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/surfc.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the surface is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the surface can be specified independently of
@@ -62,7 +62,7 @@
 ## @code{shading} command or by using @code{set} to control surface object
 ## properties.
 ## @seealso{ezsurfc, surf, surfl, surfnorm, trisurf, contour, mesh, surface,
-## meshgrid, hidden, shading, colormap, caxis}
+## meshgrid, hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surfc (varargin)
--- a/scripts/plot/draw/surfl.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/surfl.m	Fri Apr 12 15:10:26 2024 +0200
@@ -83,7 +83,7 @@
 ## shading interp;
 ## @end group
 ## @end example
-## @seealso{diffuse, specular, surf, shading, colormap, caxis}
+## @seealso{diffuse, specular, surf, shading, colormap, clim}
 ## @end deftypefn
 
 function h = surfl (varargin)
--- a/scripts/plot/draw/trimesh.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/trimesh.m	Fri Apr 12 15:10:26 2024 +0200
@@ -42,7 +42,7 @@
 ## the triangles are plotted as a 2-D figure.
 ##
 ## The color of the trimesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
--- a/scripts/plot/draw/trisurf.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/trisurf.m	Fri Apr 12 15:10:26 2024 +0200
@@ -40,7 +40,7 @@
 ## plane of each vertex.
 ##
 ## The color of the trisurf is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or change
+## to fit the range of the current colormap.  Use @code{clim} and/or change
 ## the colormap to control the appearance.
 ##
 ## Optionally, the color of the mesh can be specified independently of @var{z}
--- a/scripts/plot/draw/waterfall.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/draw/waterfall.m	Fri Apr 12 15:10:26 2024 +0200
@@ -45,7 +45,7 @@
 ## of @var{z} correspond to different @var{y} values.
 ##
 ## The color of the mesh is computed by linearly scaling the @var{z} values
-## to fit the range of the current colormap.  Use @code{caxis} and/or
+## to fit the range of the current colormap.  Use @code{clim} and/or
 ## change the colormap to control the appearance.
 ##
 ## Optionally the color of the mesh can be specified independently of @var{z}
@@ -62,7 +62,7 @@
 ## surface object.
 ##
 ## @seealso{meshz, mesh, meshc, contour, surf, surface, ribbon, meshgrid,
-## hidden, shading, colormap, caxis}
+## hidden, shading, colormap, clim}
 ## @end deftypefn
 
 function h = waterfall (varargin)
--- a/scripts/plot/util/hdl2struct.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/plot/util/hdl2struct.m	Fri Apr 12 15:10:26 2024 +0200
@@ -51,7 +51,7 @@
     s.special = [];
 
     ## Process, in reverse order, all children except for
-    ## legends, colorbars, uimenu, and hggroup children
+    ## legends, colorbars, uimenu, and hggroup children.
     ii = 0;
     allkids = get (h, "children");
     if (! strcmp (s.type, "hggroup"))
@@ -71,7 +71,7 @@
     endif
 
     ## Add non "children" children objects (title, xlabel, ...) and
-    ## hggroup children and tag them in "special"
+    ## hggroup children and tag them in "special".
     if (strcmp (s.type, "hggroup"))
       special = allkids;
     else
@@ -88,8 +88,8 @@
 
     if (strcmp (s.type, "axes") ...
         && ! any (strcmp (get (h, "tag"), {'colorbar', 'legend'})))
-      ## look for legends and colorbars among axes brothers and add them
-      ## to the children list
+      ## Look for legends and colorbars among axes brothers and add them
+      ## to the children list.
       try
         lg = get (h, "__legend_handle__");
       catch
@@ -146,13 +146,8 @@
   persistent excluded;
 
   if (isempty (excluded))
-    excluded = cell2struct (repmat ({[]}, 1, 17),
-                            {"beingdeleted", "busyaction", "buttondownfcn", ...
-                             "children", "clipping", "contextmenu", ...
-                             "createfcn", "deletefcn", "handlevisibility", ...
-                             "hittest", "interruptible", "parent", ...
-                             "selected" , "selectionhighlight", ...
-                             "selectedobject", "type", "uicontextmenu"}, 2);
+    excluded = cell2struct (repmat ({[]}, 1, 4),
+                            {"beingdeleted", "children", "parent", "type"}, 2);
   endif
 
   obj = get (h);
@@ -174,6 +169,7 @@
 
 endfunction
 
+
 ## FIXME: need validation tests
 
 ## FIXME: Need to test code for legends, colorbars.
--- a/scripts/set/intersect.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/set/intersect.m	Fri Apr 12 15:10:26 2024 +0200
@@ -111,8 +111,8 @@
     else
       c = [a; b];
       ## FIXME: Is there a way to avoid a call to sort?
-      [c_ind, sort_ind] = sort (ic(match));
-      c = c(c_ind, :);
+      [c_idx, sort_idx] = sort (ic(match));
+      c = c(c_idx, :);
     endif
     len_a = rows (a);
   else
@@ -133,8 +133,8 @@
     else
       c = [a(:); b(:)];
       ## FIXME: Is there a way to avoid a call to sort?
-      [c_ind, sort_ind] = sort (ic(match));
-      c = c(c_ind);
+      [c_idx, sort_idx] = sort (ic(match));
+      c = c(c_idx);
     endif
 
     ## Adjust output orientation for Matlab compatibility
@@ -149,7 +149,7 @@
     if (! optsorted)
       ## FIXME: Is there a way to avoid a call to sort?
       ia = sort (ia);
-      ib_ind(sort_ind) = 1:numel(sort_ind);
+      ib_ind(sort_idx) = 1:numel(sort_idx);
       ## Change ordering to conform to unsorted c
       ib(ib_ind) = ib;
     endif
--- a/scripts/set/unique.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/set/unique.m	Fri Apr 12 15:10:26 2024 +0200
@@ -84,9 +84,6 @@
 ## outputs @var{i}, @var{j} will follow the shape of the input @var{x} rather
 ## than always being column vectors.
 ##
-## The third output, @var{j}, has not been implemented yet when the sort
-## order is @qcode{"stable"}.
-##
 ## @seealso{uniquetol, union, intersect, setdiff, setxor, ismember}
 ## @end deftypefn
 
@@ -189,8 +186,8 @@
   ## Calculate y output
   if (optrows)
     if (nargout > 1 || ! optsorted)
-      [y, i] = sortrows (x);
-      i = i(:);
+      [y, j] = sortrows (x);
+      j = j(:);
     else
       y = sortrows (x);
     endif
@@ -199,7 +196,7 @@
       y(match,:) = [];
     else
       y = x;
-      y(i([false; match]), :) = [];
+      y(j([false; match]), :) = [];
     endif
   else
     if (isvector (x))
@@ -208,8 +205,8 @@
       y = x(:);
     endif
     if (nargout > 1 || ! optsorted)
-      [y, i] = sort (y);
-      i = i(:);
+      [y, j] = sort (y);
+      j = j(:);
     else
       y = sort (y);
     endif
@@ -226,40 +223,76 @@
       else
         y = x(:);
       endif
-      y(i([false; match(:)])) = [];
+      y(j([false; match(:)])) = [];
     endif
   endif
 
-  ## Calculate j output (3rd output)
-  if (nargout > 2)
-    j = i;  # cheap way to copy dimensions
-    j(i) = cumsum ([1; ! match(:)]);
-    if (! optsorted)
-      warning ("unique: third output J is not yet implemented");
-      j = [];
-    endif
+
+  ## Calculate i and j outputs (2nd and 3rd outputs)
+  if (nargout > 1)
 
-    if (optlegacy && isrowvec)
-      j = j.';
-    endif
-  endif
+    if (optsorted)
 
-  ## Calculate i output (2nd output)
-  if (nargout > 1)
-    if (optsorted)
       idx = find (match);
+
       if (! optlegacy && optfirst)
         idx += 1;   # in-place is faster than other forms of increment
       endif
+
+      i = j;
       i(idx) = [];
+
+      if (nargout > 2)
+        j(j) = cumsum (! [false; match(:)]);
+      endif
+
     else
-      i([false; match(:)]) = [];
-      ## FIXME: Is there a way to avoid a call to sort?
-      i = sort (i);
+
+      ## Get inverse of sort index j so that sort(x)(k) = x(j)(k) = x.
+      k = j;  # cheap way to copy dimensions
+      k(j) = 1:n;
+
+      ## Generate logical index of sorted unique value locations.
+      uniquex = ! [false; match(:)];
+
+      ## Remap unique locations to unsorted x, such that y = x(i).
+      i = find (uniquex(k));
+
+      if (nargout > 2)
+        ## Example of index mappings to obtain i and j ('stable').
+        ## x = [40,20,40,20,20,30,10]'     # input data, n = 7, m = 4
+        ## x(j) = [10,20,20,20,30,40,40]'  # sorted x
+        ## j =   [7,2,4,5,6,1,3]'          # sort index, x(j) = sort(x)
+        ## k = [6,2,7,3,4,5,1]'            # inverse idx of j, sort(x)(k) = x
+        ## y = [40,20,30,10]'              # unique x preserving ordering
+        ## uniquex = [1,1,0,0,1,1,0]'      # logical sorted idx of unique x vals
+        ## i = [1,2,6,7]'                  # unique output index, y = x(i)
+        ## u = [1,2,5,6]'                  # linear idx of unique x(j) elems.
+        ## l = [1,2,2,2,5,6,6]'            # unique elem. in full sort(x)
+        ## l(k) = [6,2,6,2,2,5,1]'         # l mapped back to unsorted x
+        ## j(l(k)) =  [1,2,1,2,2,6,7]'     # unique elem. mapped to x idx
+        ## p(i) = [1,2,#,#,#,3,4]'         # map between i and j(l(k))
+
+        ni = numel (i);
+
+        u = find (uniquex); # Linear index of unique elements of sort(x)
+        l = u(cumsum (uniquex)); # Expand u for all elements in sort(x)
+
+        p = j; # cheap way to copy dimensions
+        p(i) = 1:ni; # set p to contain the vector positions of i.
+
+        j = p(j(l(k))); # Replace j with 3rd output mapping y->x.
+
+      endif
     endif
 
     if (optlegacy && isrowvec)
       i = i.';
+
+      if (nargout > 2)
+        j = j.';
+      endif
+
     endif
   endif
 
@@ -302,11 +335,10 @@
 %! assert (j, [1;1;2;3;3;3;4]);
 
 %!test
-%! [y,i,~] = unique ([4,4,2,2,2,3,1], "stable");
+%! [y,i,j] = unique ([4,4,2,2,2,3,1], "stable");
 %! assert (y, [4,2,3,1]);
 %! assert (i, [1;3;6;7]);
-%! ## FIXME: 'j' input not calculated with stable
-%! ##assert (j, []);
+%! assert (j, [1;1;2;2;2;3;4]);
 
 %!test
 %! [y,i,j] = unique ([1,1,2,3,3,3,4]', "last");
@@ -335,11 +367,10 @@
 
 %!test
 %! A = [4,5,6; 1,2,3; 4,5,6];
-%! [y,i,~] = unique (A, "rows", "stable");
+%! [y,i,j] = unique (A, "rows", "stable");
 %! assert (y, [4,5,6; 1,2,3]);
 %! assert (A(i,:), y);
-%! ## FIXME: 'j' output not calculated correctly with "stable"
-%! ##assert (y(j,:), A);
+%! assert (y(j,:), A);
 
 ## Test "legacy" option
 %!test
@@ -355,6 +386,60 @@
 %! assert (i, [2; 5; 4; 3]);
 %! assert (j, [4; 1; 4; 3; 2]);
 
+%!test <*65176>
+%! a = [3 2 1 2; 1 2 2 1];
+%! [o1, o2, o3] = unique (a);
+%! assert ({o1, o2, o3}, {[1;2;3], [2;3;1], [3;1;2;2;1;2;2;1]});
+%! [o1, o2, o3] = unique (a, "stable");
+%! assert ({o1, o2, o3}, {[3;1;2], [1;2;3], [1;2;3;3;2;3;3;2]})
+
+%!test <*65176>
+%! a = [4,2,4,2,2,3,1];
+%! [o1, o2, o3] = unique (a);
+%! assert ({o1, o2, o3}, {[1,2,3,4], [7;2;6;1], [4;2;4;2;2;3;1]});
+%! [o1, o2, o3] = unique (a, "stable");
+%! assert ({o1, o2, o3}, {[4,2,3,1], [1;2;6;7], [1;2;1;2;2;3;4]})
+
+%!test <*65176>
+%! a = [3 2 1 2; 2 1 2 1];
+%! [o1, o2, o3] = unique (a(1,:), "rows");
+%! assert ({o1, o2, o3}, {a(1,:), 1, 1});
+%! [o1, o2, o3] = unique (a(1,:), "rows", "stable");
+%! assert ({o1, o2, o3}, {a(1,:), 1, 1});
+%! [o1, o2, o3] = unique (a, "rows");
+%! assert ({o1, o2, o3}, {[a(2,:); a(1,:)], [2;1], [2;1]});
+%! [o1, o2, o3] = unique (a, "rows", "stable");
+%! assert ({o1, o2, o3}, {a, [1;2], [1;2]});
+%! [o1, o2, o3] = unique ([a;a], "rows");
+%! assert ({o1, o2, o3}, {[a(2,:); a(1,:)], [2;1], [2;1;2;1]});
+%! [o1, o2, o3] = unique ([a;a], "rows", "stable");
+%! assert ({o1, o2, o3}, {a, [1;2], [1;2;1;2]});
+
+
+%!test <*65176>
+%! a = gallery ("integerdata", [-100, 100], 6, 6);
+%! a = [a(2,:); a(1:5,:); a(2:6,:)];
+%! [o1, o2, o3] = unique (a);
+%! assert ({o1, o1(o3), o2, o3}, {a(:)(o2), a(:), ...
+%! [26;22;34;45;57; 6;11;17;33;28;35;15;56; 2;59; 4;66; ...
+%!  16;50;49;27;24;37;44;48;39;38;13;23; 5;12;46;55; 1], ...
+%! [34;14;34;16;30; 6;34;16;30; 6; 7;31;28;31;12;18; 8;31;12;18; 8; 2;29; ...
+%!  22;29; 1;21;10;29; 1;21;10; 9; 3;11; 3;23;27;26; 3;23;27;26;24; 4;32; ...
+%!  4; 25;20;19; 4;25;20;19;33;13; 5;13;15; 2;24;13;15; 2;24;17]});
+%! [o1, o2, o3] = unique (a, "stable");
+%! assert ({o1, o1(o3), o2, o3}, {a(:)(o2), a(:), ...
+%! [ 1; 2; 4; 5; 6;11;12;13;15;16;17;22;23;24;26;27;28; ...
+%!  33;34;35;37;38;39;44;45;46;48;49;50;55;56;57;59;66], ...
+%! [ 1; 2; 1; 3; 4; 5; 1; 3; 4; 5; 6; 7; 8; 7; 9;10;11; 7; 9;10;11;12;13; ...
+%!  14;13;15;16;17;13;15;16;17;18;19;20;19;21;22;23;19;21;22;23;24;25;26;...
+%!  25;27;28;29;25;27;28;29;30;31;32;31;33;12;24;31;33;12;24;34]});
+%! [o1, o2, o3] = unique (a, "rows");
+%! assert ({o1, o1(o3,:), o2, o3}, {a(o2,:), a, ...
+%! [6;11;2;4;5;1], [6;3;6;4;5;1;6;4;5;1;2]});
+%! [o1, o2, o3] = unique (a, "rows", "stable");
+%! assert ({o1, o1(o3,:), o2, o3}, {a(o2,:), a, ...
+%! [1;2;4;5;6;11], [1;2;1;3;4;5;1;3;4;5;6]});
+
 ## Test input validation
 %!error <Invalid call> unique ()
 %!error <X must be an array or cell array of strings> unique ({1})
@@ -376,6 +461,4 @@
 %!error <invalid option> unique ({"a", "b", "c"}, "rows", "UnknownOption2")
 %!error <invalid option> unique ({"a", "b", "c"}, "UnknownOption1", "last")
 %!warning <"rows" is ignored for cell arrays> unique ({"1"}, "rows");
-%!warning <third output J is not yet implemented>
-%! [y,i,j] = unique ([2,1], "stable");
-%! assert (j, []);
+
--- a/scripts/signal/movfun.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/signal/movfun.m	Fri Apr 12 15:10:26 2024 +0200
@@ -178,23 +178,25 @@
   valid_bc = {"shrink", "discard", "fill", "same", "periodic"};
 
   ## Parse input arguments
-  parser = inputParser ();
-  parser.FunctionName = "movfun";
-  parser.addParamValue ("Endpoints", "shrink", ...
-    @(x) any (strcmpi (x, valid_bc)) || (isnumeric (x) && isscalar (x)));
-  parser.addParamValue ("dim", [], ...
-    @(d) isempty (d) || (isscalar (d) && isindex (d, ndims (x))));
-  parser.addParamValue ("nancond", "includenan", ...
-    @(x) any (strcmpi (x, {"includenan", "omitnan"})));
-  parser.addParamValue ("outdim", [], ...
-    @(d) isempty (d) || (isvector (d) && isindex (d)));
+  persistent parser;
+  if isempty (parser)
+    parser = inputParser ();
+    parser.FunctionName = "movfun";
+    parser.addParamValue ("Endpoints", "shrink", ...
+      @(x) any (strcmpi (x, valid_bc)) || (isnumeric (x) && isscalar (x)));
+    parser.addParamValue ("dim", [], ...
+      @(d) isempty (d) || (isscalar (d) && isindex (d, ndims (x))));
+    parser.addParamValue ("nancond", "includenan", ...
+      @(x) any (strcmpi (x, {"includenan", "omitnan"})));
+    parser.addParamValue ("outdim", [], ...
+      @(d) isempty (d) || (isvector (d) && isindex (d)));
+  endif
 
   parser.parse (varargin{:});
   bc      = parser.Results.Endpoints;   # boundary condition
   dim     = parser.Results.dim;         # dimension to be used as input
   nancond = parser.Results.nancond;     # whether NaN are ignored or not
   outdim  = parser.Results.outdim;      # selected output dimension of fcn
-  clear parser
   ## End parse input arguments
 
   if (isempty (x))
@@ -261,11 +263,10 @@
     endswitch
   endif
 
-  ## FIXME: Validation doesn't seem to work correctly (noted 12/16/2018).
   ## Validate that outdim makes sense
-  fout = fcn (zeros (length (win), 1, class (x)));  # output for window
-  yclass = class (fout);                    # record class of fcn output
-  noutdim = length (fout);                  # number of output dimensions
+  fout = fcn (x(1:length (win))(:));  # output for window (see bug #55984)
+  yclass = class (fout);              # record class of fcn output
+  noutdim = length (fout);            # number of output dimensions
   if (! isempty (outdim))
     if (max (outdim) > noutdim)
       error ("Octave:invalid-input-arg", ...
--- a/scripts/signal/private/triangle_sw.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/signal/private/triangle_sw.m	Fri Apr 12 15:10:26 2024 +0200
@@ -24,21 +24,21 @@
 ########################################################################
 
 ## -*- texinfo -*-
-## @deftypefn {} {@var{retval} =} triangle_sw (@var{n}, @var{b})
+## @deftypefn {} {@var{c} =} triangle_sw (@var{n}, @var{b})
 ## Triangular spectral window.
 ##
 ## Subfunction used for spectral density estimation.
 ## @seealso{spectral_xdf}
 ## @end deftypefn
 
-function retval = triangle_sw (n, b)
+function c = triangle_sw (n, b)
 
-  retval = zeros (n,1);
-  retval(1) = 1 / b;
+  c = zeros (n,1);
+  c(1) = 1 / b;
 
   l = (2:n)' - 1;
   l = 2 * pi * l / n;
 
-  retval(2:n) = b * (sin (l / (2*b)) ./ sin (l / 2)).^2;
+  c(2:n) = b * (sin (l / (2*b)) ./ sin (l / 2)).^2;
 
 endfunction
--- a/scripts/specfun/betaln.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/specfun/betaln.m	Fri Apr 12 15:10:26 2024 +0200
@@ -56,8 +56,6 @@
 
   if (! isreal (a) || ! isreal (b))
     error ("betaln: A and B must be real");
-  elseif (! size_equal (a, b) && numel (a) != 1 && numel (b) != 1)
-    error ("betaln: A and B must have consistent sizes");
   endif
 
   lnb = gammaln (a) + gammaln (b) - gammaln (a + b);
@@ -72,6 +70,3 @@
 %!error <Invalid call> betaln (1)
 %!error <A and B must be real> betaln (1i, 2)
 %!error <A and B must be real> betaln (2, 1i)
-%!error <A and B must have consistent sizes> betaln ([1 2], [1 2 3])
-%!error <A and B must have consistent sizes> betaln ([1 2 3], [1 2])
-%!error <A and B must have consistent sizes> betaln ([1 2 3], [1 2 3]')
--- a/scripts/specfun/nchoosek.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/specfun/nchoosek.m	Fri Apr 12 15:10:26 2024 +0200
@@ -112,48 +112,53 @@
   n = numel (v);
 
   if (n == 1 && isnumeric (v))
-    ## Improve precision over direct call to prod().
-    ## Steps: 1) Make a list of integers for numerator and denominator,
-    ## 2) filter out common factors, 3) multiply what remains.
-    k = min (k, v-k);
-
-    if (isinteger (v) || isinteger (k))
-      numer = (v-k+1):v;
-      denom = (1:k);
+    ## Compute number of combinations rather than actual set combinations.
+    try
+      ## Use subtraction operation to validate combining integer data types
+      ## and for type propagation rules between integer and floating point.
+      k = min (k, v-k);
+    catch
+      error ("nchoosek: incompatible input types for N (%s), K (%s)", ...
+             class (v), class (k));
+    end_try_catch
+    is_int = isinteger (k);
+    if (is_int)
+      imax = intmax (k);
     else
-      ## For a ~25% performance boost, multiply values pairwise so there
-      ## are fewer elements in do/until loop which is the slow part.
-      ## Since Odd*Even is guaranteed to be Even, also take out a factor
-      ## of 2 from numerator and denominator.
-      if (rem (k, 2))  # k is odd
-        numer = [((v-k+1:v-(k+1)/2) .* (v-1:-1:v-(k-1)/2)) / 2, v];
-        denom = [((1:(k-1)/2) .* (k-1:-1:(k+1)/2)) / 2, k];
-      else             # k is even
-        numer = ((v-k+1:v-k/2) .* (v:-1:v-k/2+1)) / 2;
-        denom = ((1:k/2) .* (k:-1:k/2+1)) / 2;
-      endif
+      imax = flintmax (k);
     endif
-
-    ## Remove common factors from numerator and denominator
-    do
-      for i = numel (denom):-1:1
-        factors = gcd (denom(i), numer);
-        [f, j] = max (factors);
-        denom(i) /= f;
-        numer(j) /= f;
-      endfor
-      denom = denom(denom > 1);
-      numer = numer(numer > 1);
-    until (isempty (denom))
-
-    C = prod (numer, "native");
-    if (isfloat (C) && C > flintmax (C))
+    C = 1;
+    for i = 1:k
+      if (C * (v - k + i) >= imax)
+        ## Avoid overflow / precision loss by determining the smallest
+        ## possible factor of (C * (n-k+i)) and i via the gcd.
+        ## Note that by design in each iteration
+        ##   1) C will always increase (factor is always > 1).
+        ##   2) C will always be a whole number.
+        ## Therefore, using the gcd will always provide the best possible
+        ## solution until saturation / has the least precision loss.
+        g1 = gcd (C, i);
+        g2 = gcd (v - k + i, i/g1);
+        C /= g1;
+        C *= (v - k + i)/g2;
+        if (is_int && (C == imax))
+          break;  # Stop here; saturation reached.
+        endif
+        C /= i/(g1 * g2);
+      else
+        C *= (v - k + i);
+        C /= i;
+      endif
+    endfor
+    if (! is_int && C > imax)
       warning ("Octave:nchoosek:large-output-float", ...
                "nchoosek: possible loss of precision");
-    elseif (isinteger (C) && C == intmax (C))
+    elseif (is_int && C == imax)
       warning ("Octave:nchoosek:large-output-integer", ...
                "nchoosek: result may have saturated at intmax");
     endif
+
+  ## Compute actual set combinations
   elseif (k == 0)
     C = v(zeros (1, 0));  # Return 1x0 object for Matlab compatibility
   elseif (k == 1)
@@ -283,6 +288,15 @@
 %! assert (x, uint8 (252));
 %! assert (class (x), "uint8");
 
+## Test combining rules for integers and floating point
+%!test
+%! x = nchoosek (uint8 (10), single (5));
+%! assert (x, uint8 (252));
+
+%!test
+%! x = nchoosek (double (10), single (5));
+%! assert (x, single (252));
+
 %!test <*63538>
 %! x = nchoosek ([1:3]', 2);
 %! assert (x, [1 2; 1 3; 2 3]);
@@ -299,6 +313,7 @@
 %!error <N must be a non-negative integer .= K> nchoosek (100, 145)
 %!error <N must be a non-negative integer .= K> nchoosek (-100, 45)
 %!error <N must be a non-negative integer .= K> nchoosek (100.5, 45)
+%!error <incompatible input types> nchoosek (uint8 (15), uint16 (5))
 %!warning <possible loss of precision> nchoosek (100, 45);
 %!warning <result .* saturated> nchoosek (uint64 (80), uint64 (40));
 %!warning <result .* saturated> nchoosek (uint32 (80), uint32 (40));
--- a/scripts/statistics/iqr.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/statistics/iqr.m	Fri Apr 12 15:10:26 2024 +0200
@@ -67,28 +67,41 @@
 
 function z = iqr (x, dim)
 
-  ## input checks
+  ## Perform input checks.
   if (nargin < 1)
     print_usage ();
   elseif (nargin < 2)
     dim = [];
   endif
 
-  if (! (isnumeric (x) || islogical (x)))
-    error ("iqr: X must be a numeric vector or matrix");
-  endif
-
   vecdim_flag = false;
   nd = ndims (x);
   sz = size (x);
+  empty_x = any (sz == 0);
+
+  if (! (empty_x || isnumeric (x) || islogical (x)))
+    error ("iqr: X must be a numeric vector or matrix");
+  endif
 
   if (isempty (dim))
     ## Find first non-singleton dimension.
-    if (max (sz) == 1)
+    if (max (sz) == 1  && ! empty_x)
       dim = 2;
     else
-      dim = find ((sz > 1), 1);
+      dim = find ((sz != 1), 1);
     endif
+
+  if (empty_x)
+    ## Handle empty x with no input dim.
+    if ((ndims (x) == 2 && all (sz == 0)) || iscolumn (x) || isrow (x))
+      z = NaN;
+    else
+      sz(dim) = 1;
+      z = NaN (sz);
+    endif
+    return
+  endif
+
   else
 
     if (isvector (dim) && isnumeric (dim)
@@ -97,6 +110,13 @@
       if (((num_vecdims = numel (dim)) > 1) && all (diff (sort (dim))))
         ## DIM must be 1-D and non repeating.
 
+        if (empty_x)
+          ## Handle empty x with input vecdim.
+          sz(dim(dim <= nd)) = 1;
+          z = NaN (sz);
+          return
+        endif
+
         ## Detect trivial case of DIM being all dimensions (same as "all").
         highest_dim = (max (nd, max (dim)));
         if ((num_vecdims == nd) && (highest_dim == nd))
@@ -144,14 +164,26 @@
 
       elseif (! isscalar (dim))
         error ("iqr: vector DIM must contain non-repeating positive integers");
+
+      elseif (empty_x)
+        ## Handle empty x with scalar input dim.
+        sz(dim(dim <= nd)) = 1;
+        z = NaN (sz);
+        return
       endif
 
     elseif (strcmp (lower (dim), "all"))
-      ## "ALL" simplifies to collapsing all elements to single vector
+      ## "ALL" simplifies to collapsing all elements to single vector.
       x = x(:);
       dim = 1;
       sz = size (x);
 
+      if (empty_x)
+        ## Handle empty x with "all" dim input.
+        z = NaN;
+        return
+      endif
+
     else
       error ("iqr: DIM must be a positive integer scalar, vector, or 'all'");
     endif
@@ -159,10 +191,10 @@
   endif
 
   if (((dim > nd) || (sz(dim) == 1)) && all (isfinite (x)))
-    ## shortcut easy zeros
+    ## Shortcut easy zeros.
     z = zeros (sz);
   elseif (iscolumn (x) && (dim == 1))
-    ## detect col vector with quantile/diff dim requirement mismatch
+    ## Detect col vector with quantile/diff dim requirement mismatch.
     z = abs (diff (quantile (x, [0.25, 0.75], 1), [], 2));
   else
     z = abs (diff (quantile (x, [0.25, 0.75], dim), [], dim));
@@ -189,83 +221,113 @@
 %!assert (iqr ([1:5; 2:6], "all"), 3)
 
 %!test
-%! x = reshape (1:6, [1 2 3]);
+%! x = reshape (1:6, [1, 2, 3]);
 %! assert (iqr (x), ones (1, 1, 3));
 %! assert (iqr (x, 1), zeros (1, 2, 3));
 %! assert (iqr (x, 2), ones (1, 1, 3));
-%! assert (iqr (x, 3), [3 3]);
+%! assert (iqr (x, 3), [3, 3]);
 
 ## n-D arrays
 %!test
 %! x = magic (4); x = cat (3,x, 2*x, 3*x); x = cat (4, x, 2*x);
-%! y = cat (3, 8*[1 1 1 1], 16*[1 1 1 1], 24*[1 1 1 1]);
+%! y = cat (3, 8*[1, 1, 1, 1], 16*[1, 1, 1, 1], 24*[1, 1, 1, 1]);
 %! assert (iqr (x), cat (4, y, 2*y));
 %! assert (iqr (x, 1), cat (4, y, 2*y));
-%! y = cat (3, 4*[3 1 1 3].', 8*[3 1 1 3].', 12*[3 1 1 3].');
+%! y = cat (3, 4*[3, 1, 1, 3].', 8*[3, 1, 1, 3].', 12*[3, 1, 1, 3].');
 %! assert (iqr (x, 2), cat (4, y, 2*y));
-%! y = [24 3 4.5 19.5; 7.5 16.5 15 12; 13.5 10.5 9, 18; 6 21 22.5 1.5];
+%! y = [24, 3, 4.5, 19.5; 7.5, 16.5, 15, 12; 13.5, 10.5, 9, 18; 6, 21, 22.5, 1.5];
 %! assert (iqr (x, 3), cat (4, y, 2*y));
-%! y = [16 2 3 13; 5 11 10 8; 9 7 6 12; 4 14 15 1];
+%! y = [16, 2, 3, 13; 5, 11, 10, 8; 9, 7, 6, 12; 4, 14, 15, 1];
 %! assert (iqr (x, 4), cat (3, y, 2*y, 3*y));
 %! assert (iqr (x, 5), zeros (size (x)));
 
 ## vector dimensions
-%!assert (iqr (17, [1 8]), 0)
-%!assert (iqr ([[1 2 5]; [2 5 6]], [1 2]), 3)
-%!assert (iqr (cat (3, [1 2 5; 2 5 6], [1 2 5; 2 5 6]), [1 2]), cat(3, 3, 3))
-%!assert (iqr (cat (3, [1 2 5; 2 5 6], [1 2 5; 2 5 6]), [1 2]'), cat(3, 3, 3))
+%!assert (iqr (17, [1, 8]), 0)
+%!assert (iqr ([[1, 2, 5]; [2, 5, 6]], [1, 2]), 3)
+%!assert (iqr (cat (3, [1, 2, 5; 2, 5, 6], [1, 2, 5; 2, 5, 6]), [1, 2]), cat(3, 3, 3))
+%!assert (iqr (cat (3, [1, 2, 5; 2, 5, 6], [1, 2, 5; 2, 5, 6]), [1, 2]'), cat(3, 3, 3))
 %!test
 %! x = magic (4); x = cat (3, x, 2*x, 3*x); x = cat (4, x, 2*x);
 %! y = cat (3, 8, 16, 24);
-%! assert (iqr (x, [1 2]), cat (4, y, 2*y));
-%! y = [14, 18.5, 17.5 19.5];
-%! assert (iqr (x, [1 3]), cat (4, y, 2*y));
-%! y = [10.5 12.5 11.5 15.0000];
-%! assert (iqr (x, [1 4]), cat (3, y, 2*y, 3*y));
-%! assert (iqr (x, [1 5]), iqr (x, 1));
-%! y = [24 13 12 25.5]';
-%! assert (iqr (x, [2 3]), cat (4, y, 2*y));
+%! assert (iqr (x, [1, 2]), cat (4, y, 2*y));
+%! y = [14, 18.5, 17.5, 19.5];
+%! assert (iqr (x, [1, 3]), cat (4, y, 2*y));
+%! y = [10.5, 12.5, 11.5, 15];
+%! assert (iqr (x, [1, 4]), cat (3, y, 2*y, 3*y));
+%! assert (iqr (x, [1, 5]), iqr (x, 1));
+%! y = [24, 13, 12, 25.5]';
+%! assert (iqr (x, [2, 3]), cat (4, y, 2*y));
 %! y = [17.5, 9, 8, 18.5]';
-%! assert (iqr (x, [2 4]), cat (3, y, 2*y, 3*y));
-%! assert (iqr (x, [3 4]), [32 4 6 26; 10 22 20 16; 18 14 12 24; 8 28 30 2]);
-%! assert (iqr (x, [3 4]), iqr (x, [4 3]));
-%! assert (iqr (x, [1 2 3]), cat (4, 17.5, 35));
-%! assert (iqr (x, [2 3 4]), [29.5 19.5 23 31]');
-%! assert (iqr (x, [1 3 4]), [22 28 22 30.5]);
-%! assert (iqr (x, [1 2 4]), cat (3, 11, 22, 33));
-%! assert (iqr (x, [1 2 5]), iqr (x, [1 2]));
-%! assert (iqr (x, [5 6]), zeros (size (x)));
+%! assert (iqr (x, [2, 4]), cat (3, y, 2*y, 3*y));
+%! assert (iqr (x, [3, 4]), [32, 4, 6, 26; 10, 22, 20, 16; 18, 14, 12, 24; 8, 28, 30, 2]);
+%! assert (iqr (x, [3, 4]), iqr (x, [4, 3]));
+%! assert (iqr (x, [1, 2, 3]), cat (4, 17.5, 35));
+%! assert (iqr (x, [2, 3, 4]), [29.5, 19.5, 23, 31]');
+%! assert (iqr (x, [1, 3, 4]), [22, 28, 22, 30.5]);
+%! assert (iqr (x, [1, 2, 4]), cat (3, 11, 22, 33));
+%! assert (iqr (x, [1, 2, 5]), iqr (x, [1, 2]));
+%! assert (iqr (x, [5, 6]), zeros (size (x)));
 
 ## Inf, NaN
 %!assert (iqr (Inf), NaN)
 %!assert (iqr (-Inf), NaN)
 %!assert (iqr (NaN), NaN)
 %!assert (iqr (NaN), NaN)
-%!assert (iqr ([1 2 Inf], 1), [0 0 NaN])
-%!assert (iqr ([1 2 Inf], 2), Inf)
-%!assert (iqr ([1 2 -Inf], 1), [0 0 NaN])
-%!assert (iqr ([1 2 -Inf], 2), Inf)
-%!assert (iqr ([1 2 3 NaN], 1), [0 0 0 NaN])
-%!assert (iqr ([1 2 3 NaN], 2), 1.5)
-%!assert (iqr ([1 NaN 2 3], 2), 1.5)
+%!assert (iqr ([1, 2, Inf], 1), [0, 0, NaN])
+%!assert (iqr ([1, 2, Inf], 2), Inf)
+%!assert (iqr ([1, 2, -Inf], 1), [0, 0, NaN])
+%!assert (iqr ([1, 2, -Inf], 2), Inf)
+%!assert (iqr ([1, 2, 3, NaN], 1), [0, 0, 0, NaN])
+%!assert (iqr ([1, 2, 3, NaN], 2), 1.5)
+%!assert (iqr ([1, NaN, 2, 3], 2), 1.5)
 %!assert (iqr (NaN (2), 1), [NaN, NaN])
 %!assert (iqr (NaN (2), 2), [NaN; NaN])
 %!assert (iqr (NaN (2), 3), NaN (2))
-%!assert (iqr ([[1 2 5], [2 NaN 6]], "all"), 3.5)
+%!assert (iqr ([[1, 2, 5], [2, NaN, 6]], "all"), 3.5)
+
+## Empty inputs
+%!assert <*65531> (iqr ([]), NaN)
+%!assert <*65531> (iqr (ones (0, 1)), NaN)
+%!assert <*65531> (iqr (ones (0, 1), 1), NaN)
+%!assert <*65531> (iqr (ones (0, 1), 2), NaN (0, 1))
+%!assert <*65531> (iqr (ones (0, 1), 3), NaN (0, 1))
+%!assert <*65531> (iqr (ones (1, 0)), NaN)
+%!assert <*65531> (iqr (ones (1, 0), 1), NaN (1, 0))
+%!assert <*65531> (iqr (ones (1, 0), 2), NaN)
+%!assert <*65531> (iqr (ones (1, 0), 3), NaN (1, 0))
+%!assert <*65531> (iqr (ones (1, 0), 9), NaN (1, 0))
+%!assert <*65531> (iqr (ones (1, 1, 0)), NaN)
+%!assert <*65531> (iqr (ones (0, 0, 1, 0)), NaN (1, 0, 1, 0))
+%!assert <*65531> (iqr (ones (1, 1, 1, 0)), NaN)
+%!assert <*65531> (iqr (ones (1, 1, 1, 0), 1), NaN (1, 1, 1, 0))
+%!assert <*65531> (iqr (ones (1, 1, 1, 0), 1), NaN (1, 1, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 1), NaN (1, 0, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 2), NaN (0, 1, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 3), NaN (0, 0, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 4), NaN (0, 0, 1, 1))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 9), NaN (0, 0, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 2]), NaN (1, 1, 1, 0))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 4]), NaN (1, 0, 1, 1))
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), [1, 9]), NaN (1, 0, 1, 0))
+%!assert <*65531> (iqr ([], "all"), NaN)
+%!assert <*65531> (iqr (ones (0, 1), "all"), NaN)
+%!assert <*65531> (iqr (ones (1, 0), "all"), NaN)
+%!assert <*65531> (iqr (ones (1, 1, 0), "all"), NaN)
+%!assert <*65531> (iqr (ones (0, 0, 1, 0), 'all'), NaN)
 
 ## input validation
-%!error iqr ()
+%!error <Invalid call> iqr ()
 %!error iqr (1, 2, 3)
-%!error <X .* numeric> iqr (['A'; 'B'])
+%!error <X must be a numeric> iqr (['A'; 'B'])
 %!error <DIM .* positive integer> iqr (1, 'A')
 %!error <DIM .* positive integer> iqr (1, 0)
 %!error <DIM .* positive integer> iqr (1, -2)
 %!error <DIM .* positive integer> iqr (1, 1.4)
-%!error <DIM .* positive integer> iqr (1, [1 -2])
-%!error <DIM .* positive integer> iqr (1, [1 1.4])
-%!error <DIM .* positive integer> iqr ([1 2 3], NaN)
-%!error <DIM .* positive integer> iqr ([1 2 3], [2 NaN])
-%!error <DIM .* positive integer> iqr ([1 2 3], Inf)
-%!error <DIM .* positive integer> iqr ([1 2 3], [2 Inf])
-%!error <vector DIM .* non-repeating> iqr ([1 2 3], [1 2 1])
-%!error <DIM .* vector> iqr (1, [1 2; 3 4])
+%!error <DIM .* positive integer> iqr (1, [1, -2])
+%!error <DIM .* positive integer> iqr (1, [1, 1.4])
+%!error <DIM .* positive integer> iqr ([1, 2, 3], NaN)
+%!error <DIM .* positive integer> iqr ([1, 2, 3], [2, NaN])
+%!error <DIM .* positive integer> iqr ([1, 2, 3], Inf)
+%!error <DIM .* positive integer> iqr ([1, 2, 3], [2, Inf])
+%!error <vector DIM .* non-repeating> iqr ([1, 2, 3], [1, 2, 1])
+%!error <DIM .* vector> iqr (1, [1, 2; 3, 4])
--- a/scripts/testfun/assert.m	Sat Apr 06 14:43:10 2024 +0200
+++ b/scripts/testfun/assert.m	Fri Apr 12 15:10:26 2024 +0200
@@ -765,17 +765,17 @@
 ## Convert all error indices into tuple format
 function cout = ind2tuple (matsize, erridx)
 
-  cout = cell (numel (erridx), 1);
   tmp = cell (1, numel (matsize));
   [tmp{:}] = ind2sub (matsize, erridx(:));
   subs = [tmp{:}];
   if (numel (matsize) == 2)
-    subs = subs(:, matsize != 1);
+    subs = subs(:, matsize != 1);  # For vectors, use 1-D index
   endif
-  for i = 1:numel (erridx)
-    loc = sprintf ("%d,", subs(i,:));
-    cout{i} = ["(" loc(1:end-1) ")"];
-  endfor
+  fmt = repmat ('%d,', 1, max (columns (subs), 1));
+  fmt(end) = [];   # delete final extra comma
+  cout = ostrsplit (sprintf (['(' fmt ')', '$'], subs'), '$');
+  cout(end) = [];  # delete extra cell from final '$'
+  cout = cout.';   # return column vector 
 
 endfunction
 
@@ -785,15 +785,24 @@
 
   str = ["ASSERT errors for:  assert " argin "\n"];
   str = [str, "\n  Location  |  Observed  |  Expected  |  Reason\n"];
-  for i = 1:length (err.index)
-    leni = length (err.index{i});
-    leno = length (err.observed{i});
-    lene = length (err.expected{i});
-    str = [str, sprintf("%*s%*s %*s%*s %*s%*s   %s\n",
-                  6+fix(leni/2), err.index{i}   , max (6-fix(leni/2), 0), "",
-                  6+fix(leno/2), err.observed{i}, max (6-fix(leno/2), 0), "",
-                  6+fix(lene/2), err.expected{i}, max (6-fix(lene/2), 0), "",
-                  err.reason{i})];
+
+  pos = numel (str);
+  str(pos + 100 * numel (err.index)) = ' ';
+  for i = 1:numel (err.index)
+    leni = numel (err.index{i});
+    leno = numel (err.observed{i});
+    lene = numel (err.expected{i});
+    tmp = sprintf("%*s%*s %*s%*s %*s%*s   %s\n",
+            6+fix(leni/2), err.index{i}   , max (6-fix(leni/2), 0), "",
+            6+fix(leno/2), err.observed{i}, max (6-fix(leno/2), 0), "",
+            6+fix(lene/2), err.expected{i}, max (6-fix(lene/2), 0), "",
+            err.reason{i});
+    if (pos + numel (tmp) > numel (str))
+      str(end + 1e6) = ' ';
+    endif
+    str((pos + 1):(pos + numel (tmp))) = tmp;
+    pos += numel (tmp);
   endfor
+  str = str(1:pos);
 
 endfunction
--- a/src/main-gui.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/src/main-gui.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -144,7 +144,12 @@
 
   octave::sys::env::set_program_name (argv[0]);
 
-  octave::qt_application app ("octave", "octave-gui", OCTAVE_VERSION,
+  std::string app_name ("octave-gui");
+  std::string settings_file = octave::sys::env::getenv ("OCTAVE_GUI_SETTINGS");
+  if (! settings_file.empty ())
+    app_name = settings_file;
+
+  octave::qt_application app ("octave", app_name, OCTAVE_VERSION,
                               argc, argv);
 
   int ret = app.execute ();
--- a/src/main.in.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/src/main.in.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -314,7 +314,8 @@
           file = octave_cli;
           break;
 
-        case NO_GUI_OPTION:
+        case 'G':
+          // option "--no-gui"
           // If we see this option, then we can just exec octave; we don't
           // have to create a child process and wait for it to exit.  But do
           // exec "octave-gui", not "octave-cli", because even if the
@@ -324,10 +325,10 @@
           new_argv[k++] = argv[old_optind];
           break;
 
-        case GUI_OPTION:
+        case 'g':
+          // option "--gui"
           // If we see this option, then we fork and exec octave with the
-          // --gui option, while continuing to handle signals in the
-          // terminal.
+          // --gui option, while continuing to handle signals in the terminal.
           // Do not copy the arg now, since we still not know if the gui
           // should really be launched.  Just store the index.
           start_gui = true;
@@ -354,14 +355,15 @@
           new_argv[k++] = argv[old_optind];
           break;
 
-        case EVAL_OPTION:
+        case 'e':
+          // option "--eval"
           eval_code = true;
           for (int i = old_optind; i < next_optind; i++)
             new_argv[k++] = argv[i];
           break;
 
         case 'q':
-          // options "--silent" or "--quiet"
+          // options "--quiet" or "--silent"
           warn_display = false;
           new_argv[k++] = argv[old_optind];
           break;
--- a/src/mkoctfile.in.cc	Sat Apr 06 14:43:10 2024 +0200
+++ b/src/mkoctfile.in.cc	Fri Apr 12 15:10:26 2024 +0200
@@ -516,7 +516,7 @@
   "\n"
   "  -v, --verbose           Echo commands as they are executed.\n"
   "\n"
-  "  --silent                Ignored.  Intended to suppress output from\n"
+  "  --quiet                 Ignored.  Intended to suppress output from\n"
   "                          compiler steps.\n"
   "\n"
   "  FILE                    Compile or link FILE.  Recognized file types are:\n"
@@ -799,7 +799,8 @@
         {
           verbose = true;
         }
-      else if (arg == "-silent" ||  arg == "--silent")
+      else if (arg == "-silent" || arg == "--silent"
+               || arg == "-quiet" || arg == "--quiet")
         {
           // Ignored for now.
         }
@@ -1346,7 +1347,7 @@
     }
   else
     {
-#if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
+#if defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS)
       octave_libs = "-L" + quote_path (vars["OCTLIBDIR"])
                     + ' ' + vars["OCTAVE_LIBS"];
 #endif
@@ -1358,7 +1359,7 @@
            + vars["LDFLAGS"] + ' ' + octave_libs + ' '
            + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]);
 
-#if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS)
+#if defined (OCTAVE_USE_WINDOWS_API) || defined (CROSS)
       if (! f77files.empty () && ! vars["FLIBS"].empty ())
         cmd += ' ' + vars["FLIBS"];
 #endif
--- a/test/Makefile.am	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/Makefile.am	Fri Apr 12 15:10:26 2024 +0200
@@ -76,6 +76,7 @@
 include bug-38236/module.mk
 include bug-38691/module.mk
 include bug-41723/module.mk
+include bug-44643/module.mk
 include bug-44940/module.mk
 include bug-45351/module.mk
 include bug-46660/module.mk
@@ -84,6 +85,7 @@
 include bug-49379/module.mk
 include bug-50014/module.mk
 include bug-50035/module.mk
+include bug-50395/module.mk
 include bug-50716/module.mk
 include bug-50831/module.mk
 include bug-51192/module.mk
@@ -112,7 +114,6 @@
 include bug-61191/module.mk
 include bug-63841/module.mk
 include bug-65037/module.mk
-include bug-65220/module.mk
 include class-concat/module.mk
 include classdef/module.mk
 include classdef-debug/module.mk
@@ -122,6 +123,7 @@
 include ctor-vs-method/module.mk
 include fcn-handle/module.mk
 include file-encoding/module.mk
+include help/module.mk
 include json/module.mk
 include jupyter-notebook/module.mk
 include load-path/module.mk
@@ -135,7 +137,7 @@
 # run-octave (optional-prepare-commands)
 
 define run-octave-tests
-  ( $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) --no-init-file --silent \
+  ( $(SHELL) ../run-octave $(RUN_OCTAVE_OPTIONS) --no-init-file --quiet  \
       --no-history -p $(abs_top_builddir)/test/mex \
       $(abs_top_srcdir)/test/fntests.m $(abs_top_srcdir)/test "$(1)" ) && \
   if $(AM_V_P); then \
--- a/test/args.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/args.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -33,6 +33,8 @@
 %!endfunction
 %!test
 %! f;
+%!error <function called with too many inputs> f (1)
+%!error <function called with too many outputs> y = f ()
 
 ## one input with two possible inputs
 %!function f (x, y)
@@ -41,6 +43,8 @@
 %!endfunction
 %!test
 %! f (1);
+%!error <function called with too many inputs> f (1, 2, 3)
+%!error <function called with too many outputs> y = f ()
 
 ## no inputs, one of multiple outputs
 %!function [x, y] = f ()
@@ -50,6 +54,8 @@
 %!endfunction
 %!test
 %! assert (f (), 2);
+%!error <function called with too many inputs> f (1)
+%!error <function called with too many outputs> [x, y, z] = f ()
 
 ## one of multiple inputs, one of multiple outputs
 %!function [x, y] = f (a, b)
@@ -59,6 +65,8 @@
 %!endfunction
 %!test
 %! assert (f (1), 1);
+%!error <function called with too many inputs> f (1, 2, 3)
+%!error <function called with too many outputs> [x, y, z] = f ()
 
 ########################################
 ## Varargin, varargout
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/bug-44643.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,8 @@
+%!test <44643>
+%! a = bug44643 ();
+%! b = bug44643 ();
+%! a.parent = b;
+%! b.child  = a;
+%!
+%! assert (isequal (a, b));
+%! assert (isequal (a, a));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/bug44643.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,6 @@
+classdef bug44643 < handle
+  properties
+    child
+    parent
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-44643/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,5 @@
+bug_44643_TEST_FILES = \
+  %reldir%/bug-44643.tst \
+  %reldir%/bug44643.m
+
+TEST_FILES += $(bug_44643_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug-50395.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,5 @@
+%!test <50395>
+%! a = bug50395_a ();
+%! clear all
+%! c = 3;
+%! a = bug50395_a ();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug50395_a.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,6 @@
+classdef bug50395_a < bug50395_c
+  methods
+     function obj = bug50395_a ()
+     end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/bug50395_c.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,2 @@
+classdef bug50395_c
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug-50395/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,6 @@
+bug_50395_TEST_FILES = \
+  %reldir%/bug-50395.tst \
+  %reldir%/bug50395_a.m \
+  %reldir%/bug50395_c.m
+
+TEST_FILES += $(bug_50395_TEST_FILES)
--- a/test/bug-65220/bug-65220.tst	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2024 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/>.
-##
-########################################################################
-
-%!test <*65220>
-%! unwind_protect
-%!   addpath ('cdefdir');
-%! 
-%!   ## Check methods first (bug was disguised if class checked first)
-%!   s = help ('cdef_help1.meth1');
-%!   assert (regexp (s, 'meth1: method help text ABOVE function'));
-%!
-%!   s = help ('cdef_help1.meth2');
-%!   assert (regexp (s, 'meth2: method help text BELOW function'));
-%!
-%!   s = help ('cdef_help1.meth3');
-%!   assert (regexp (s, 'meth3: method help text BELOW function'));
-%!
-%!   s = '';
-%!   try
-%!     s = help ('cdef_help1.meth4');
-%!   catch
-%!     assert (regexp (lasterr (), "'cdef_help1.meth4' is not documented"));
-%!   end_try_catch
-%!   if (! isempty (s))
-%!     error ("Impossible state: Help text found for 'cdef_help1.meth4'");
-%!   endif
-%!
-%!   ## Check documentation for entire class
-%!   s = help ('cdef_help1');
-%!   assert (regexp (s, 'class cdef_help1 : class help text ABOVE classdef'));
-%!   
-%!   ## Check documentation for constructor
-%!   s = help ('cdef_help1.cdef_help1');
-%!   assert (regexp (s, 'cdef_help1: constructor help text BELOW function'));
-%!   
-%!   ## Check documentation for properties
-%!   s = help ('cdef_help1.prop1');
-%!   assert (regexp (s, 'prop1: property help text ABOVE property'));
-%!
-%!   s = help ('cdef_help1.prop2');
-%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));
-%!
-%! unwind_protect_cleanup
-%!   rmpath ('cdefdir');
-%! end_unwind_protect
-
-%!test <*65220>
-%! unwind_protect
-%!   addpath ('cdefdir');
-%! 
-%!   ## Check methods first (bug was disguised if class checked first)
-%!   s = help ('cdef_help2.meth1');
-%!   assert (regexp (s, 'meth1: method help text ABOVE function'));
-%!
-%!   s = help ('cdef_help2.meth2');
-%!   assert (regexp (s, 'meth2: method help text BELOW function'));
-%!
-%!   s = help ('cdef_help2.meth3');
-%!   assert (regexp (s, 'meth3: method help text ABOVE function'));
-%!
-%!   s = '';
-%!   try
-%!     s = help ('cdef_help2.meth4');
-%!   catch
-%!     assert (regexp (lasterr (), "'cdef_help2.meth4' is not documented"));
-%!   end_try_catch
-%!   if (! isempty (s))
-%!     error ("Impossible state: Help text found for 'cdef_help2.meth4'");
-%!   endif
-%!
-%!   ## Check documentation for entire class
-%!   s = help ('cdef_help2');
-%!   assert (regexp (s, 'class cdef_help2 : class help text BELOW classdef'));
-%!   
-%!   ## Check documentation for constructor
-%!   s = help ('cdef_help2.cdef_help2');
-%!   assert (regexp (s, 'cdef_help2: constructor help text ABOVE function'));
-%!   
-%!   ## Check documentation for properties
-%!   s = help ('cdef_help2.prop1');
-%!   assert (regexp (s, 'prop1: property help text ABOVE property'));
-%!
-%!   s = help ('cdef_help2.prop2');
-%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));
-%!
-%! unwind_protect_cleanup
-%!   rmpath ('cdefdir');
-%! end_unwind_protect
--- a/test/bug-65220/cdefdir/cdef_help1.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%
-%% Copyright (C) 2024 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/>.
-%%
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-% class cdef_help1 : class help text ABOVE classdef keyword.
-%
-% Type 'help cdef_help1'
-
-classdef cdef_help1
-  % -*- texinfo -*-
-  % class cdef_help1 : class help text BELOW classdef keyword.
-  %
-  % Type 'help cdef_help1'
-
-  properties
-    % prop1: property help text ABOVE property name.
-    % Type "help cdef_help1.prop1"
-    prop1   % prop1: EOL-comment text.  Should not be displayed
-    prop2   % prop2: property help text in EOL-comment for property PROP2.  Type "help cdef_help1.prop2"
-  end
-
-  methods
-
-    % cdef_help1: constructor help text ABOVE function keyword
-    % Type 'help cdef_help1.cdef_help1'.
-    function obj = cdef_help1 (p1, p2)
-      % cdef_help1: constructor help text BELOW function keyword
-      % Type 'help cdef_help1.cdef_help1'.
-      if (nargin ~= 2)
-        obj.prop1 = 'default';
-        obj.prop2 = 42;
-      else
-        obj.prop1 = p1;
-        obj.prop2 = p2;
-      end
-    end
-
-    % meth1: method help text ABOVE function
-    % 
-    % Type 'help cdef_help1.meth1'.
-    function obj2 = meth1 (obj, n)
-      obj2 = n + obj;
-    end
-    
-    function obj2 = meth2 (obj, n)
-
-      % meth2: method help text BELOW function
-      % The blank line between function and comment is intentional.
-      % Type 'help cdef_help1.meth2'.
-      obj2 = n - obj;
-    end
-
-    % meth3: method help text ABOVE function
-    % Type 'help cdef_help1.meth3'.
-    % This should not be shown.
-    function obj3 = meth3 (obj, n)
-      % meth3: method help text BELOW function
-      % Type 'help cdef_help1.meth3'.
-      % This should be displayed.
-      obj3 = obj + n;
-    end
-
-    function obj4 = meth4 (obj, n)
-
-      obj4 = n - obj;
-      if (n)
-        % meth4: pure comment text.  This should *never* be displayed.
-        % Type 'help cdef_help1.meth4'.
-      end
-    end
-
-  end
-
-end
--- a/test/bug-65220/cdefdir/cdef_help2.m	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,92 +0,0 @@
-########################################################################
-##
-## Copyright (C) 2024 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/>.
-##
-########################################################################
-
-classdef cdef_help2
-  # -*- texinfo -*-
-  # class cdef_help2 : class help text BELOW classdef keyword.
-  #
-  # Type 'help cdef_help2'
-
-  properties
-    # prop1: property help text ABOVE property name.
-    # Type "help cdef_help2.prop1"
-    prop1   # prop1: EOL-comment text.  Should not be displayed
-    prop2   # prop2: property help text in EOL-comment for property PROP2.  Type "help cdef_help2.prop2"
-  end
-
-  methods
-
-    # cdef_help2: constructor help text ABOVE function keyword
-    # Type 'help cdef_help2.cdef_help2'.
-    # This should be shown because Octave comment character '#' is used.
-    function obj = cdef_help2 (p1, p2)
-      # cdef_help2: constructor help text BELOW function keyword
-      # Type 'help cdef_help2.cdef_help2'.
-      if (nargin ~= 2)
-        obj.prop1 = 'default';
-        obj.prop2 = 42;
-      else
-        obj.prop1 = p1;
-        obj.prop2 = p2;
-      end
-    end
-
-    # meth1: method help text ABOVE function
-    # 
-    # Type 'help cdef_help2.meth1'.
-    function obj2 = meth1 (obj, n)
-      obj2 = n + obj;
-    end
-    
-    function obj2 = meth2 (obj, n)
-
-      # meth2: method help text BELOW function
-      # The blank line between function and comment is intentional.
-      # Type 'help cdef_help2.meth2'.
-      obj2 = n - obj;
-    end
-
-    # meth3: method help text ABOVE function
-    # Type 'help cdef_help2.meth3'.
-    # This should be shown because Octave comment character '#' is used.
-    function obj3 = meth3 (obj, n)
-      # meth3: method help text BELOW function
-      # Type 'help cdef_help2.meth3'.
-      # This should NOT be displayed.
-      obj3 = obj + n;
-    end
-
-    function obj4 = meth4 (obj, n)
-
-      obj4 = n - obj;
-      if (n)
-        # meth4: pure comment text.  This should *never* be displayed.
-        # Type 'help cdef_help2.meth4'.
-      end
-    end
-
-  end
-
-end
--- a/test/bug-65220/module.mk	Sat Apr 06 14:43:10 2024 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-bug_65220_TEST_FILES = \
-  %reldir%/bug-65220.tst \
-  %reldir%/cdefdir/cdef_help1.m \
-  %reldir%/cdefdir/cdef_help2.m
-
-TEST_FILES += $(bug_65220_TEST_FILES)
--- a/test/classdef/classdef.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/classdef/classdef.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -80,7 +80,7 @@
 %! obj = obj.move_element_to_end (2);
 %! assert (isequal (obj.element, [1 3 2]));
 
-%!error <parse error> plist_t1
+%!error <syntax error> plist_t1
 %!assert (strcmp (class (plist_t2), 'plist_t2'))
 %!assert (strcmp (class (plist_t3), 'plist_t3'))
 
--- a/test/for.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/for.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -130,15 +130,15 @@
 %! __printf_assert__ ("\n");
 %! assert (__prog_output_assert__ ("1234"));
 
-%!test <*50893>
+%!test <*55622>
 %! cnt = 0;
 %! for k = zeros (0,3)
 %!   cnt++;
 %! endfor
-%! assert (cnt, 0);
-%! assert (k, zeros (0,3));
+%! assert (cnt, 3);
+%! assert (k, zeros (0,1));
 
-%!test <*50893>
+%!test <*55622>
 %! cnt = 0;
 %! for k = zeros (3,0)
 %!   cnt++;
@@ -159,8 +159,24 @@
 %! for k = cell (0,3)
 %!   cnt++;
 %! endfor
+%! assert (cnt, 3);
+%! assert (k, cell (0,1));
+
+%!test <*55622>
+%! cnt = 0;
+%! for k = zeros (1,2,3);
+%!   cnt++;
+%! endfor
+%! assert (cnt, 6);
+%! assert (k, 0);
+
+%!test <*55622>
+%! cnt = 0;
+%! for k = zeros (1,2,0);
+%!   cnt++;
+%! endfor
 %! assert (cnt, 0);
-%! assert (k, cell (0,3));
+%! assert (k, zeros (1,0));
 
 %!test <*45143>
 %! warning ("on", "Octave:infinite-loop", "local");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/cdefdir/cdef_help1.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,95 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%
+%% Copyright (C) 2024 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/>.
+%%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% class cdef_help1 : class help text ABOVE classdef keyword.
+%
+% Type 'help cdef_help1'
+
+classdef cdef_help1
+  % -*- texinfo -*-
+  % class cdef_help1 : class help text BELOW classdef keyword.
+  %
+  % Type 'help cdef_help1'
+
+  properties
+    % prop1: property help text ABOVE property name.
+    % Type "help cdef_help1.prop1"
+    prop1   % prop1: EOL-comment text.  Should not be displayed
+    prop2   % prop2: property help text in EOL-comment for property PROP2.  Type "help cdef_help1.prop2"
+  end
+
+  methods
+
+    % cdef_help1: constructor help text ABOVE function keyword
+    % Type 'help cdef_help1.cdef_help1'.
+    function obj = cdef_help1 (p1, p2)
+      % cdef_help1: constructor help text BELOW function keyword
+      % Type 'help cdef_help1.cdef_help1'.
+      if (nargin ~= 2)
+        obj.prop1 = 'default';
+        obj.prop2 = 42;
+      else
+        obj.prop1 = p1;
+        obj.prop2 = p2;
+      end
+    end
+
+    % meth1: method help text ABOVE function
+    %
+    % Type 'help cdef_help1.meth1'.
+    function obj2 = meth1 (obj, n)
+      obj2 = n + obj;
+    end
+
+    function obj2 = meth2 (obj, n)
+
+      % meth2: method help text BELOW function
+      % The blank line between function and comment is intentional.
+      % Type 'help cdef_help1.meth2'.
+      obj2 = n - obj;
+    end
+
+    % meth3: method help text ABOVE function
+    % Type 'help cdef_help1.meth3'.
+    % This should not be shown.
+    function obj3 = meth3 (obj, n)
+      % meth3: method help text BELOW function
+      % Type 'help cdef_help1.meth3'.
+      % This should be displayed.
+      obj3 = obj + n;
+    end
+
+    function obj4 = meth4 (obj, n)
+
+      obj4 = n - obj;
+      if (n)
+        % meth4: pure comment text.  This should *never* be displayed.
+        % Type 'help cdef_help1.meth4'.
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/cdefdir/cdef_help2.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,92 @@
+########################################################################
+##
+## Copyright (C) 2024 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/>.
+##
+########################################################################
+
+classdef cdef_help2
+  # -*- texinfo -*-
+  # class cdef_help2 : class help text BELOW classdef keyword.
+  #
+  # Type 'help cdef_help2'
+
+  properties
+    # prop1: property help text ABOVE property name.
+    # Type "help cdef_help2.prop1"
+    prop1   # prop1: EOL-comment text.  Should not be displayed
+    prop2   # prop2: property help text in EOL-comment for property PROP2.  Type "help cdef_help2.prop2"
+  end
+
+  methods
+
+    # cdef_help2: constructor help text ABOVE function keyword
+    # Type 'help cdef_help2.cdef_help2'.
+    # This should be shown because Octave comment character '#' is used.
+    function obj = cdef_help2 (p1, p2)
+      # cdef_help2: constructor help text BELOW function keyword
+      # Type 'help cdef_help2.cdef_help2'.
+      if (nargin ~= 2)
+        obj.prop1 = 'default';
+        obj.prop2 = 42;
+      else
+        obj.prop1 = p1;
+        obj.prop2 = p2;
+      end
+    end
+
+    # meth1: method help text ABOVE function
+    #
+    # Type 'help cdef_help2.meth1'.
+    function obj2 = meth1 (obj, n)
+      obj2 = n + obj;
+    end
+
+    function obj2 = meth2 (obj, n)
+
+      # meth2: method help text BELOW function
+      # The blank line between function and comment is intentional.
+      # Type 'help cdef_help2.meth2'.
+      obj2 = n - obj;
+    end
+
+    # meth3: method help text ABOVE function
+    # Type 'help cdef_help2.meth3'.
+    # This should be shown because Octave comment character '#' is used.
+    function obj3 = meth3 (obj, n)
+      # meth3: method help text BELOW function
+      # Type 'help cdef_help2.meth3'.
+      # This should NOT be displayed.
+      obj3 = obj + n;
+    end
+
+    function obj4 = meth4 (obj, n)
+
+      obj4 = n - obj;
+      if (n)
+        # meth4: pure comment text.  This should *never* be displayed.
+        # Type 'help cdef_help2.meth4'.
+      end
+    end
+
+  end
+
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/cdefdir/cdef_help3.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,38 @@
+########################################################################
+##
+## Copyright (C) 2024 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/>.
+##
+########################################################################
+
+classdef cdef_help3
+  properties
+    prop1 = 13;
+    prop2 = 42;
+  end
+
+  methods
+    function obj = cdef_help3 (p1, p2)
+      obj.prop1 = p1;
+      obj.prop2 = p2;
+    end
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/cdefdir/cdef_help4.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,31 @@
+########################################################################
+##
+## Copyright (C) 2024 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/>.
+##
+########################################################################
+
+classdef cdef_help4
+  properties
+    prop1 = 13;
+    prop2 = 42;
+  end
+end
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/help.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,254 @@
+########################################################################
+##
+## Copyright (C) 2024 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/>.
+##
+########################################################################
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check methods first (bug was disguised if class checked first)
+%!   s = help ('cdef_help1.meth1');
+%!   assert (regexp (s, 'meth1: method help text ABOVE function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help1.meth2');
+%!   assert (regexp (s, 'meth2: method help text BELOW function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help1.meth3');
+%!   assert (regexp (s, 'meth3: method help text BELOW function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65258>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help1.meth4');
+%!   assert (regexp (s, 'undocumented method: obj4 = meth4 \(obj, n\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for entire class
+%!   s = help ('cdef_help1');
+%!   assert (regexp (s, 'class cdef_help1 : class help text ABOVE classdef'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for constructor
+%!   s = help ('cdef_help1.cdef_help1');
+%!   assert (regexp (s, 'cdef_help1: constructor help text BELOW function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for properties
+%!   s = help ('cdef_help1.prop1');
+%!   assert (regexp (s, 'prop1: property help text ABOVE property'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help1.prop2');
+%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check methods first (bug was disguised if class checked first)
+%!   s = help ('cdef_help2.meth1');
+%!   assert (regexp (s, 'meth1: method help text ABOVE function'));
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help2.meth2');
+%!   assert (regexp (s, 'meth2: method help text BELOW function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help2.meth3');
+%!   assert (regexp (s, 'meth3: method help text ABOVE function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help2.meth4');
+%!   assert (regexp (s, 'undocumented method: obj4 = meth4 \(obj, n\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for entire class
+%!   s = help ('cdef_help2');
+%!   assert (regexp (s, 'class cdef_help2 : class help text BELOW classdef'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for constructor
+%!   s = help ('cdef_help2.cdef_help2');
+%!   assert (regexp (s, 'cdef_help2: constructor help text ABOVE function'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   ## Check documentation for properties
+%!   s = help ('cdef_help2.prop1');
+%!   assert (regexp (s, 'prop1: property help text ABOVE property'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65220>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help2.prop2');
+%!   assert (regexp (s, 'prop2: property help text in EOL-comment'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65258>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help3');
+%!   assert (regexp (s, 'undocumented constructor: obj = cdef_help3 \(p1, p2\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65258>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help3.cdef_help3');
+%!   assert (regexp (s, 'undocumented constructor: obj = cdef_help3 \(p1, p2\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65258>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help4');
+%!   assert (regexp (s, 'default constructor: obj = cdef_help4 \(\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!test <*65258>
+%! unwind_protect
+%!   addpath ('cdefdir');
+%!
+%!   s = help ('cdef_help4.cdef_help4');
+%!   assert (regexp (s, 'default constructor: obj = cdef_help4 \(\)'));
+%!
+%! unwind_protect_cleanup
+%!   rmpath ('cdefdir');
+%! end_unwind_protect
+
+%!assert <*65258> (regexp (help ('undoc_fcn'), 'undocumented function: \[x, y, z\] = undoc_fcn \(a, b, ~, c = 3\)'))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/module.mk	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,9 @@
+help_TEST_FILES = \
+  %reldir%/help.tst \
+  %reldir%/undoc_fcn.m \
+  %reldir%/cdefdir/cdef_help1.m \
+  %reldir%/cdefdir/cdef_help2.m \
+  %reldir%/cdefdir/cdef_help3.m \
+  %reldir%/cdefdir/cdef_help4.m
+
+TEST_FILES += $(help_TEST_FILES)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/help/undoc_fcn.m	Fri Apr 12 15:10:26 2024 +0200
@@ -0,0 +1,5 @@
+function [x, y, z] = undoc_fcn (a, b, ~, c = 3)
+  x = a;
+  y = b;
+  z = c;
+end
--- a/test/io.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/io.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -671,8 +671,7 @@
 %! [val, count, msg, pos] = sscanf ('1 2 ', '%f');
 %! assert (val, [1; 2]);
 %! assert (count, 2);
-%! ## FIXME: The message should be empty, but is not.
-%! # assert (msg, '');
+%! assert (msg, '');
 %! assert (pos, 5);
 
 ## Test newline at end of input string
@@ -680,8 +679,7 @@
 %! [val, count, msg, pos] = sscanf ("1 2\n", '%f');
 %! assert (val, [1; 2]);
 %! assert (count, 2);
-%! ## FIXME: The message should be empty, but is not.
-%! # assert (msg, '');
+%! assert (msg, '');
 %! assert (pos, 5);
 
 %!test
--- a/test/json/jsonencode_BIST.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/json/jsonencode_BIST.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -15,6 +15,10 @@
 %! assert (isequal (jsonencode (logical (1)), 'true'));
 %! assert (isequal (jsonencode (logical (0)), 'false'));
 %! assert (isequal (jsonencode (50.025), '50.025'));
+%! %% FIXME: Uncomment when bug #64960 is fixed
+%! %% assert (isequal (jsonencode (single (50.025)), '50.025'));
+%! assert (isequal (jsonencode (uint64 (1e6)), '1000000'));
+%! assert (isequal (jsonencode (int64 (-1e6)), '-1000000'));
 %! assert (isequal (jsonencode (NaN), 'null'));
 %! assert (isequal (jsonencode (NA), 'null'));    % Octave-only test
 %! assert (isequal (jsonencode (Inf), 'null'));
@@ -110,6 +114,8 @@
 %!testif HAVE_RAPIDJSON
 %! assert (isequal (jsonencode ([]), '[]'));
 %! assert (isequal (jsonencode ([1, 2, 3, 4]), '[1,2,3,4]'));
+%! % Matlab encodes flints with values above 1e6-1 in scientific notation.  Octave writes integers.
+%! assert (isequal (jsonencode ([1.23e6, 2]), '[1230000,2]'));
 %! assert (isequal (jsonencode ([true; false; true]), '[true,false,true]'));
 
 %% Test arrays
--- a/test/leftdiv.tst	Sat Apr 06 14:43:10 2024 +0200
+++ b/test/leftdiv.tst	Fri Apr 12 15:10:26 2024 +0200
@@ -30,6 +30,72 @@
 %#!assert (0 \ i, Inf)
 %#!assert (0 \ single (i), single (Inf))
 
+################################################################################
+## Series of tests for memory leaks in function
+## sparse_qr<SPARSE_T>min2norm_solve<RHS_T, RET_T> (A, b)
+## in sparse-qr.cc.
+################################################################################
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=real full>, <RET=Matrix>, (real sparse, real full)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);
+%! x0 = mldivide (A, ones (m,1));
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=real sparse>, <RET=SparseMatrix>, (real sparse, real sparse)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);
+%! b = sparse (ones (m,1));
+%! x0 = mldivide (A, b);
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=complex full>, <RET=ComplexMatrix>, (real sparse, complex full)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);
+%! b = ones (m,1) + i;
+%! x0 = mldivide (A, b);
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (real sparse, complex sparse)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);
+%! b = sparse (ones (m, 1) + i);
+%! x0 = A \ b;
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (real sparse, complex sparse)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1), -ones(mn,1)],[-1,0,1], m, n);
+%! b = sparse (ones (m, 1) + i);
+%! x0 = A \ b;
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=complex full>, <RET=ComplexMatrix>, (complex sparse, complex full)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);
+%! b = ones (m, 1) + i;
+%! x0 = A \ b;
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=real full>, <RET=ComplexMatrix>, (complex sparse, real full)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);
+%! b = ones (m, 1);
+%! x0 = A \ b;
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=complex sparse>, <RET=SparseComplexMatrix>, (complex sparse, complex sparse)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);
+%! b = sparse (ones (m, 1) + i);
+%! x0 = A \ b;
+
+%!testif HAVE_SPQR, HAVE_CHOLMOD
+%! # <RHS=real sparse>, <RET=SparseComplexMatrix>, (complex sparse, real sparse)
+%! m = 11; n = 10; mn = max (m ,n);
+%! A = spdiags ([ones(mn,1), 10*ones(mn,1) + i, -ones(mn,1)],[-1,0,1], m, n);
+%! b = sparse (ones (m, 1));
+
 %!warning <matrix singular to machine precision>
 %! warning ('on', 'Octave:singular-matrix', 'local');
 %! assert ([Inf, 0; 0, 0] \ [1; 1], zeros (2,1));