# HG changeset patch # User John W. Eaton # Date 1670357836 18000 # Node ID bd9da634f00d44e43c9725f1f770cf039447652d # Parent 91680d96c860f33873d39586ef25718e054c5ca2# Parent 9089bd969b370f8613112bc58a0b32d6faa7fd79 maint: Merge stable to default. diff -r 9089bd969b37 -r bd9da634f00d .github/workflows/make.yaml --- a/.github/workflows/make.yaml Tue Dec 06 14:23:21 2022 -0500 +++ b/.github/workflows/make.yaml Tue Dec 06 15:17:16 2022 -0500 @@ -85,7 +85,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default - name: configure ccache env: @@ -239,7 +239,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.compiler }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.compiler }}:refs/heads/default - name: configure ccache # The cache doesn't seem to compress well on macOS. Is it already compressed? @@ -468,7 +468,7 @@ key: ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:${{ matrix.msystem }}:${{ github.ref }} - ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/stable + ccache:${{ matrix.os }}:${{ matrix.msystem }}:refs/heads/default - name: configure ccache # Limit the maximum size and switch on compression to avoid exceeding the total disk or cache quota. @@ -707,7 +707,7 @@ key: ccache:${{ matrix.os }}:cygwin:${{ github.ref }}:${{ steps.ccache_cache_timestamp.outputs.timestamp }}:${{ github.sha }} restore-keys: | ccache:${{ matrix.os }}:cygwin:${{ github.ref }} - ccache:${{ matrix.os }}:cygwin:refs/heads/stable + ccache:${{ matrix.os }}:cygwin:refs/heads/default - name: configure ccache run: | diff -r 9089bd969b37 -r bd9da634f00d configure.ac --- a/configure.ac Tue Dec 06 14:23:21 2022 -0500 +++ b/configure.ac Tue Dec 06 15:17:16 2022 -0500 @@ -27,7 +27,7 @@ ### Initialize Autoconf AC_PREREQ([2.65]) -AC_INIT([GNU Octave], [8.0.1], [https://octave.org/bugs.html], [octave], +AC_INIT([GNU Octave], [9.0.0], [https://octave.org/bugs.html], [octave], [https://www.gnu.org/software/octave/]) ### Declare version numbers @@ -39,9 +39,9 @@ ## explains how to update these numbers for release and development ## versions. -OCTAVE_MAJOR_VERSION=8 +OCTAVE_MAJOR_VERSION=9 OCTAVE_MINOR_VERSION=0 -OCTAVE_PATCH_VERSION=1 +OCTAVE_PATCH_VERSION=0 dnl PACKAGE_VERSION is set by the AC_INIT VERSION argument. OCTAVE_VERSION="$PACKAGE_VERSION" diff -r 9089bd969b37 -r bd9da634f00d doc/interpreter/contributors.in --- a/doc/interpreter/contributors.in Tue Dec 06 14:23:21 2022 -0500 +++ b/doc/interpreter/contributors.in Tue Dec 06 15:17:16 2022 -0500 @@ -101,6 +101,7 @@ Massimiliano Fasi Stephen Fegan Ramon Garcia Fernandez +Kasper H. Filtenborg Torsten Finke David Finkel Guillaume Flandin diff -r 9089bd969b37 -r bd9da634f00d doc/interpreter/linalg.txi --- a/doc/interpreter/linalg.txi Tue Dec 06 14:23:21 2022 -0500 +++ b/doc/interpreter/linalg.txi Tue Dec 06 15:17:16 2022 -0500 @@ -211,6 +211,8 @@ @DOCSTRING(kron) +@DOCSTRING(tensorprod) + @DOCSTRING(blkmm) @DOCSTRING(sylvester) diff -r 9089bd969b37 -r bd9da634f00d doc/liboctave/range.texi --- a/doc/liboctave/range.texi Tue Dec 06 14:23:21 2022 -0500 +++ b/doc/liboctave/range.texi Tue Dec 06 15:17:16 2022 -0500 @@ -20,35 +20,4 @@ @chapter Ranges @cindex ranges -@deftypefn {} {} Range (void) -@deftypefnx {} {} Range (const Range &@var{r}) -@deftypefnx {} {} Range (double @var{b}, double @var{l}) -@deftypefnx {} {} Range (double @var{b}, double @var{l}, double @var{i}) -@end deftypefn - -@deftypefn {} double base (void) const -@deftypefnx {} double limit (void) const -@deftypefnx {} double inc (void) const -@end deftypefn - -@deftypefn {} void set_base (double @var{b}) -@deftypefnx {} void set_limit (double @var{l}) -@deftypefnx {} void set_inc (double @var{i}) -@end deftypefn - -@deftypefn {} int nelem (void) const -@end deftypefn - -@deftypefn {} double min (void) const -@deftypefnx {} double max (void) const -@end deftypefn - -@deftypefn {} void sort (void) -@end deftypefn - -@deftypefn {} {ostream&} {operator <<} (ostream &@var{os}, const Range &@var{r}) -@deftypefnx {} {istream&} {operator >>} (istream &@var{is}, Range &@var{r}) -@end deftypefn - -@deftypefn {} void print_range (void) -@end deftypefn +FIXME: The @code{Range} class is obsolete. diff -r 9089bd969b37 -r bd9da634f00d etc/NEWS.8.md diff -r 9089bd969b37 -r bd9da634f00d etc/NEWS.9.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/etc/NEWS.9.md Tue Dec 06 15:17:16 2022 -0500 @@ -0,0 +1,93 @@ +Summary of important user-visible changes for version 9 (yyyy-mm-dd): +--------------------------------------------------------------------- + +### General improvements + +- `oruntests`: The current directory now changes to the directory +containing the files with the tests for the duration of the test. This +aligns the behavior of this function with Octave's test suite. This also +means that the file encoding specified in the `.oct-config` file for the +respective directory is taken into account for the tests. + +### Graphical User Interface + +### Graphics backend + +### Matlab compatibility + +### Alphabetical list of new functions added in Octave 9 + +* `tensorprod` + +### Deprecated functions, properties, and operators + +The following functions and properties have been deprecated in Octave 9 +and will be removed from Octave 11 (or whatever version is the second +major release after 9): + +- Functions + + Function | Replacement + -----------------------|------------------ + +- Properties + + The following property names are discouraged, but there is no fixed + date for their removal. + + Object | Property | Replacement + -----------------|-------------|------------ + +The following features were deprecated in Octave 7 and have been removed +from Octave 9. + +- Functions + + Function | Replacement + ---------------------------|------------------ + disable_diagonal_matrix | optimize_diagonal_matrix + disable_permutation_matrix | optimize_permutation_matrix + disable_range | optimize_range + +- Operators + + Operator | Replacement + ---------|------------ + .+ | + + .+= | += + .- | - + .-= | -= + ** | ^ + **= | ^= + .** | .^ + .**= | .^= + +- Interpreter + + * The use of `'...'` for line continuations *inside* double-quoted + strings has been removed. Use `'\'` for line continuations inside strings + instead. + + * The use of `'\'` as a line continuation *outside* of double-quoted + strings has been removed. Use `'...'` for line continuations instead. + + * Support for trailing whitespace after a `'\'` line continuation has been + removed. Delete unnecessary trailing whitespace. + +- For plot functions, the use of numbers to select line colors in + shorthand formats was an undocumented feature was removed from Octave 9. + +- The environment variable used by `mkoctfile` for linker flags is now + `LDFLAGS` rather than `LFLAGS`. `LFLAGS` was deprecated in Octave 6 + and has been removed. + +### Old release news + +- [Octave 8.x](etc/NEWS.8) +- [Octave 7.x](etc/NEWS.7) +- [Octave 6.x](etc/NEWS.6) +- [Octave 5.x](etc/NEWS.5) +- [Octave 4.x](etc/NEWS.4) +- [Octave 3.x](etc/NEWS.3) +- [Octave 2.x](etc/NEWS.2) +- [Octave 1.x](etc/NEWS.1) diff -r 9089bd969b37 -r bd9da634f00d etc/module.mk --- a/etc/module.mk Tue Dec 06 14:23:21 2022 -0500 +++ b/etc/module.mk Tue Dec 06 15:17:16 2022 -0500 @@ -13,6 +13,7 @@ %reldir%/NEWS.6.md \ %reldir%/NEWS.7.md \ %reldir%/NEWS.8.md \ + %reldir%/NEWS.9.md \ %reldir%/gdbinit %canon_reldir%_EXTRA_DIST += \ diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/BaseControl.cc --- a/libgui/graphics/BaseControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/BaseControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -116,10 +116,9 @@ w->setPalette (p); } - BaseControl::BaseControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + BaseControl::BaseControl (octave::interpreter& interp, const graphics_object& go, QWidget *w) - : Object (oct_qobj, interp, go, w), m_normalizedFont (false), + : Object (interp, go, w), m_normalizedFont (false), m_keyPressHandlerDefined (false) { qObject ()->setObjectName ("UIControl"); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/BaseControl.h --- a/libgui/graphics/BaseControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/BaseControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,13 +33,12 @@ namespace octave { - class base_qobject; class interpreter; class BaseControl : public Object { public: - BaseControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + BaseControl (octave::interpreter& interp, const graphics_object& go, QWidget *w); ~BaseControl (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ButtonControl.cc --- a/libgui/graphics/ButtonControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ButtonControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -40,11 +40,10 @@ namespace octave { - ButtonControl::ButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ButtonControl::ButtonControl (octave::interpreter& interp, const graphics_object& go, QAbstractButton *btn) - : BaseControl (oct_qobj, interp, go, btn), m_blockCallback (false) + : BaseControl (interp, go, btn), m_blockCallback (false) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ButtonControl.h --- a/libgui/graphics/ButtonControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ButtonControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ namespace octave { - class base_qobject; class interpreter; class ButtonControl : public BaseControl @@ -40,7 +39,7 @@ Q_OBJECT public: - ButtonControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ButtonControl (octave::interpreter& interp, const graphics_object& go, QAbstractButton *btn); ~ButtonControl (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ButtonGroup.cc --- a/libgui/graphics/ButtonGroup.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ButtonGroup.cc Tue Dec 06 15:17:16 2022 -0500 @@ -45,7 +45,6 @@ #include "QtHandlesUtils.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" #include "octave-qtutils.h" #include "interpreter.h" @@ -100,8 +99,7 @@ } ButtonGroup * - ButtonGroup::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + ButtonGroup::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -112,7 +110,7 @@ if (container) { QFrame *frame = new QFrame (container); - return new ButtonGroup (oct_qobj, interp, go, + return new ButtonGroup (interp, go, new QButtonGroup (frame), frame); } } @@ -120,11 +118,10 @@ return nullptr; } - ButtonGroup::ButtonGroup (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ButtonGroup::ButtonGroup (octave::interpreter& interp, const graphics_object& go, QButtonGroup *buttongroup, QFrame *frame) - : Object (oct_qobj, interp, go, frame), m_hiddenbutton (nullptr), + : Object (interp, go, frame), m_hiddenbutton (nullptr), m_container (nullptr), m_title (nullptr), m_blockUpdates (false) { uibuttongroup::properties& pp = properties (); @@ -144,7 +141,7 @@ m_hiddenbutton->hide (); m_buttongroup->addButton (m_hiddenbutton); - m_container = new Container (frame, oct_qobj, interp); + m_container = new Container (frame, interp); m_container->canvas (m_handle); connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ButtonGroup.h --- a/libgui/graphics/ButtonGroup.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ButtonGroup.h Tue Dec 06 15:17:16 2022 -0500 @@ -36,7 +36,6 @@ namespace octave { - class base_qobject; class interpreter; class Container; @@ -46,7 +45,7 @@ Q_OBJECT public: - ButtonGroup (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ButtonGroup (octave::interpreter& interp, const graphics_object& go, QButtonGroup *buttongroup, QFrame *frame); ~ButtonGroup (void); @@ -56,7 +55,7 @@ bool eventFilter (QObject *watched, QEvent *event); static ButtonGroup * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); void addButton (QAbstractButton *btn); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Canvas.cc --- a/libgui/graphics/Canvas.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Canvas.cc Tue Dec 06 15:17:16 2022 -0500 @@ -43,7 +43,7 @@ #include "qt-graphics-toolkit.h" #include "annotation-dialog.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "qt-interpreter-events.h" #include "builtin-defun-decls.h" @@ -77,9 +77,9 @@ QCursor Canvas::make_cursor (const QString& name, int hot_x, int hot_y) { - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - QIcon icon = rmgr.icon (name); + QIcon icon = settings.icon (name); return QCursor (icon.pixmap (22, 22), hot_x, hot_y); } @@ -869,7 +869,7 @@ octave_value_list props = ovl ("textbox", bb); - annotation_dialog anno_dlg (m_octave_qobj, w, props); + annotation_dialog anno_dlg (w, props); if (anno_dlg.exec () == QDialog::Accepted) { @@ -1086,12 +1086,12 @@ } Canvas * - Canvas::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Canvas::create (octave::interpreter& interp, const graphics_handle& handle, QWidget *parent, const std::string& /* name */) { // Only OpenGL - return new GLCanvas (oct_qobj, interp, handle, parent); + return new GLCanvas (interp, handle, parent); } } diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Canvas.h --- a/libgui/graphics/Canvas.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Canvas.h Tue Dec 06 15:17:16 2022 -0500 @@ -43,7 +43,6 @@ namespace octave { - class base_qobject; class interpreter; class Canvas : public QObject @@ -78,9 +77,8 @@ virtual QWidget * qWidget (void) = 0; static Canvas * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle, QWidget *parent, - const std::string& name); + create (octave::interpreter& interp, const graphics_handle& handle, + QWidget *parent, const std::string& name); virtual uint8NDArray getPixels (void) { return do_getPixels (m_handle); }; @@ -114,10 +112,8 @@ const graphics_handle& handle) = 0; protected: - Canvas (octave::base_qobject& oct_qobj, octave::interpreter& interp, - const graphics_handle& handle) - : m_octave_qobj (oct_qobj), - m_interpreter (interp), + Canvas (octave::interpreter& interp, const graphics_handle& handle) + : m_interpreter (interp), m_handle (handle), m_redrawBlocked (false), m_mouseMode (NoMode), @@ -149,7 +145,7 @@ std::vector omit = std::vector ()); protected: - octave::base_qobject& m_octave_qobj; + octave::interpreter& m_interpreter; private: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/CheckBoxControl.cc --- a/libgui/graphics/CheckBoxControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/CheckBoxControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -32,14 +32,11 @@ #include "CheckBoxControl.h" #include "Container.h" -#include "octave-qobject.h" - namespace octave { CheckBoxControl * - CheckBoxControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + CheckBoxControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -49,17 +46,16 @@ Container *container = parent->innerContainer (); if (container) - return new CheckBoxControl (oct_qobj, interp, go, + return new CheckBoxControl (interp, go, new QCheckBox (container)); } return nullptr; } - CheckBoxControl::CheckBoxControl (octave::base_qobject& oct_obj, - octave::interpreter& interp, + CheckBoxControl::CheckBoxControl (octave::interpreter& interp, const graphics_object& go, QCheckBox *box) - : ButtonControl (oct_obj, interp, go, box) + : ButtonControl (interp, go, box) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/CheckBoxControl.h --- a/libgui/graphics/CheckBoxControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/CheckBoxControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,19 +32,17 @@ namespace octave { - class base_qobject; class interpreter; class CheckBoxControl : public ButtonControl { public: - CheckBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, + CheckBoxControl (octave::interpreter& interp, const graphics_object& go, QCheckBox *box); ~CheckBoxControl (void); static CheckBoxControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Container.cc --- a/libgui/graphics/Container.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Container.cc Tue Dec 06 15:17:16 2022 -0500 @@ -41,10 +41,8 @@ namespace octave { - Container::Container (QWidget *xparent, octave::base_qobject& oct_qobj, - octave::interpreter& interp) - : ContainerBase (xparent), m_octave_qobj (oct_qobj), - m_interpreter (interp), m_canvas (nullptr) + Container::Container (QWidget *xparent, octave::interpreter& interp) + : ContainerBase (xparent), m_interpreter (interp), m_canvas (nullptr) { setFocusPolicy (Qt::ClickFocus); } @@ -67,7 +65,7 @@ { graphics_object fig = go.get_ancestor ("figure"); - m_canvas = Canvas::create (m_octave_qobj, m_interpreter, gh, this, + m_canvas = Canvas::create (m_interpreter, gh, this, fig.get ("renderer").string_value ()); connect (m_canvas, QOverload::of (&Canvas::interpreter_event), diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Container.h --- a/libgui/graphics/Container.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Container.h Tue Dec 06 15:17:16 2022 -0500 @@ -35,11 +35,6 @@ namespace octave { - class base_qobject; -} - -namespace octave -{ DECLARE_GENERICEVENTNOTIFY_SENDER(ContainerBase, QWidget); @@ -50,8 +45,7 @@ Q_OBJECT public: - Container (QWidget *parent, octave::base_qobject& oct_qobj, - octave::interpreter& interp); + Container (QWidget *parent, octave::interpreter& interp); ~Container (void); Canvas * canvas (const graphics_handle& handle, bool create = true); @@ -81,7 +75,6 @@ void resizeEvent (QResizeEvent *event); private: - octave::base_qobject& m_octave_qobj; octave::interpreter& m_interpreter; Canvas *m_canvas; }; diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ContextMenu.cc --- a/libgui/graphics/ContextMenu.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ContextMenu.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,16 +33,13 @@ #include "QtHandlesUtils.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" - #include "interpreter.h" namespace octave { ContextMenu * - ContextMenu::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + ContextMenu::create (octave::interpreter& interp, const graphics_object& go) { Object *xparent = parentObject (interp, go); @@ -50,16 +47,15 @@ { QWidget *w = xparent->qWidget (); - return new ContextMenu (oct_qobj, interp, go, new QMenu (w)); + return new ContextMenu (interp, go, new QMenu (w)); } return nullptr; } - ContextMenu::ContextMenu (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ContextMenu::ContextMenu (octave::interpreter& interp, const graphics_object& go, QMenu *xmenu) - : Object (oct_qobj, interp, go, xmenu) + : Object (interp, go, xmenu) { xmenu->setAutoFillBackground (true); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ContextMenu.h --- a/libgui/graphics/ContextMenu.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ContextMenu.h Tue Dec 06 15:17:16 2022 -0500 @@ -35,7 +35,6 @@ namespace octave { - class base_qobject; class interpreter; class ContextMenu : public Object, public MenuContainer @@ -43,12 +42,12 @@ Q_OBJECT public: - ContextMenu (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ContextMenu (octave::interpreter& interp, const graphics_object& go, QMenu *menu); ~ContextMenu (void); static ContextMenu * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); static void executeAt (octave::interpreter& interp, diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/EditControl.cc --- a/libgui/graphics/EditControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/EditControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -34,14 +34,11 @@ #include "TextEdit.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { EditControl * - EditControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + EditControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -54,10 +51,10 @@ uicontrol::properties& up = Utils::properties (go); if ((up.get_max () - up.get_min ()) > 1) - return new EditControl (oct_qobj, interp, go, + return new EditControl (interp, go, new TextEdit (container)); else - return new EditControl (oct_qobj, interp, go, + return new EditControl (interp, go, new QLineEdit (container)); } } @@ -65,10 +62,9 @@ return nullptr; } - EditControl::EditControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + EditControl::EditControl (octave::interpreter& interp, const graphics_object& go, QLineEdit *edit) - : BaseControl (oct_qobj, interp, go, edit), m_multiLine (false), + : BaseControl (interp, go, edit), m_multiLine (false), m_textChanged (false) { init (edit); @@ -101,10 +97,9 @@ this, &EditControl::returnPressed); } - EditControl::EditControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + EditControl::EditControl (octave::interpreter& interp, const graphics_object& go, TextEdit *edit) - : BaseControl (oct_qobj, interp, go, edit), m_multiLine (true), + : BaseControl (interp, go, edit), m_multiLine (true), m_textChanged (false) { init (edit); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/EditControl.h --- a/libgui/graphics/EditControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/EditControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ namespace octave { - class base_qobject; class interpreter; class TextEdit; @@ -43,16 +42,16 @@ Q_OBJECT public: - EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + EditControl (octave::interpreter& interp, const graphics_object& go, QLineEdit *edit); - EditControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + EditControl (octave::interpreter& interp, const graphics_object& go, TextEdit *edit); ~EditControl (void); static EditControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Figure.cc --- a/libgui/graphics/Figure.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Figure.cc Tue Dec 06 15:17:16 2022 -0500 @@ -110,19 +110,19 @@ } Figure * - Figure::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Figure::create (octave::interpreter& interp, const graphics_object& go) { - return new Figure (oct_qobj, interp, go, new FigureWindow ()); + return new Figure (interp, go, new FigureWindow ()); } - Figure::Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Figure::Figure (octave::interpreter& interp, const graphics_object& go, FigureWindow *win) - : Object (oct_qobj, interp, go, win), m_blockUpdates (false), + : Object (interp, go, win), m_blockUpdates (false), m_figureToolBar (nullptr), m_menuBar (nullptr), m_innerRect (), m_outerRect (), m_previousHeight (0), m_resizable (true) { - m_container = new Container (win, oct_qobj, interp); + m_container = new Container (win, interp); win->setCentralWidget (m_container); connect (m_container, QOverload::of (&Container::interpreter_event), diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Figure.h --- a/libgui/graphics/Figure.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Figure.h Tue Dec 06 15:17:16 2022 -0500 @@ -39,7 +39,6 @@ namespace octave { - class base_qobject; class interpreter; enum MouseMode @@ -68,12 +67,12 @@ friend class ToolBar; public: - Figure (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Figure (octave::interpreter& interp, const graphics_object& go, FigureWindow *win); ~Figure (void); static Figure * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); QString fileName (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/GLCanvas.cc --- a/libgui/graphics/GLCanvas.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/GLCanvas.cc Tue Dec 06 15:17:16 2022 -0500 @@ -50,11 +50,10 @@ # endif #endif - GLCanvas::GLCanvas (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + GLCanvas::GLCanvas (octave::interpreter& interp, const graphics_handle& gh, QWidget *xparent) : OCTAVE_QT_OPENGL_WIDGET (OCTAVE_QT_OPENGL_WIDGET_FORMAT_ARGS xparent), - Canvas (oct_qobj, interp, gh), m_glfcns (), m_renderer (m_glfcns) + Canvas (interp, gh), m_glfcns (), m_renderer (m_glfcns) { setFocusPolicy (Qt::ClickFocus); setFocus (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/GLCanvas.h --- a/libgui/graphics/GLCanvas.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/GLCanvas.h Tue Dec 06 15:17:16 2022 -0500 @@ -51,7 +51,6 @@ namespace octave { - class base_qobject; } namespace octave @@ -59,7 +58,7 @@ class GLCanvas : public OCTAVE_QT_OPENGL_WIDGET, public Canvas { public: - GLCanvas (octave::base_qobject& oct_qobj, octave::interpreter& interp, + GLCanvas (octave::interpreter& interp, const graphics_handle& handle, QWidget *parent); ~GLCanvas (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ListBoxControl.cc --- a/libgui/graphics/ListBoxControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ListBoxControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -35,8 +35,6 @@ #include "ListBoxControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { @@ -70,8 +68,7 @@ } ListBoxControl * - ListBoxControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ListBoxControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -81,17 +78,16 @@ Container *container = parent->innerContainer (); if (container) - return new ListBoxControl (oct_qobj, interp, go, + return new ListBoxControl (interp, go, new QListWidget (container)); } return nullptr; } - ListBoxControl::ListBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ListBoxControl::ListBoxControl (octave::interpreter& interp, const graphics_object& go, QListWidget *list) - : BaseControl (oct_qobj, interp, go, list), m_blockCallback (false), + : BaseControl (interp, go, list), m_blockCallback (false), m_selectionChanged (false) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ListBoxControl.h --- a/libgui/graphics/ListBoxControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ListBoxControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,7 +34,6 @@ namespace octave { - class base_qobject; class interpreter; class ListBoxControl : public BaseControl @@ -42,13 +41,12 @@ Q_OBJECT public: - ListBoxControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, + ListBoxControl (octave::interpreter& interp, const graphics_object& go, QListWidget *list); ~ListBoxControl (void); static ListBoxControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Menu.cc --- a/libgui/graphics/Menu.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Menu.cc Tue Dec 06 15:17:16 2022 -0500 @@ -36,8 +36,6 @@ #include "Menu.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { @@ -63,7 +61,7 @@ } Menu * - Menu::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Menu::create (octave::interpreter& interp, const graphics_object& go) { Object *parent_obj = parentObject (interp, go); @@ -73,16 +71,16 @@ QObject *qObj = parent_obj->qObject (); if (qObj) - return new Menu (oct_qobj, interp, go, new QAction (qObj), + return new Menu (interp, go, new QAction (qObj), parent_obj); } return nullptr; } - Menu::Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Menu::Menu (octave::interpreter& interp, const graphics_object& go, QAction *action, Object *xparent) - : Object (oct_qobj, interp, go, action), m_parent (nullptr), + : Object (interp, go, action), m_parent (nullptr), m_separator (nullptr) { uimenu::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Menu.h --- a/libgui/graphics/Menu.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Menu.h Tue Dec 06 15:17:16 2022 -0500 @@ -35,7 +35,6 @@ namespace octave { - class base_qobject; class interpreter; class Menu : public Object, public MenuContainer @@ -43,12 +42,12 @@ Q_OBJECT public: - Menu (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Menu (octave::interpreter& interp, const graphics_object& go, QAction *action, Object *parent); ~Menu (void); static Menu * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); Container * innerContainer (void) { return nullptr; } diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Object.cc --- a/libgui/graphics/Object.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Object.cc Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ #include "Object.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "qt-graphics-toolkit.h" #include "graphics.h" @@ -41,10 +40,10 @@ namespace octave { - Object::Object (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Object::Object (octave::interpreter& interp, const graphics_object& go, QObject *obj) - : QObject (), m_octave_qobj (oct_qobj), m_interpreter (interp), - m_go (go), m_handle (go.get_handle ()), m_qobject (nullptr) + : QObject (), m_interpreter (interp), m_go (go), + m_handle (go.get_handle ()), m_qobject (nullptr) { gh_manager& gh_mgr = m_interpreter.get_gh_manager (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Object.h --- a/libgui/graphics/Object.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Object.h Tue Dec 06 15:17:16 2022 -0500 @@ -37,7 +37,6 @@ namespace octave { - class base_qobject; class interpreter; class Container; @@ -48,8 +47,8 @@ Q_OBJECT public: - Object (octave::base_qobject& qobj, octave::interpreter& interp, - const graphics_object& go, QObject *obj = nullptr); + Object (octave::interpreter& interp, const graphics_object& go, + QObject *obj = nullptr); virtual ~Object (void); @@ -132,7 +131,6 @@ protected: - octave::base_qobject& m_octave_qobj; octave::interpreter& m_interpreter; // Store the graphics object directly so that it will exist when diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Panel.cc --- a/libgui/graphics/Panel.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Panel.cc Tue Dec 06 15:17:16 2022 -0500 @@ -39,8 +39,6 @@ #include "Panel.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" @@ -93,7 +91,7 @@ } Panel * - Panel::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Panel::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -103,15 +101,15 @@ Container *container = parent->innerContainer (); if (container) - return new Panel (oct_qobj, interp, go, new QFrame (container)); + return new Panel (interp, go, new QFrame (container)); } return nullptr; } - Panel::Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Panel::Panel (octave::interpreter& interp, const graphics_object& go, QFrame *frame) - : Object (oct_qobj, interp, go, frame), m_container (nullptr), + : Object (interp, go, frame), m_container (nullptr), m_title (nullptr), m_blockUpdates (false), m_previous_bbox (Matrix (1, 4, 0)) { @@ -128,7 +126,7 @@ setupPalette (pp, pal); frame->setPalette (pal); - m_container = new Container (frame, oct_qobj, interp); + m_container = new Container (frame, interp); m_container->canvas (m_handle); connect (m_container, SIGNAL (interpeter_event (const fcn_callback&)), diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Panel.h --- a/libgui/graphics/Panel.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Panel.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ namespace octave { - class base_qobject; class interpreter; class Container; @@ -41,7 +40,7 @@ class Panel : public Object { public: - Panel (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Panel (octave::interpreter& interp, const graphics_object& go, QFrame *frame); ~Panel (void); @@ -50,7 +49,7 @@ bool eventFilter (QObject *watched, QEvent *event); static Panel * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); void do_connections (const QObject *receiver, diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PopupMenuControl.cc --- a/libgui/graphics/PopupMenuControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PopupMenuControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,15 +33,13 @@ #include "PopupMenuControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "octave-qtutils.h" namespace octave { PopupMenuControl * - PopupMenuControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + PopupMenuControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -51,18 +49,17 @@ Container *container = parent->innerContainer (); if (container) - return new PopupMenuControl (oct_qobj, interp, go, + return new PopupMenuControl (interp, go, new QComboBox (container)); } return nullptr; } - PopupMenuControl::PopupMenuControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + PopupMenuControl::PopupMenuControl (octave::interpreter& interp, const graphics_object& go, QComboBox *box) - : BaseControl (oct_qobj, interp, go, box), m_blockUpdate (false) + : BaseControl (interp, go, box), m_blockUpdate (false) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PopupMenuControl.h --- a/libgui/graphics/PopupMenuControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PopupMenuControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ namespace octave { - class base_qobject; class interpreter; class PopupMenuControl : public BaseControl @@ -40,13 +39,12 @@ Q_OBJECT public: - PopupMenuControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, + PopupMenuControl (octave::interpreter& interp, const graphics_object& go, QComboBox *box); ~PopupMenuControl (void); static PopupMenuControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PushButtonControl.cc --- a/libgui/graphics/PushButtonControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PushButtonControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -34,14 +34,11 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { PushButtonControl * - PushButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + PushButtonControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -51,18 +48,17 @@ Container *container = parent->innerContainer (); if (container) - return new PushButtonControl (oct_qobj, interp, go, + return new PushButtonControl (interp, go, new QPushButton (container)); } return nullptr; } - PushButtonControl::PushButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + PushButtonControl::PushButtonControl (octave::interpreter& interp, const graphics_object& go, QPushButton *btn) - : ButtonControl (oct_qobj, interp, go, btn) + : ButtonControl (interp, go, btn) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PushButtonControl.h --- a/libgui/graphics/PushButtonControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PushButtonControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,19 +32,17 @@ namespace octave { - class base_qobject; class interpreter; class PushButtonControl : public ButtonControl { public: - PushButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, + PushButtonControl (octave::interpreter& interp, const graphics_object& go, QPushButton *btn); ~PushButtonControl (void); static PushButtonControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PushTool.cc --- a/libgui/graphics/PushTool.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PushTool.cc Tue Dec 06 15:17:16 2022 -0500 @@ -31,14 +31,11 @@ #include "ToolBarButton.cc" -#include "octave-qobject.h" - namespace octave { PushTool * - PushTool::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + PushTool::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -47,17 +44,16 @@ QWidget *parentWidget = parent->qWidget (); if (parentWidget) - return new PushTool (oct_qobj, interp, go, + return new PushTool (interp, go, new QAction (parentWidget)); } return nullptr; } - PushTool::PushTool (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + PushTool::PushTool (octave::interpreter& interp, const graphics_object& go, QAction *action) - : ToolBarButton (oct_qobj, interp, go, action) + : ToolBarButton (interp, go, action) { connect (action, &QAction::triggered, this, &PushTool::clicked); } diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/PushTool.h --- a/libgui/graphics/PushTool.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/PushTool.h Tue Dec 06 15:17:16 2022 -0500 @@ -30,7 +30,6 @@ namespace octave { - class base_qobject; class interpreter; class PushTool : public ToolBarButton @@ -38,12 +37,12 @@ Q_OBJECT public: - PushTool (octave::base_qobject& oct_qobj, octave::interpreter& interp, + PushTool (octave::interpreter& interp, const graphics_object& go, QAction *action); ~PushTool (void); static PushTool * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/RadioButtonControl.cc --- a/libgui/graphics/RadioButtonControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/RadioButtonControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -34,14 +34,11 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { RadioButtonControl * - RadioButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + RadioButtonControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -51,18 +48,17 @@ Container *container = parent->innerContainer (); if (container) - return new RadioButtonControl (oct_qobj, interp, go, + return new RadioButtonControl (interp, go, new QRadioButton (container)); } return nullptr; } - RadioButtonControl::RadioButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + RadioButtonControl::RadioButtonControl (octave::interpreter& interp, const graphics_object& go, QRadioButton *radio) - : ButtonControl (oct_qobj, interp, go, radio) + : ButtonControl (interp, go, radio) { Object *parent = parentObject (interp, go); ButtonGroup *btnGroup = dynamic_cast(parent); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/RadioButtonControl.h --- a/libgui/graphics/RadioButtonControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/RadioButtonControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,19 +32,16 @@ namespace octave { - class base_qobject; class interpreter; class RadioButtonControl : public ButtonControl { public: - RadioButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go, + RadioButtonControl (octave::interpreter& interp, const graphics_object& go, QRadioButton *box); ~RadioButtonControl (void); - static RadioButtonControl * create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + static RadioButtonControl * create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/SliderControl.cc --- a/libgui/graphics/SliderControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/SliderControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,8 +33,6 @@ #include "SliderControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" @@ -44,8 +42,7 @@ { SliderControl * - SliderControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + SliderControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -55,18 +52,17 @@ Container *container = parent->innerContainer (); if (container) - return new SliderControl (oct_qobj, interp, go, + return new SliderControl (interp, go, new QScrollBar (container)); } return nullptr; } - SliderControl::SliderControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + SliderControl::SliderControl (octave::interpreter& interp, const graphics_object& go, QAbstractSlider *slider) - : BaseControl (oct_qobj, interp, go, slider), m_blockUpdates (false) + : BaseControl (interp, go, slider), m_blockUpdates (false) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/SliderControl.h --- a/libgui/graphics/SliderControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/SliderControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ namespace octave { - class base_qobject; class interpreter; class SliderControl : public BaseControl @@ -40,12 +39,12 @@ Q_OBJECT public: - SliderControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + SliderControl (octave::interpreter& interp, const graphics_object& go, QAbstractSlider *slider); ~SliderControl (void); static SliderControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Table.cc --- a/libgui/graphics/Table.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Table.cc Tue Dec 06 15:17:16 2022 -0500 @@ -48,8 +48,6 @@ #include "Table.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - #include "graphics.h" #include "interpreter.h" #include "oct-map.h" @@ -436,7 +434,7 @@ } Table * - Table::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Table::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -446,15 +444,15 @@ Container *container = parent->innerContainer (); if (container) - return new Table (oct_qobj, interp, go, new QTableWidget (container)); + return new Table (interp, go, new QTableWidget (container)); } return 0; } - Table::Table (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Table::Table (octave::interpreter& interp, const graphics_object& go, QTableWidget *tableWidget) - : Object (oct_qobj, interp, go, tableWidget), m_tableWidget (tableWidget), + : Object (interp, go, tableWidget), m_tableWidget (tableWidget), m_curData (), m_blockUpdates (false) { qObject ()->setObjectName ("UItable"); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/Table.h --- a/libgui/graphics/Table.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/Table.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,7 +34,6 @@ namespace octave { - class base_qobject; class interpreter; class Container; @@ -44,7 +43,7 @@ Q_OBJECT public: - Table (octave::base_qobject& oct_qobj, octave::interpreter& interp, + Table (octave::interpreter& interp, const graphics_object& go, QTableWidget *tableWidget); ~Table (void); @@ -53,7 +52,7 @@ bool eventFilter (QObject *watched, QEvent *event); static Table * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/TextControl.cc --- a/libgui/graphics/TextControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/TextControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,14 +33,11 @@ #include "TextControl.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { TextControl * - TextControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + TextControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -49,16 +46,15 @@ Container *container = parent->innerContainer (); if (container) - return new TextControl (oct_qobj, interp, go, new QLabel (container)); + return new TextControl (interp, go, new QLabel (container)); } return nullptr; } - TextControl::TextControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + TextControl::TextControl (octave::interpreter& interp, const graphics_object& go, QLabel *label) - : BaseControl (oct_qobj, interp, go, label) + : BaseControl (interp, go, label) { uicontrol::properties& up = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/TextControl.h --- a/libgui/graphics/TextControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/TextControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,18 +32,17 @@ namespace octave { - class base_qobject; class interpreter; class TextControl : public BaseControl { public: - TextControl (octave::base_qobject& oct_qobj, octave::interpreter& interp, + TextControl (octave::interpreter& interp, const graphics_object& go, QLabel *label); ~TextControl (void); static TextControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToggleButtonControl.cc --- a/libgui/graphics/ToggleButtonControl.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToggleButtonControl.cc Tue Dec 06 15:17:16 2022 -0500 @@ -34,14 +34,11 @@ #include "Container.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" - namespace octave { ToggleButtonControl * - ToggleButtonControl::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ToggleButtonControl::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -51,18 +48,17 @@ Container *container = parent->innerContainer (); if (container) - return new ToggleButtonControl (oct_qobj, interp, go, + return new ToggleButtonControl (interp, go, new QPushButton (container)); } return nullptr; } - ToggleButtonControl::ToggleButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ToggleButtonControl::ToggleButtonControl (octave::interpreter& interp, const graphics_object& go, QPushButton *btn) - : ButtonControl (oct_qobj, interp, go, btn) + : ButtonControl (interp, go, btn) { Object *parent = parentObject (interp, go); ButtonGroup *btnGroup = dynamic_cast(parent); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToggleButtonControl.h --- a/libgui/graphics/ToggleButtonControl.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToggleButtonControl.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,19 +32,17 @@ namespace octave { - class base_qobject; class interpreter; class ToggleButtonControl : public ButtonControl { public: - ToggleButtonControl (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ToggleButtonControl (octave::interpreter& interp, const graphics_object& go, QPushButton *box); ~ToggleButtonControl (void); static ToggleButtonControl * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToggleTool.cc --- a/libgui/graphics/ToggleTool.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToggleTool.cc Tue Dec 06 15:17:16 2022 -0500 @@ -31,14 +31,11 @@ #include "ToolBarButton.cc" -#include "octave-qobject.h" - namespace octave { ToggleTool * - ToggleTool::create (octave::base_qobject& oct_qobj, - octave::interpreter& interp, const graphics_object& go) + ToggleTool::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -47,17 +44,16 @@ QWidget *parentWidget = parent->qWidget (); if (parentWidget) - return new ToggleTool (oct_qobj, interp, go, + return new ToggleTool (interp, go, new QAction (parentWidget)); } return nullptr; } - ToggleTool::ToggleTool (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ToggleTool::ToggleTool (octave::interpreter& interp, const graphics_object& go, QAction *action) - : ToolBarButton (oct_qobj, interp, go, action) + : ToolBarButton (interp, go, action) { uitoggletool::properties& tp = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToggleTool.h --- a/libgui/graphics/ToggleTool.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToggleTool.h Tue Dec 06 15:17:16 2022 -0500 @@ -30,7 +30,6 @@ namespace octave { - class base_qobject; class interpreter; class ToggleTool : public ToolBarButton @@ -38,13 +37,13 @@ Q_OBJECT public: - ToggleTool (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ToggleTool (octave::interpreter& interp, const graphics_object& go, QAction *action); ~ToggleTool (void); static ToggleTool * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); protected: diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToolBar.cc --- a/libgui/graphics/ToolBar.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToolBar.cc Tue Dec 06 15:17:16 2022 -0500 @@ -42,7 +42,6 @@ #include "QtHandlesUtils.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" namespace octave { @@ -69,7 +68,7 @@ } ToolBar * - ToolBar::create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ToolBar::create (octave::interpreter& interp, const graphics_object& go) { Object *parent = parentObject (interp, go); @@ -79,16 +78,16 @@ QWidget *parentWidget = parent->qWidget (); if (parentWidget) - return new ToolBar (oct_qobj, interp, go, + return new ToolBar (interp, go, new QToolBar (parentWidget)); } return nullptr; } - ToolBar::ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ToolBar::ToolBar (octave::interpreter& interp, const graphics_object& go, QToolBar *bar) - : Object (oct_qobj, interp, go, bar), m_empty (nullptr), m_figure (nullptr) + : Object (interp, go, bar), m_empty (nullptr), m_figure (nullptr) { uitoolbar::properties& tp = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToolBar.h --- a/libgui/graphics/ToolBar.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToolBar.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ namespace octave { - class base_qobject; class interpreter; class Figure; @@ -43,12 +42,12 @@ Q_OBJECT public: - ToolBar (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ToolBar (octave::interpreter& interp, const graphics_object& go, QToolBar *bar); ~ToolBar (void); static ToolBar * - create (octave::base_qobject& oct_qobj, octave::interpreter& interp, + create (octave::interpreter& interp, const graphics_object& go); Container * innerContainer (void) { return nullptr; } diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToolBarButton.cc --- a/libgui/graphics/ToolBarButton.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToolBarButton.cc Tue Dec 06 15:17:16 2022 -0500 @@ -34,16 +34,14 @@ #include "ToolBarButton.h" #include "QtHandlesUtils.h" -#include "octave-qobject.h" #include "gui-preferences-global.h" namespace octave { template - ToolBarButton::ToolBarButton (octave::base_qobject& oct_qobj, - octave::interpreter& interp, + ToolBarButton::ToolBarButton (octave::interpreter& interp, const graphics_object& go, QAction *action) - : Object (oct_qobj, interp, go, action), m_separator (nullptr) + : Object (interp, go, action), m_separator (nullptr) { typename T::properties& tp = properties (); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/ToolBarButton.h --- a/libgui/graphics/ToolBarButton.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/ToolBarButton.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ namespace octave { - class base_qobject; class interpreter; class Container; @@ -42,7 +41,7 @@ class ToolBarButton : public Object { public: - ToolBarButton (octave::base_qobject& oct_qobj, octave::interpreter& interp, + ToolBarButton (octave::interpreter& interp, const graphics_object& go, QAction *action); ~ToolBarButton (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/annotation-dialog.cc --- a/libgui/graphics/annotation-dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/annotation-dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,17 +33,14 @@ #include "gui-settings.h" #include "gui-preferences-gp.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "QtHandlesUtils.h" #include "annotation-dialog.h" #include "ui-annotation-dialog.h" -using namespace octave; - -annotation_dialog::annotation_dialog (octave::base_qobject& oct_qobj, - QWidget *p, const octave_value_list& pr): - QDialog (p), m_octave_qobj (oct_qobj), ui (new Ui::annotation_dialog) +annotation_dialog::annotation_dialog (QWidget *p, const octave_value_list& pr): + QDialog (p), ui (new Ui::annotation_dialog) { props = pr; @@ -55,13 +52,11 @@ { ui->setupUi (this); - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - octave::gui_settings *settings = rmgr.get_settings (); + octave::gui_settings settings; // restore last geometry - if (settings && settings->contains (gp_annotation_geometry.key)) - restoreGeometry (settings->value (gp_annotation_geometry).toByteArray ()); + if (settings.contains (gp_annotation_geometry.key)) + restoreGeometry (settings.value (gp_annotation_geometry).toByteArray ()); // connect signals connect (ui->button_box, &QDialogButtonBox::clicked, @@ -101,13 +96,10 @@ QDialogButtonBox::ButtonRole button_role = ui->button_box->buttonRole (button); - octave::resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - octave::gui_settings *settings = rmgr.get_settings (); + octave::gui_settings settings; // save position - if (settings) - settings->setValue (gp_annotation_geometry.key, saveGeometry ()); + settings.setValue (gp_annotation_geometry.key, saveGeometry ()); if (button_role == QDialogButtonBox::ApplyRole || button_role == QDialogButtonBox::AcceptRole) @@ -164,7 +156,7 @@ ui->cb_font_bold->isChecked () ? "bold" : "normal")); props.append (ovl ("fontangle", ui->cb_font_italic->isChecked () ? "italic" : "normal")); - props.append (ovl ("color", Utils::toRgb (ui->btn_color->palette (). + props.append (ovl ("color", octave::Utils::toRgb (ui->btn_color->palette (). color (QPalette::Button)))); // FIXME: only "none" linestyle is selectable, change the code bellow @@ -249,7 +241,7 @@ { QColor color; if (props(1*i +1).is_matrix_type ()) - color = Utils::fromRgb (props(2*i +1).matrix_value ()); + color = octave::Utils::fromRgb (props(2*i +1).matrix_value ()); else color.setNamedColor (props(2*i +1).string_value ().c_str ()); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/annotation-dialog.h --- a/libgui/graphics/annotation-dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/annotation-dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,11 +32,6 @@ #include "ovl.h" -namespace octave -{ - class base_qobject; -} - namespace Ui { class annotation_dialog; @@ -46,8 +41,7 @@ { Q_OBJECT public: - annotation_dialog (octave::base_qobject& oct_qobj, QWidget *parent, - const octave_value_list& pr); + annotation_dialog (QWidget *parent, const octave_value_list& pr); ~annotation_dialog (); octave_value_list get_properties () const; @@ -64,7 +58,6 @@ void get_gui_props (); void set_gui_props (); - octave::base_qobject& m_octave_qobj; Ui::annotation_dialog *ui; octave_value_list props; }; diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/qt-graphics-toolkit.cc --- a/libgui/graphics/qt-graphics-toolkit.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/qt-graphics-toolkit.cc Tue Dec 06 15:17:16 2022 -0500 @@ -57,8 +57,6 @@ #include "ToolBar.h" #include "qt-graphics-toolkit.h" -#include "octave-qobject.h" - #include "event-manager.h" #include "graphics.h" #include "interpreter.h" @@ -98,10 +96,8 @@ return ""; } - qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp, - octave::base_qobject& oct_qobj) - : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp), - m_octave_qobj (oct_qobj) + qt_graphics_toolkit::qt_graphics_toolkit (octave::interpreter& interp) + : QObject (), base_graphics_toolkit ("qt"), m_interpreter (interp) { // Implemented with a signal/slot connection in order to properly // cross from the interpreter thread (where requests to create @@ -412,47 +408,47 @@ Object *obj = nullptr; if (go.isa ("figure")) - obj = Figure::create (m_octave_qobj, m_interpreter, go); + obj = Figure::create (m_interpreter, go); else if (go.isa ("uicontrol")) { uicontrol::properties& up = Utils::properties (go); if (up.style_is ("pushbutton")) - obj = PushButtonControl::create (m_octave_qobj, m_interpreter, go); + obj = PushButtonControl::create (m_interpreter, go); else if (up.style_is ("edit")) - obj = EditControl::create (m_octave_qobj, m_interpreter, go); + obj = EditControl::create (m_interpreter, go); else if (up.style_is ("checkbox")) - obj = CheckBoxControl::create (m_octave_qobj, m_interpreter, go); + obj = CheckBoxControl::create (m_interpreter, go); else if (up.style_is ("radiobutton")) - obj = RadioButtonControl::create (m_octave_qobj, m_interpreter, go); + obj = RadioButtonControl::create (m_interpreter, go); else if (up.style_is ("togglebutton")) - obj = ToggleButtonControl::create (m_octave_qobj, m_interpreter, go); + obj = ToggleButtonControl::create (m_interpreter, go); else if (up.style_is ("text")) - obj = TextControl::create (m_octave_qobj, m_interpreter, go); + obj = TextControl::create (m_interpreter, go); else if (up.style_is ("popupmenu")) - obj = PopupMenuControl::create (m_octave_qobj, m_interpreter, go); + obj = PopupMenuControl::create (m_interpreter, go); else if (up.style_is ("slider")) - obj = SliderControl::create (m_octave_qobj, m_interpreter, go); + obj = SliderControl::create (m_interpreter, go); else if (up.style_is ("listbox")) - obj = ListBoxControl::create (m_octave_qobj, m_interpreter, go); + obj = ListBoxControl::create (m_interpreter, go); } else if (go.isa ("uibuttongroup")) - obj = ButtonGroup::create (m_octave_qobj, m_interpreter, go); + obj = ButtonGroup::create (m_interpreter, go); else if (go.isa ("uipanel")) - obj = Panel::create (m_octave_qobj, m_interpreter, go); + obj = Panel::create (m_interpreter, go); else if (go.isa ("uimenu")) - obj = Menu::create (m_octave_qobj, m_interpreter, go); + obj = Menu::create (m_interpreter, go); else if (go.isa ("uicontextmenu")) - obj = ContextMenu::create (m_octave_qobj, m_interpreter, go); + obj = ContextMenu::create (m_interpreter, go); else if (go.isa ("uitable")) - obj = Table::create (m_octave_qobj, m_interpreter, go); + obj = Table::create (m_interpreter, go); else if (go.isa ("uitoolbar")) - obj = ToolBar::create (m_octave_qobj, m_interpreter, go); + obj = ToolBar::create (m_interpreter, go); else if (go.isa ("uipushtool")) - obj = PushTool::create (m_octave_qobj, m_interpreter, go); + obj = PushTool::create (m_interpreter, go); else if (go.isa ("uitoggletool")) - obj = ToggleTool::create (m_octave_qobj, m_interpreter, go); + obj = ToggleTool::create (m_interpreter, go); else qWarning ("qt_graphics_toolkit::create_object: unsupported type '%s'", go.type ().c_str ()); diff -r 9089bd969b37 -r bd9da634f00d libgui/graphics/qt-graphics-toolkit.h --- a/libgui/graphics/qt-graphics-toolkit.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/graphics/qt-graphics-toolkit.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,7 +34,6 @@ namespace octave { class interpreter; - class base_qobject; class Object; class ObjectProxy; @@ -46,8 +45,7 @@ public: - qt_graphics_toolkit (octave::interpreter& interp, - octave::base_qobject& oct_qobj); + qt_graphics_toolkit (octave::interpreter& interp); ~qt_graphics_toolkit (void) = default; @@ -119,8 +117,6 @@ private: octave::interpreter& m_interpreter; - - octave::base_qobject& m_octave_qobj; }; } diff -r 9089bd969b37 -r bd9da634f00d libgui/qterminal/libqterminal/QTerminal.cc --- a/libgui/qterminal/libqterminal/QTerminal.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/qterminal/libqterminal/QTerminal.cc Tue Dec 06 15:17:16 2022 -0500 @@ -38,6 +38,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-cs.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "resource-manager.h" @@ -199,32 +200,31 @@ } void -QTerminal::notice_settings (const gui_settings *settings) +QTerminal::notice_settings (void) { - if (! settings) - return; + octave::gui_settings settings; // Set terminal font: QFont term_font = QFont (); term_font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); term_font.setFamily - (settings->value (cs_font.key, default_font).toString ()); + (settings.value (cs_font.key, default_font).toString ()); term_font.setPointSize - (settings->value (cs_font_size).toInt ()); + (settings.value (cs_font_size).toInt ()); setTerminalFont (term_font); QFontMetrics metrics (term_font); setMinimumSize (metrics.maxWidth ()*16, metrics.height ()*3); QString cursor_type - = settings->value (cs_cursor).toString (); + = settings.value (cs_cursor).toString (); bool cursor_blinking; - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); for (int ct = IBeamCursor; ct <= UnderlineCursor; ct++) { @@ -236,47 +236,47 @@ } bool cursorUseForegroundColor - = settings->value (cs_cursor_use_fgcol).toBool (); + = settings.value (cs_cursor_use_fgcol).toBool (); - int mode = settings->value (cs_color_mode).toInt (); + int mode = settings.value (cs_color_mode).toInt (); - setForegroundColor (settings->color_value (cs_colors[0], mode)); + setForegroundColor (settings.color_value (cs_colors[0], mode)); - setBackgroundColor (settings->color_value (cs_colors[1], mode)); + setBackgroundColor (settings.color_value (cs_colors[1], mode)); - setSelectionColor (settings->color_value (cs_colors[2], mode)); + setSelectionColor (settings.color_value (cs_colors[2], mode)); setCursorColor (cursorUseForegroundColor, - settings->color_value (cs_colors[3], mode)); + settings.color_value (cs_colors[3], mode)); - setScrollBufferSize (settings->value (cs_hist_buffer).toInt ()); + setScrollBufferSize (settings.value (cs_hist_buffer).toInt ()); // If the Copy shortcut is Ctrl+C, then the Copy action also emits // a signal for interrupting the current code executed by the worker. // If the Copy shortcut is not Ctrl+C, an extra interrupt action is // set up for emitting the interrupt signal. - QString sc = settings->sc_value (sc_main_edit_copy); + QString sc = settings.sc_value (sc_main_edit_copy); // Dis- or enable extra interrupt action: We need an extra option when // copy shortcut is not Ctrl-C or when global shortcuts (like copy) are // disabled. bool extra_ir_action = (sc != QKeySequence (Qt::ControlModifier | Qt::Key_C).toString ()) - || settings->value (sc_prevent_rl_conflicts).toBool (); + || settings.value (sc_prevent_rl_conflicts).toBool (); _interrupt_action->setEnabled (extra_ir_action); has_extra_interrupt (extra_ir_action); // check whether shortcut Ctrl-D is in use by the main-window - bool ctrld = settings->value (sc_main_ctrld).toBool (); + bool ctrld = settings.value (sc_main_ctrld).toBool (); _nop_action->setEnabled (! ctrld); } void QTerminal::construct (octave::base_qobject& oct_qobj) { - octave::resource_manager& rmgr = oct_qobj.get_resource_manager (); + octave::gui_settings settings; // context menu setContextMenuPolicy (Qt::CustomContextMenu); @@ -284,11 +284,11 @@ _contextMenu = new QMenu (this); _copy_action - = _contextMenu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, + = _contextMenu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this, SLOT (copyClipboard ())); _paste_action - = _contextMenu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this, + = _contextMenu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this, SLOT (pasteClipboard ())); _contextMenu->addSeparator (); diff -r 9089bd969b37 -r bd9da634f00d libgui/qterminal/libqterminal/QTerminal.h --- a/libgui/qterminal/libqterminal/QTerminal.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/qterminal/libqterminal/QTerminal.h Tue Dec 06 15:17:16 2022 -0500 @@ -30,13 +30,6 @@ #include #include -// For now, we need to use the following #include and using statement -// for the signal/slot macros. Could maybe change later when using -// Qt5-style signal/slot connections. -#include "gui-settings.h" - -using octave::gui_settings; - namespace octave { class base_qobject; @@ -126,7 +119,7 @@ virtual void handleCustomContextMenuRequested (const QPoint& at); - void notice_settings (const gui_settings *settings); + void notice_settings (void); virtual void init_terminal_size (void) { } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/command-widget.cc --- a/libgui/src/command-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/command-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -44,6 +44,7 @@ #include "event-manager.h" #include "gui-preferences-cs.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "gui-utils.h" #include "input.h" #include "interpreter.h" @@ -144,23 +145,25 @@ } - void command_widget::notice_settings (const gui_settings *settings) + void command_widget::notice_settings (void) { + gui_settings settings; + // Set terminal font: QFont term_font = QFont (); term_font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); term_font.setFamily - (settings->value (cs_font.key, default_font).toString ()); + (settings.value (cs_font.key, default_font).toString ()); term_font.setPointSize - (settings->value (cs_font_size).toInt ()); + (settings.value (cs_font_size).toInt ()); m_console->setFont (term_font); // Colors - int mode = settings->value (cs_color_mode).toInt (); - QColor fgc = settings->color_value (cs_colors[0], mode); - QColor bgc = settings->color_value (cs_colors[1], mode); + int mode = settings.value (cs_color_mode).toInt (); + QColor fgc = settings.color_value (cs_colors[0], mode); + QColor bgc = settings.color_value (cs_colors[1], mode); m_console->setStyleSheet (QString ("color: %1; background-color:%2;") .arg (fgc.name ()).arg (bgc.name ())); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/command-widget.h --- a/libgui/src/command-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/command-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -30,8 +30,11 @@ #include -#include "octave-qobject.h" -#include "gui-settings.h" +// FIXME: We need the following header for the fcn_callback and +// meth_callback typedefs. Maybe it would be better to declare those in +// a separate file because inclding "event-manager.h" pulls in a lot of +// other unnecessary declarations. +#include "event-manager.h" class QsciScintilla; @@ -113,7 +116,7 @@ void insert_interpreter_output (const QString& msg); - void notice_settings (const gui_settings *settings); + void notice_settings (void); private: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/community-news.cc --- a/libgui/src/community-news.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/community-news.cc Tue Dec 06 15:17:16 2022 -0500 @@ -35,27 +35,25 @@ #include "gui-utils.h" #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "news-reader.h" -#include "octave-qobject.h" namespace octave { - community_news::community_news (base_qobject& oct_qobj, int serial) + community_news::community_news (int serial) : QWidget (nullptr), m_browser (nullptr) { - construct (oct_qobj, "https://octave.org", "community-news.html", serial); + construct ("https://octave.org", "community-news.html", serial); } - community_news::community_news (base_qobject& oct_qobj, QWidget *parent, - const QString& base_url, const QString& page, - int serial) + community_news::community_news (QWidget *parent, const QString& base_url, + const QString& page, int serial) : QWidget (parent), m_browser (nullptr) { - construct (oct_qobj, base_url, page, serial); + construct (base_url, page, serial); } - void community_news::construct (base_qobject& oct_qobj, - const QString& base_url, const QString& page, + void community_news::construct (const QString& base_url, const QString& page, int serial) { m_browser = new QTextBrowser (this); @@ -76,11 +74,10 @@ resize (win_x/2, win_y/2); move ((win_x - width ())/2, (win_y - height ())/2); - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; QString icon; - QString icon_set = settings->value (dw_icon_set).toString (); + QString icon_set = settings.value (dw_icon_set).toString (); if (icon_set != "NONE") // No extra icon for Community news, take the one of the release notes icon = dw_icon_set_names[icon_set] + "ReleaseWidget.png"; @@ -92,15 +89,12 @@ // FIXME: This is a news reader preference, so shouldn't it be used // in the news_reader object? - bool connect_to_web - = (settings - ? settings->value (nr_allow_connection).toBool () - : true); + bool connect_to_web = settings.value (nr_allow_connection).toBool (); QThread *worker_thread = new QThread; - news_reader *reader = new news_reader (oct_qobj, base_url, page, - serial, connect_to_web); + news_reader *reader + = new news_reader (base_url, page, serial, connect_to_web); reader->moveToThread (worker_thread); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/community-news.h --- a/libgui/src/community-news.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/community-news.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,17 +33,15 @@ namespace octave { - class base_qobject; - class community_news : public QWidget { Q_OBJECT public: - community_news (base_qobject& oct_qobj, int serial); + community_news (int serial); - community_news (base_qobject& oct_qobj, QWidget *parent = nullptr, + community_news (QWidget *parent = nullptr, const QString& base_url = "https://octave.org", const QString& page = "community-news.html", int serial = -1); @@ -58,8 +56,7 @@ private: - void construct (base_qobject& oct_qobj, const QString& base_url, - const QString& page, int serial); + void construct (const QString& base_url, const QString& page, int serial); QTextBrowser *m_browser; }; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/dialog.cc --- a/libgui/src/dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -42,14 +42,14 @@ #include #include "dialog.h" -#include "octave-qobject.h" #include "gui-preferences-global.h" +#include "gui-settings.h" namespace octave { - QUIWidgetCreator::QUIWidgetCreator (base_qobject& oct_qobj) - : QObject (), m_octave_qobj (oct_qobj), m_dialog_result (-1), - m_dialog_button (), m_string_list (), m_list_index (), m_path_name () + QUIWidgetCreator::QUIWidgetCreator () + : QObject (), m_dialog_result (-1), m_dialog_button (), + m_string_list (), m_list_index (), m_path_name () { connect (this, &QUIWidgetCreator::create_dialog, this, &QUIWidgetCreator::handle_create_dialog); @@ -180,8 +180,7 @@ const QStringList& role) { MessageDialog *message_dialog - = new MessageDialog (m_octave_qobj, message, title, icon, - button, defbutton, role); + = new MessageDialog (message, title, icon, button, defbutton, role); connect (message_dialog, &MessageDialog::buttonClicked, this, &QUIWidgetCreator::dialog_button_clicked); @@ -232,7 +231,7 @@ const QString& cancel_string) { ListDialog *list_dialog - = new ListDialog (m_octave_qobj, list, mode, wd, ht, initial, + = new ListDialog (list, mode, wd, ht, initial, name, prompt, ok_string, cancel_string); connect (list_dialog, &ListDialog::finish_selection, @@ -264,7 +263,7 @@ const QStringList& defaults) { InputDialog *input_dialog - = new InputDialog (m_octave_qobj, prompt, title, nr, nc, defaults); + = new InputDialog (prompt, title, nr, nc, defaults); connect (input_dialog, &InputDialog::finish_input, this, &QUIWidgetCreator::input_finished); @@ -292,8 +291,7 @@ const QString& multimode) { FileDialog *file_dialog - = new FileDialog (m_octave_qobj, filters, title, filename, - dirname, multimode); + = new FileDialog (filters, title, filename, dirname, multimode); connect (file_dialog, &FileDialog::finish_input, this, &QUIWidgetCreator::filedialog_finished); @@ -316,7 +314,7 @@ wake_all (); } - MessageDialog::MessageDialog (base_qobject&, const QString& message, + MessageDialog::MessageDialog (const QString& message, const QString& title, const QString& qsicon, const QStringList& qsbutton, const QString& defbutton, @@ -388,7 +386,7 @@ } } - ListDialog::ListDialog (base_qobject&, const QStringList& list, + ListDialog::ListDialog (const QStringList& list, const QString& mode, int wd, int ht, const QList& initial, const QString& title, const QStringList& prompt, @@ -524,7 +522,7 @@ buttonOk_clicked (); } - InputDialog::InputDialog (base_qobject&, const QStringList& prompt, + InputDialog::InputDialog (const QStringList& prompt, const QString& title, const QFloatList& nr, const QFloatList& nc, const QStringList& defaults) : QDialog () @@ -618,8 +616,7 @@ buttonCancel_clicked (); } - FileDialog::FileDialog (base_qobject& oct_qobj, - const QStringList& name_filters, + FileDialog::FileDialog (const QStringList& name_filters, const QString& title, const QString& filename, const QString& dirname, const QString& multimode) : QFileDialog () @@ -631,9 +628,10 @@ setDirectory (dirname); // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) setOption(QFileDialog::DontUseNativeDialog); if (multimode == "on") // uigetfile multiselect=on diff -r 9089bd969b37 -r bd9da634f00d libgui/src/dialog.h --- a/libgui/src/dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -44,15 +44,13 @@ namespace octave { - class base_qobject; - class QUIWidgetCreator : public QObject { Q_OBJECT public: - QUIWidgetCreator (base_qobject& oct_qobj); + QUIWidgetCreator (void); ~QUIWidgetCreator (void) = default; @@ -148,8 +146,6 @@ private: - base_qobject& m_octave_qobj; - int m_dialog_result; QString m_dialog_button; @@ -176,7 +172,7 @@ public: - MessageDialog (base_qobject& oct_qobj, const QString& message, + MessageDialog (const QString& message, const QString& title, const QString& icon, const QStringList& button, const QString& defbutton, const QStringList& role); @@ -201,7 +197,7 @@ public: - ListDialog (base_qobject& oct_qobj, const QStringList& list, + ListDialog (const QStringList& list, const QString& mode, int width, int height, const QList& initial, const QString& name, const QStringList& prompt, const QString& ok_string, @@ -236,7 +232,7 @@ public: - InputDialog (base_qobject& oct_qobj, const QStringList& prompt, + InputDialog (const QStringList& prompt, const QString& title, const QFloatList& nr, const QFloatList& nc, const QStringList& defaults); @@ -261,7 +257,7 @@ public: - FileDialog (base_qobject& oct_qobj, const QStringList& filters, + FileDialog (const QStringList& filters, const QString& title, const QString& filename, const QString& dirname, const QString& multimode); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation-bookmarks.cc --- a/libgui/src/documentation-bookmarks.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation-bookmarks.cc Tue Dec 06 15:17:16 2022 -0500 @@ -28,7 +28,10 @@ #endif #include +#include +#include #include +#include #include #include #include @@ -36,10 +39,10 @@ #include "documentation.h" #include "documentation-bookmarks.h" -#include "gui-settings.h" #include "gui-preferences-global.h" #include "gui-preferences-dc.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qtutils.h" #include "shortcut-manager.h" @@ -49,17 +52,14 @@ namespace octave { - documentation_bookmarks::documentation_bookmarks ( - documentation *doc, documentation_browser *browser, - base_qobject& oct_qobj, QWidget *p) - : QWidget (p), - m_doc (doc), m_browser (browser), m_octave_qobj (oct_qobj), - m_ctx_menu_item (nullptr) + documentation_bookmarks::documentation_bookmarks (documentation *doc, + documentation_browser *browser, + QWidget *p) + : QWidget (p), m_doc (doc), m_browser (browser), m_ctx_menu_item (nullptr) { setObjectName ("documentation_tab_bookmarks"); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; // Setup the tree view with the bookmarks m_tree = new QTreeWidget (p); @@ -89,7 +89,7 @@ icon_bookmark.addPixmap (style ()->standardPixmap(QStyle::SP_FileIcon)); // Setup and read the bookmarkfile - QFileInfo f (settings->fileName ()); + QFileInfo f (settings.fileName ()); QString f_path = f.absolutePath (); f.setFile (QDir (f_path), dc_bookmark_file); m_xbel_file.setFileName (f.absoluteFilePath ()); @@ -121,7 +121,7 @@ m_filter->setSizePolicy (size_pol); m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive); - m_filter->addItems (settings->value (dc_bookmark_filter_mru).toStringList ()); + m_filter->addItems (settings.value (dc_bookmark_filter_mru).toStringList ()); connect (m_filter, &QComboBox::editTextChanged, this, &documentation_bookmarks::filter_bookmarks); @@ -129,7 +129,7 @@ this, &documentation_bookmarks::update_filter_history); m_filter_checkbox = new QCheckBox (m_filter_widget); - bool filter_state = settings->value (dc_bookmark_filter_active).toBool (); + bool filter_state = settings.value (dc_bookmark_filter_active).toBool (); m_filter_checkbox->setChecked (filter_state); filter_activate (filter_state); @@ -144,7 +144,7 @@ h_box_bm->setMargin (2); m_filter_widget->setLayout (h_box_bm); - m_filter_shown = settings->value (dc_bookmark_filter_shown).toBool (); + m_filter_shown = settings.value (dc_bookmark_filter_shown).toBool (); m_filter_widget->setVisible (m_filter_shown); // Resulting Layout of this widget @@ -322,11 +322,11 @@ if (m_ctx_menu_item) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; menu.addAction (tr ("&Open"), this, &documentation_bookmarks::open); menu.addAction (tr ("&Rename"), this, &documentation_bookmarks::edit); - menu.addAction (rmgr.icon ("window-close"), tr ("Remo&ve"), + menu.addAction (settings.icon ("window-close"), tr ("Remo&ve"), this, &documentation_bookmarks::remove); menu.addSeparator (); } @@ -380,21 +380,23 @@ m_filter_widget->setVisible (m_filter_shown); } - void documentation_bookmarks::save_settings (gui_settings *settings) + void documentation_bookmarks::save_settings (void) { // Write the bookmarks to the xbel-file write_bookmarks (); // Store settings - settings->setValue (dc_bookmark_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (dc_bookmark_filter_shown.key, m_filter_shown); + gui_settings settings; + + settings.setValue (dc_bookmark_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (dc_bookmark_filter_shown.key, m_filter_shown); QStringList mru; for (int i = 0; i < m_filter->count (); i++) mru.append (m_filter->itemText (i)); - settings->setValue (dc_bookmark_filter_mru.key, mru); + settings.setValue (dc_bookmark_filter_mru.key, mru); - settings->sync (); + settings.sync (); } void documentation_bookmarks::write_bookmarks (void) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation-bookmarks.h --- a/libgui/src/documentation-bookmarks.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation-bookmarks.h Tue Dec 06 15:17:16 2022 -0500 @@ -28,16 +28,14 @@ #include #include +#include #include #include #include "documentation.h" -#include "octave-qobject.h" - namespace octave { - class base_qobject; class documentation; class documentation_bookmarks : public QWidget @@ -46,9 +44,9 @@ public: - documentation_bookmarks ( - documentation *doc, documentation_browser *browser, - base_qobject& oct_qobj, QWidget *p = nullptr); + documentation_bookmarks (documentation *doc, + documentation_browser *browser, + QWidget *p = nullptr); ~documentation_bookmarks (void) = default; @@ -56,7 +54,7 @@ void add_bookmark (void); void add_folder (bool); - void save_settings (gui_settings *settings); + void save_settings (void); private slots: @@ -103,7 +101,6 @@ documentation *m_doc; documentation_browser *m_browser; - base_qobject& m_octave_qobj; QComboBox *m_filter; QTreeWidget *m_tree; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation-dock-widget.cc --- a/libgui/src/documentation-dock-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation-dock-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -47,9 +47,9 @@ make_window (); } - void documentation_dock_widget::notice_settings (const gui_settings *settings) + void documentation_dock_widget::notice_settings (void) { - m_docs->notice_settings (settings); + m_docs->notice_settings (); } void documentation_dock_widget::save_settings (void) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation-dock-widget.h --- a/libgui/src/documentation-dock-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation-dock-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -45,7 +45,7 @@ public slots: - void notice_settings (const gui_settings *settings); + void notice_settings (void); void save_settings (void); void copyClipboard (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation.cc --- a/libgui/src/documentation.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation.cc Tue Dec 06 15:17:16 2022 -0500 @@ -56,6 +56,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-dc.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "shortcut-manager.h" @@ -156,14 +157,16 @@ QToolButton *forward_button = new QToolButton (find_footer); forward_button->setText (tr ("Search forward")); forward_button->setToolTip (tr ("Search forward")); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - forward_button->setIcon (rmgr.icon ("go-down")); + + gui_settings settings; + + forward_button->setIcon (settings.icon ("go-down")); connect (forward_button, &QToolButton::pressed, this, [=] () { find (); }); QToolButton *backward_button = new QToolButton (find_footer); backward_button->setText (tr ("Search backward")); backward_button->setToolTip (tr ("Search backward")); - backward_button->setIcon (rmgr.icon ("go-up")); + backward_button->setIcon (settings.icon ("go-up")); connect (backward_button, &QToolButton::pressed, this, &documentation::find_backward); QHBoxLayout *h_box_find_footer = new QHBoxLayout (find_footer); @@ -180,7 +183,7 @@ v_box_browser_find->addWidget (find_footer); browser_find->setLayout (v_box_browser_find); - notice_settings (rmgr.get_settings ()); + notice_settings (); m_findnext_shortcut->setContext (Qt::WidgetWithChildrenShortcut); connect (m_findnext_shortcut, &QShortcut::activated, @@ -262,8 +265,7 @@ this, &documentation::filter_update_history); // Bookmarks (own class) - m_bookmarks - = new documentation_bookmarks (this, m_doc_browser, m_octave_qobj, navi); + m_bookmarks = new documentation_bookmarks (this, m_doc_browser, navi); navi->addTab (m_bookmarks, tr ("Bookmarks")); connect (m_action_bookmark, &QAction::triggered, @@ -348,13 +350,14 @@ void documentation::construct_tool_bar (void) { // Home, Previous, Next - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; + m_action_go_home - = add_action (rmgr.icon ("go-home"), tr ("Go home"), SLOT (home (void)), + = add_action (settings.icon ("go-home"), tr ("Go home"), SLOT (home (void)), m_doc_browser, m_tool_bar); m_action_go_prev - = add_action (rmgr.icon ("go-previous"), tr ("Go back"), + = add_action (settings.icon ("go-previous"), tr ("Go back"), SLOT (backward (void)), m_doc_browser, m_tool_bar); m_action_go_prev->setEnabled (false); @@ -369,7 +372,7 @@ m_tool_bar->addWidget (popdown_button_prev_pages); m_action_go_next - = add_action (rmgr.icon ("go-next"), tr ("Go forward"), + = add_action (settings.icon ("go-next"), tr ("Go forward"), SLOT (forward (void)), m_doc_browser, m_tool_bar); m_action_go_next->setEnabled (false); @@ -412,26 +415,26 @@ // Find m_tool_bar->addSeparator (); m_action_find - = add_action (rmgr.icon ("edit-find"), tr ("Find"), + = add_action (settings.icon ("edit-find"), tr ("Find"), SLOT (activate_find (void)), this, m_tool_bar); // Zoom m_tool_bar->addSeparator (); m_action_zoom_in - = add_action (rmgr.icon ("view-zoom-in"), tr ("Zoom in"), + = add_action (settings.icon ("view-zoom-in"), tr ("Zoom in"), SLOT (zoom_in (void)), m_doc_browser, m_tool_bar); m_action_zoom_out - = add_action (rmgr.icon ("view-zoom-out"), tr ("Zoom out"), + = add_action (settings.icon ("view-zoom-out"), tr ("Zoom out"), SLOT (zoom_out (void)), m_doc_browser, m_tool_bar); m_action_zoom_original - = add_action (rmgr.icon ("view-zoom-original"), tr ("Zoom original"), + = add_action (settings.icon ("view-zoom-original"), tr ("Zoom original"), SLOT (zoom_original (void)), m_doc_browser, m_tool_bar); // Bookmarks (connect slots later) m_tool_bar->addSeparator (); m_action_bookmark - = add_action (rmgr.icon ("bookmark-new"), tr ("Bookmark current page"), - nullptr, nullptr, m_tool_bar); + = add_action (settings.icon ("bookmark-new"), + tr ("Bookmark current page"), nullptr, nullptr, m_tool_bar); } void documentation::global_search (void) @@ -603,15 +606,17 @@ m_doc_browser->moveCursor (QTextCursor::Start); } - void documentation::notice_settings (const gui_settings *settings) + void documentation::notice_settings (void) { + gui_settings settings; + // If m_help_engine is not defined, the objects accessed by this method // are not valid. Thus, just return in this case. if (! m_help_engine) return; // Icon size in the toolbar. - int size_idx = settings->value (global_icon_size).toInt (); + int size_idx = settings.value (global_icon_size).toInt (); size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 QStyle *st = style (); @@ -633,16 +638,15 @@ scmgr.set_shortcut (m_action_bookmark, sc_doc_bookmark); // Settings for the browser - m_doc_browser->notice_settings (settings); + m_doc_browser->notice_settings (); } void documentation::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - m_doc_browser->save_settings (settings); - m_bookmarks->save_settings (settings); + m_doc_browser->save_settings (); + m_bookmarks->save_settings (); } void documentation::copyClipboard (void) @@ -1039,12 +1043,14 @@ QDesktopServices::openUrl (url); } - void documentation_browser::notice_settings (const gui_settings *settings) + void documentation_browser::notice_settings (void) { + gui_settings settings; + // Zoom level only at startup, not when other settings have changed if (m_zoom_level > max_zoom_level) { - m_zoom_level = settings->value (dc_browser_zoom_level).toInt (); + m_zoom_level = settings.value (dc_browser_zoom_level).toInt (); zoomIn (m_zoom_level); } } @@ -1057,11 +1063,13 @@ return QTextBrowser::loadResource(type, url); } - void documentation_browser::save_settings (gui_settings *settings) + void documentation_browser::save_settings (void) { - settings->setValue (dc_browser_zoom_level.key, m_zoom_level); + gui_settings settings; - settings->sync (); + settings.setValue (dc_browser_zoom_level.key, m_zoom_level); + + settings.sync (); } void documentation_browser::zoom_in (void) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/documentation.h --- a/libgui/src/documentation.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/documentation.h Tue Dec 06 15:17:16 2022 -0500 @@ -37,8 +37,6 @@ #include #include -#include "gui-settings.h" - namespace octave { class base_qobject; @@ -62,8 +60,8 @@ void handle_index_clicked (const QUrl& url, const QString& keyword = QString ()); - void notice_settings (const gui_settings *settings); - void save_settings (gui_settings *settings); + void notice_settings (void); + void save_settings (void); //! Zooming in and out while taking care of the zoom level //!@{ @@ -122,7 +120,7 @@ public slots: - void notice_settings (const gui_settings *settings); + void notice_settings (void); void save_settings (void); void copyClipboard (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/dw-main-window.cc --- a/libgui/src/dw-main-window.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/dw-main-window.cc Tue Dec 06 15:17:16 2022 -0500 @@ -36,9 +36,10 @@ #include #include "dw-main-window.h" +#include "gui-preferences-sc.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "shortcut-manager.h" -#include "gui-preferences-sc.h" namespace octave { @@ -46,19 +47,19 @@ dw_main_window::dw_main_window (base_qobject& oct_qobj, QWidget *p) : QMainWindow (p), m_octave_qobj (oct_qobj) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; // Adding the actions for closing the dock widgets m_close_action - = add_action (nullptr, rmgr.icon ("window-close", false), + = add_action (nullptr, settings.icon ("window-close", false), tr ("&Close"), SLOT (request_close ()), this); m_close_all_action - = add_action (nullptr, rmgr.icon ("window-close", false), + = add_action (nullptr, settings.icon ("window-close", false), tr ("Close &All"), SLOT (request_close_all ()), this); m_close_others_action - = add_action (nullptr, rmgr.icon ("window-close", false), + = add_action (nullptr, settings.icon ("window-close", false), tr ("Close &Other"), SLOT (request_close_other ()), this); m_switch_left_action @@ -76,7 +77,7 @@ m_actions_list << m_switch_left_action; m_actions_list << m_switch_right_action; - notice_settings (rmgr.get_settings ()); + notice_settings (); } @@ -130,7 +131,7 @@ } // Update the settings - void dw_main_window::notice_settings (const gui_settings *) + void dw_main_window::notice_settings (void) { shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/dw-main-window.h --- a/libgui/src/dw-main-window.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/dw-main-window.h Tue Dec 06 15:17:16 2022 -0500 @@ -28,8 +28,6 @@ #include -#include "gui-settings.h" - namespace octave { class base_qobject; @@ -52,7 +50,7 @@ public slots: - void notice_settings (const gui_settings *); + void notice_settings (void); protected slots: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/external-editor-interface.cc --- a/libgui/src/external-editor-interface.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/external-editor-interface.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,13 +33,11 @@ #include "external-editor-interface.h" #include "gui-settings.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" namespace octave { - external_editor_interface::external_editor_interface (QWidget *p, - base_qobject& oct_qobj) - : QWidget (p), m_octave_qobj (oct_qobj) + external_editor_interface::external_editor_interface (QWidget *p) + : QWidget (p) { } // Calling the external editor @@ -103,10 +101,10 @@ // Get and verify the settings of the external editor program QString external_editor_interface::external_editor (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString editor = settings->value (global_custom_editor.key, - global_custom_editor.def).toString (); + gui_settings settings; + + QString editor = settings.value (global_custom_editor.key, + global_custom_editor.def).toString (); // check the settings (avoid an empty string) if (editor.trimmed ().isEmpty ()) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/external-editor-interface.h --- a/libgui/src/external-editor-interface.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/external-editor-interface.h Tue Dec 06 15:17:16 2022 -0500 @@ -31,15 +31,13 @@ namespace octave { - class base_qobject; - class external_editor_interface : public QWidget { Q_OBJECT public: - external_editor_interface (QWidget *main_win, base_qobject& oct_qobj); + external_editor_interface (QWidget *main_win); ~external_editor_interface (void) = default; @@ -64,8 +62,6 @@ private: QString external_editor (void); - - base_qobject& m_octave_qobj; }; } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/files-dock-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -49,6 +49,7 @@ #include "files-dock-widget.h" #include "gui-preferences-fb.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "qt-interpreter-events.h" @@ -226,20 +227,21 @@ QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred); m_current_directory->setSizePolicy (sizePol); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; QAction *directory_up_action - = new QAction (rmgr.icon ("folder-up", false, "go-up"), "", m_navigation_tool_bar); + = new QAction (settings.icon ("folder-up", false, "go-up"), "", + m_navigation_tool_bar); directory_up_action->setToolTip (tr ("One directory up")); m_sync_browser_directory_action - = new QAction (rmgr.icon ("go-first"), tr ("Show Octave directory"), + = new QAction (settings.icon ("go-first"), tr ("Show Octave directory"), m_navigation_tool_bar); m_sync_browser_directory_action->setToolTip (tr ("Go to current Octave directory")); m_sync_browser_directory_action->setEnabled (false); m_sync_octave_directory_action - = new QAction (rmgr.icon ("go-last"), tr ("Set Octave directory"), + = new QAction (settings.icon ("go-last"), tr ("Set Octave directory"), m_navigation_tool_bar); m_sync_octave_directory_action->setToolTip (tr ("Set Octave directory to current browser directory")); m_sync_octave_directory_action->setEnabled (false); @@ -247,7 +249,7 @@ QToolButton *popdown_button = new QToolButton (); popdown_button->setToolTip (tr ("Actions on current directory")); QMenu *popdown_menu = new QMenu (); - popdown_menu->addAction (rmgr.icon ("user-home"), + popdown_menu->addAction (settings.icon ("user-home"), tr ("Show Home Directory"), this, SLOT (popdownmenu_home (bool))); popdown_menu->addAction (m_sync_browser_directory_action); @@ -255,22 +257,23 @@ popdown_button->setMenu (popdown_menu); popdown_button->setPopupMode (QToolButton::InstantPopup); popdown_button->setDefaultAction ( - new QAction (rmgr.icon ("folder-settings", false, "applications-system"), - "", m_navigation_tool_bar)); + new QAction (settings.icon ("folder-settings", false, + "applications-system"), + "", m_navigation_tool_bar)); popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("folder"), + popdown_menu->addAction (settings.icon ("folder"), tr ("Set Browser Directory..."), this, &files_dock_widget::popdownmenu_search_dir); popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("edit-find"), + popdown_menu->addAction (settings.icon ("edit-find"), tr ("Find Files..."), this, &files_dock_widget::popdownmenu_findfiles); popdown_menu->addSeparator (); - popdown_menu->addAction (rmgr.icon ("document-new"), + popdown_menu->addAction (settings.icon ("document-new"), tr ("New File..."), this, &files_dock_widget::popdownmenu_newfile); - popdown_menu->addAction (rmgr.icon ("folder-new"), + popdown_menu->addAction (settings.icon ("folder-new"), tr ("New Directory..."), this, &files_dock_widget::popdownmenu_newdir); @@ -285,24 +288,21 @@ connect (m_sync_browser_directory_action, &QAction::triggered, this, &files_dock_widget::do_sync_browser_directory); - gui_settings *settings = rmgr.get_settings (); - // FIXME: what should happen if settings is 0? - // Create the QFileSystemModel starting in the desired directory QDir startup_dir; // take current dir - if (settings->value (fb_restore_last_dir).toBool ()) + if (settings.value (fb_restore_last_dir).toBool ()) { // restore last dir from previous session QStringList last_dirs - = settings->value (fb_mru_list.key).toStringList (); + = settings.value (fb_mru_list.key).toStringList (); if (last_dirs.length () > 0) startup_dir = QDir (last_dirs.at (0)); // last dir in previous session } - else if (! settings->value (fb_startup_dir).toString ().isEmpty ()) + else if (! settings.value (fb_startup_dir).toString ().isEmpty ()) { // do not restore but there is a startup dir configured - startup_dir = QDir (settings->value (fb_startup_dir.key).toString ()); + startup_dir = QDir (settings.value (fb_startup_dir.key).toString ()); } if (! startup_dir.exists ()) @@ -349,14 +349,14 @@ // get sort column and order as well as column state (order and width) m_file_tree_view->sortByColumn - (settings->value (fb_sort_column).toInt (), - static_cast (settings->value (fb_sort_order).toUInt ())); + (settings.value (fb_sort_column).toInt (), + static_cast (settings.value (fb_sort_order).toUInt ())); // FIXME: use value instead of static cast after // dropping support of Qt 5.4 - if (settings->contains (fb_column_state.key)) + if (settings.contains (fb_column_state.key)) m_file_tree_view->header ()->restoreState - (settings->value (fb_column_state.key).toByteArray ()); + (settings.value (fb_column_state.key).toByteArray ()); // Set header properties for sorting m_file_tree_view->header ()->setSectionsClickable (true); @@ -364,7 +364,7 @@ m_file_tree_view->header ()->setSortIndicatorShown (true); QStringList mru_dirs = - settings->value (fb_mru_list.key).toStringList (); + settings.value (fb_mru_list.key).toStringList (); m_current_directory->addItems (mru_dirs); m_current_directory->setEditText @@ -430,27 +430,23 @@ void files_dock_widget::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; + gui_settings settings; int sort_column = m_file_tree_view->header ()->sortIndicatorSection (); Qt::SortOrder sort_order = m_file_tree_view->header ()->sortIndicatorOrder (); - settings->setValue (fb_sort_column.key, sort_column); - settings->setValue (fb_sort_order.key, sort_order); - settings->setValue (fb_column_state.key, - m_file_tree_view->header ()->saveState ()); + settings.setValue (fb_sort_column.key, sort_column); + settings.setValue (fb_sort_order.key, sort_order); + settings.setValue (fb_column_state.key, + m_file_tree_view->header ()->saveState ()); QStringList dirs; for (int i=0; i< m_current_directory->count (); i++) { dirs.append (m_current_directory->itemText (i)); } - settings->setValue (fb_mru_list.key, dirs); + settings.setValue (fb_mru_list.key, dirs); - settings->sync (); + settings.sync (); octave_dock_widget::save_settings (); @@ -534,9 +530,10 @@ QString abs_fname = fileInfo.absoluteFilePath (); QString suffix = fileInfo.suffix ().toLower (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString ext = settings->value (fb_txt_file_ext).toString (); + + gui_settings settings; + + QString ext = settings.value (fb_txt_file_ext).toString (); #if defined (HAVE_QT_SPLITBEHAVIOR_ENUM) QStringList extensions = ext.split (";", Qt::SkipEmptyParts); #else @@ -565,13 +562,12 @@ void files_dock_widget::toggle_header (int col) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; QString key = m_columns_shown_keys.at (col); - bool shown = settings->value (key, false).toBool (); - settings->setValue (key, ! shown); - settings->sync (); + bool shown = settings.value (key, false).toBool (); + settings.setValue (key, ! shown); + settings.sync (); switch (col) { @@ -584,7 +580,7 @@ case 3: case 4: // other actions depending on new settings - notice_settings (settings); + notice_settings (); break; } } @@ -597,8 +593,7 @@ delete m_sig_mapper; m_sig_mapper = new QSignalMapper (this); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; for (int i = 0; i < m_columns_shown.size (); i++) { @@ -607,8 +602,8 @@ m_sig_mapper->setMapping (action, i); action->setCheckable (true); action->setChecked - (settings->value (m_columns_shown_keys.at (i), - m_columns_shown_defs.at (i)).toBool ()); + (settings.value (m_columns_shown_keys.at (i), + m_columns_shown_defs.at (i)).toBool ()); } // FIXME: We could use @@ -655,10 +650,10 @@ | QItemSelectionModel::Rows); } - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; // construct the context menu depending on item - menu.addAction (rmgr.icon ("document-open"), tr ("Open"), + menu.addAction (settings.icon ("document-open"), tr ("Open"), this, &files_dock_widget::contextmenu_open); if (info.isDir ()) @@ -675,7 +670,7 @@ this, &files_dock_widget::contextmenu_copy_selection); if (info.isFile () && info.suffix () == "m") - menu.addAction (rmgr.icon ("media-playback-start"), tr ("Run"), + menu.addAction (settings.icon ("media-playback-start"), tr ("Run"), this, &files_dock_widget::contextmenu_run); if (info.isFile ()) @@ -685,7 +680,7 @@ if (info.isDir ()) { menu.addSeparator (); - menu.addAction (rmgr.icon ("go-first"), tr ("Set Current Directory"), + menu.addAction (settings.icon ("go-first"), tr ("Set Current Directory"), this, &files_dock_widget::contextmenu_setcurrentdir); QMenu *add_path_menu = menu.addMenu (tr ("Add to Path")); @@ -704,21 +699,21 @@ menu.addSeparator (); - menu.addAction (rmgr.icon ("edit-find"), tr ("Find Files..."), + menu.addAction (settings.icon ("edit-find"), tr ("Find Files..."), this, &files_dock_widget::contextmenu_findfiles); } menu.addSeparator (); menu.addAction (m_rename_action); - menu.addAction (rmgr.icon ("edit-delete"), tr ("Delete..."), + menu.addAction (settings.icon ("edit-delete"), tr ("Delete..."), this, &files_dock_widget::contextmenu_delete); if (info.isDir ()) { menu.addSeparator (); - menu.addAction (rmgr.icon ("document-new"), tr ("New File..."), + menu.addAction (settings.icon ("document-new"), tr ("New File..."), this, &files_dock_widget::contextmenu_newfile); - menu.addAction (rmgr.icon ("folder-new"), tr ("New Directory..."), + menu.addAction (settings.icon ("folder-new"), tr ("New Directory..."), this, &files_dock_widget::contextmenu_newdir); } @@ -1007,11 +1002,13 @@ } } - void files_dock_widget::notice_settings (const gui_settings *settings) + void files_dock_widget::notice_settings (void) { + gui_settings settings; + // QSettings pointer is checked before emitting. - int size_idx = settings->value (global_icon_size).toInt (); + int size_idx = settings.value (global_icon_size).toInt (); size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 QStyle *st = style (); @@ -1021,22 +1018,22 @@ // filenames are always shown, other columns can be hidden by settings for (int i = 0; i < 3; i++) m_file_tree_view->setColumnHidden (i + 1, - ! settings->value (m_columns_shown_keys.at (i),false).toBool ()); + ! settings.value (m_columns_shown_keys.at (i),false).toBool ()); QDir::Filters current_filter = m_file_system_model->filter (); - if (settings->value (m_columns_shown_keys.at (3), false).toBool ()) + if (settings.value (m_columns_shown_keys.at (3), false).toBool ()) m_file_system_model->setFilter (current_filter | QDir::Hidden); else m_file_system_model->setFilter (current_filter & (~QDir::Hidden)); m_file_tree_view->setAlternatingRowColors - (settings->value (m_columns_shown_keys.at (4),true).toBool ()); + (settings.value (m_columns_shown_keys.at (4),true).toBool ()); m_file_tree_view->setModel (m_file_system_model); // enable the buttons to sync octave/browser dir // only if this is not done by default m_sync_octave_dir - = settings->value (fb_sync_octdir).toBool (); + = settings.value (fb_sync_octdir).toBool (); m_sync_octave_directory_action->setEnabled (! m_sync_octave_dir); m_sync_browser_directory_action->setEnabled (! m_sync_octave_dir); @@ -1064,9 +1061,10 @@ { // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = QFileDialog::ShowDirsOnly; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts |= QFileDialog::DontUseNativeDialog; QString dir = QFileDialog::getExistingDirectory (this, diff -r 9089bd969b37 -r bd9da634f00d libgui/src/files-dock-widget.h --- a/libgui/src/files-dock-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/files-dock-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -131,7 +131,7 @@ //! Tells the widget to react on changed settings. - void notice_settings (const gui_settings *settings); + void notice_settings (void); void save_settings (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/find-files-dialog.cc --- a/libgui/src/find-files-dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/find-files-dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -49,17 +49,17 @@ #include "find-files-model.h" #include "gui-preferences-global.h" #include "gui-preferences-ff.h" -#include "octave-qobject.h" +#include "gui-settings.h" namespace octave { - find_files_dialog::find_files_dialog (QWidget *p, base_qobject& oct_qobj) - : QDialog (p), m_octave_qobj (oct_qobj) + find_files_dialog::find_files_dialog (QWidget *p) + : QDialog (p) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; setWindowTitle (tr ("Find Files")); - setWindowIcon (rmgr.icon ("edit-find")); + setWindowIcon (settings.icon ("edit-find")); m_dir_iterator = nullptr; @@ -67,20 +67,18 @@ connect (m_timer, &QTimer::timeout, this, &find_files_dialog::look_for_files); - gui_settings *settings = rmgr.get_settings (); - QLabel *file_name_label = new QLabel (tr ("Named:")); m_file_name_edit = new QLineEdit; m_file_name_edit->setToolTip (tr ("Enter the filename search expression")); - m_file_name_edit->setText (settings->value (ff_file_name).toString ()); + m_file_name_edit->setText (settings.value (ff_file_name).toString ()); file_name_label->setBuddy (m_file_name_edit); QLabel *start_dir_label = new QLabel (tr ("Start in:")); m_start_dir_edit = new QLineEdit; - m_start_dir_edit->setText (settings->value (ff_start_dir.key, - QDir::currentPath ()).toString ()); + m_start_dir_edit->setText (settings.value (ff_start_dir.key, + QDir::currentPath ()).toString ()); m_start_dir_edit->setToolTip (tr ("Enter the start directory")); start_dir_label->setBuddy (m_start_dir_edit); @@ -90,27 +88,27 @@ this, &find_files_dialog::browse_folders); m_recurse_dirs_check = new QCheckBox (tr ("Search subdirectories")); - m_recurse_dirs_check->setChecked (settings->value (ff_recurse_dirs).toBool ()); + m_recurse_dirs_check->setChecked (settings.value (ff_recurse_dirs).toBool ()); m_recurse_dirs_check->setToolTip (tr ("Search recursively through directories for matching files")); m_include_dirs_check = new QCheckBox (tr ("Include directory names")); - m_include_dirs_check->setChecked (settings->value (ff_include_dirs).toBool ()); + m_include_dirs_check->setChecked (settings.value (ff_include_dirs).toBool ()); m_include_dirs_check->setToolTip (tr ("Include matching directories in search results")); m_name_case_check = new QCheckBox (tr ("Name case insensitive")); - m_name_case_check->setChecked (settings->value (ff_name_case).toBool ()); + m_name_case_check->setChecked (settings.value (ff_name_case).toBool ()); m_name_case_check->setToolTip (tr ("Set matching name is case insensitive")); m_contains_text_check = new QCheckBox (tr ("Contains text:")); m_contains_text_check->setToolTip (tr ("Enter the file content search expression")); - m_contains_text_check->setChecked (settings->value (ff_check_text).toBool ()); + m_contains_text_check->setChecked (settings.value (ff_check_text).toBool ()); m_contains_text_edit = new QLineEdit (); m_contains_text_edit->setToolTip (tr ("Text to match")); - m_contains_text_edit->setText (settings->value (ff_contains_text).toString ()); + m_contains_text_edit->setText (settings.value (ff_contains_text).toString ()); m_content_case_check = new QCheckBox (tr ("Text case insensitive")); - m_content_case_check->setChecked (settings->value (ff_content_case).toBool ()); + m_content_case_check->setChecked (settings.value (ff_content_case).toBool ()); m_content_case_check->setToolTip (tr ("Set text content is case insensitive")); find_files_model *model = new find_files_model (this); @@ -124,13 +122,13 @@ m_file_list->setAlternatingRowColors (true); m_file_list->setToolTip (tr ("Search results")); m_file_list->setSortingEnabled (true); - m_file_list->horizontalHeader ()->restoreState (settings->value (ff_column_state.key).toByteArray ()); + m_file_list->horizontalHeader ()->restoreState (settings.value (ff_column_state.key).toByteArray ()); m_file_list->horizontalHeader ()->setSortIndicatorShown (true); m_file_list->horizontalHeader ()->setSectionsClickable (true); m_file_list->horizontalHeader ()->setStretchLastSection (true); - m_file_list->sortByColumn (settings->value (ff_sort_files_by_column).toInt (), + m_file_list->sortByColumn (settings.value (ff_sort_files_by_column).toInt (), static_cast - (settings->value (ff_sort_files_by_order).toUInt ())); + (settings.value (ff_sort_files_by_order).toUInt ())); // FIXME: use value instead of static cast after // dropping support of Qt 5.4 @@ -209,32 +207,28 @@ void find_files_dialog::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; + gui_settings settings; int sort_column = m_file_list->horizontalHeader ()->sortIndicatorSection (); Qt::SortOrder sort_order = m_file_list->horizontalHeader ()->sortIndicatorOrder (); - settings->setValue (ff_sort_files_by_column.key, sort_column); - settings->setValue (ff_sort_files_by_order.key, sort_order); - settings->setValue (ff_column_state.key, m_file_list->horizontalHeader ()->saveState ()); + settings.setValue (ff_sort_files_by_column.key, sort_column); + settings.setValue (ff_sort_files_by_order.key, sort_order); + settings.setValue (ff_column_state.key, m_file_list->horizontalHeader ()->saveState ()); - settings->setValue (ff_file_name.key, m_file_name_edit->text ()); + settings.setValue (ff_file_name.key, m_file_name_edit->text ()); - settings->setValue (ff_start_dir.key, m_start_dir_edit->text ()); + settings.setValue (ff_start_dir.key, m_start_dir_edit->text ()); - settings->setValue (ff_recurse_dirs.key, m_recurse_dirs_check->text ()); - settings->setValue (ff_include_dirs.key, m_include_dirs_check->text ()); - settings->setValue (ff_name_case.key, m_name_case_check->text ()); + settings.setValue (ff_recurse_dirs.key, m_recurse_dirs_check->text ()); + settings.setValue (ff_include_dirs.key, m_include_dirs_check->text ()); + settings.setValue (ff_name_case.key, m_name_case_check->text ()); - settings->setValue (ff_contains_text.key, m_contains_text_edit->text ()); - settings->setValue (ff_check_text.key, m_contains_text_check->isChecked ()); - settings->setValue (ff_content_case.key, m_content_case_check->isChecked ()); + settings.setValue (ff_contains_text.key, m_contains_text_edit->text ()); + settings.setValue (ff_check_text.key, m_contains_text_check->isChecked ()); + settings.setValue (ff_content_case.key, m_content_case_check->isChecked ()); - settings->sync (); + settings.sync (); } void find_files_dialog::set_search_dir (const QString& dir) @@ -311,10 +305,12 @@ void find_files_dialog::browse_folders (void) { int opts = 0; // No options by default. + // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; QString dir = diff -r 9089bd969b37 -r bd9da634f00d libgui/src/find-files-dialog.h --- a/libgui/src/find-files-dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/find-files-dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -39,15 +39,13 @@ namespace octave { - class base_qobject; - class find_files_dialog : public QDialog { Q_OBJECT public: - find_files_dialog (QWidget *parent, base_qobject& oct_qobj); + find_files_dialog (QWidget *parent); virtual ~find_files_dialog (void); @@ -75,8 +73,6 @@ bool is_match (const QFileInfo& info); - base_qobject& m_octave_qobj; - QLineEdit *m_start_dir_edit; QLineEdit *m_file_name_edit; QPushButton *m_stop_button; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/graphics-init.cc --- a/libgui/src/graphics-init.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/graphics-init.cc Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ #include #include "graphics-init.h" -#include "octave-qobject.h" #include "qt-graphics-toolkit.h" #include "QtHandlesUtils.h" @@ -42,7 +41,7 @@ namespace octave { - void graphics_init (interpreter& interp, base_qobject& oct_qobj) + void graphics_init (interpreter& interp) { #if defined (HAVE_QT_GRAPHICS) @@ -54,7 +53,7 @@ gh_mgr.enable_event_processing (true); - qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp, oct_qobj); + qt_graphics_toolkit *qt_gtk = new qt_graphics_toolkit (interp); if (QThread::currentThread () != QApplication::instance ()->thread ()) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/graphics-init.h --- a/libgui/src/graphics-init.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/graphics-init.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,9 +34,7 @@ { class interpreter; - class base_qobject; - - extern void graphics_init (interpreter& interp, base_qobject& oct_qobj); + extern void graphics_init (interpreter& interp); } #endif diff -r 9089bd969b37 -r bd9da634f00d libgui/src/gui-preferences-global.h --- a/libgui/src/gui-preferences-global.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/gui-preferences-global.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,6 +34,9 @@ // Global preferences +const gui_pref +global_skip_welcome_wizard ("global_skip_welcome_wizard", false); + // Get the default monospaced font #if defined (Q_OS_WIN) const QString global_font_family = "Courier"; @@ -118,6 +121,9 @@ }; const gui_pref +global_icon_fallbacks ("icon_fallbacks", QVariant (QStringList ())); + +const gui_pref global_status_bar ("show_status_bar", QVariant (true)); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/gui-preferences.h diff -r 9089bd969b37 -r bd9da634f00d libgui/src/gui-settings.cc --- a/libgui/src/gui-settings.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/gui-settings.cc Tue Dec 06 15:17:16 2022 -0500 @@ -27,13 +27,37 @@ # include "config.h" #endif +#include + #include +#include +#include +#include +#include +#include #include +#include +#include +#include "gui-preferences-cs.h" +#include "gui-preferences-global.h" #include "gui-settings.h" +#include "oct-env.h" + namespace octave { + QString gui_settings::file_name (void) const + { + return fileName (); + } + + QString gui_settings::directory_name (void) const + { + QFileInfo sfile (fileName ()); + + return sfile.absolutePath (); + } QColor gui_settings::get_color_value (const QVariant& def, int mode) const { @@ -109,4 +133,219 @@ return key_seq; } + void gui_settings::config_icon_theme (void) + { + int theme_index; + + if (contains (global_icon_theme_index.key)) + theme_index = value (global_icon_theme_index).toInt (); + else + { + // New pref does not exist. Use old if required. Add new and + // remove deprecated key. + + if (value (global_icon_theme).toBool ()) + theme_index = ICON_THEME_SYSTEM; + else + theme_index = ICON_THEME_OCTAVE; + + setValue (global_icon_theme_index.key, theme_index); + remove (global_icon_theme.key); + } + + QIcon::setThemeName (global_all_icon_themes.at (theme_index)); + + QStringList icon_fallbacks; + + // Set the required fallback search paths. + + switch (theme_index) + { + case ICON_THEME_SYSTEM: + icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); + icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); + break; + case ICON_THEME_TANGO: + icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); + break; + case ICON_THEME_OCTAVE: + icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); + break; + } + + icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS); + + setValue (global_icon_fallbacks.key, icon_fallbacks); + } + + QIcon gui_settings::icon (const QString& icon_name, bool octave_only, + const QString& icon_alt_name) + { + if (octave_only) + return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png"); + + if (QIcon::hasThemeIcon (icon_name)) + return QIcon (QIcon::fromTheme (icon_name)); + else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name)) + return QIcon (QIcon::fromTheme (icon_alt_name)); + + QStringList icon_fallbacks + = value (global_icon_fallbacks.key).toStringList (); + + for (int i = 0; i < icon_fallbacks.length (); i++ ) + { + QString icon_file (icon_fallbacks.at (i) + icon_name + ".png"); + if (QFile (icon_file).exists ()) + return QIcon (icon_file); + } + + //QIcon::setThemeName (current_theme); + return QIcon (); + } + + QString gui_settings::get_default_font_family (void) + { + QString default_family; + + // Get all available fixed width fonts via a font combobox + QFontComboBox font_combo_box; + font_combo_box.setFontFilters (QFontComboBox::MonospacedFonts); + QStringList fonts; + + for (int index = 0; index < font_combo_box.count(); index++) + fonts << font_combo_box.itemText(index); + +#if defined (Q_OS_MAC) + // Use hard coded default on macOS, since selection of fixed width + // default font is unreliable (see bug #59128). + // Test for macOS default fixed width font + if (fonts.contains (global_mono_font.def.toString ())) + default_family = global_mono_font.def.toString (); +#endif + + // If default font is still empty (on all other platforms or + // if macOS default font is not available): use QFontDatabase + if (default_family.isEmpty ()) + { + // Get the system's default monospaced font + QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont); + default_family = fixed_font.defaultFamily (); + + // Since this might be unreliable, test all available fixed width fonts + if (! fonts.contains (default_family)) + { + // Font returned by QFontDatabase is not in fixed fonts list. + // Fallback: take first from this list + default_family = fonts[0]; + } + } + + // Test env variable which has preference + std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT"); + if (! env_default_family.empty ()) + default_family = QString::fromStdString (env_default_family); + + return default_family; + } + + QStringList gui_settings::get_default_font (void) + { + QString default_family = get_default_font_family (); + + // determine the fefault font size of the system + // FIXME: QApplication::font () does not return the monospace font, + // but the size should be probably near to the monospace font + QFont font = QApplication::font (); + + int font_size = font.pointSize (); + if (font_size == -1) + font_size = static_cast (std::floor(font.pointSizeF ())); + + // check for valid font size, otherwise take default 10 + QString default_font_size = "10"; + if (font_size > 0) + default_font_size = QString::number (font_size); + + std::string env_default_font_size + = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE"); + + if (! env_default_font_size.empty ()) + default_font_size = QString::fromStdString (env_default_font_size); + + QStringList result; + result << default_family; + result << default_font_size; + return result; + } + + void gui_settings::reload (void) + { + // Declare some empty options, which may be set at first startup for + // writing them into the newly created settings file + QString custom_editor; + QStringList def_font; + + // Check whether the settings file does not yet exist + if (! QFile::exists (file_name ())) + { + // Get the default font (for terminal) + def_font = get_default_font (); + + // Get a custom editor defined as env variable + std::string env_default_editor + = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR"); + + if (! env_default_editor.empty ()) + custom_editor = QString::fromStdString (env_default_editor); + } + + check (); + + // Write some settings that were dynamically determined at first startup + + // Custom editor + if (! custom_editor.isEmpty ()) + setValue (global_custom_editor.key, custom_editor); + + // Default monospace font for the terminal + if (def_font.count () > 1) + { + setValue (cs_font.key, def_font[0]); + setValue (cs_font_size.key, def_font[1].toInt ()); + } + + // Write the default monospace font into the settings for later use by + // console and editor as fallbacks of their font preferences. + setValue (global_mono_font.key, get_default_font_family ()); + } + + void gui_settings::check (void) + { + if (status () == QSettings::NoError) + { + // Test usability (force file to be really created) + setValue ("dummy", 0); + sync (); + } + + if (! (QFile::exists (file_name ()) + && isWritable () + && status () == QSettings::NoError)) + { + QString msg + = QString (QT_TR_NOOP ("Error %1 creating the settings file\n%2\n" + "Make sure you have read and write permissions to\n%3\n\n" + "Octave GUI must be closed now.")); + + QMessageBox::critical (nullptr, + QString (QT_TR_NOOP ("Octave Critical Error")), + msg.arg (status ()) + .arg (file_name ()) + .arg (directory_name ())); + + exit (1); + } + else + remove ("dummy"); // Remove test entry + } } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/gui-settings.h --- a/libgui/src/gui-settings.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/gui-settings.h Tue Dec 06 15:17:16 2022 -0500 @@ -26,6 +26,8 @@ #if ! defined (octave_gui_settings_h) #define octave_gui_settings_h 1 +#include +#include #include #include "gui-preferences.h" @@ -38,6 +40,13 @@ public: + // Location, name, and format of settings file determined by + // settings in qt_application class construtor. + + gui_settings (QObject *parent = nullptr) + : QSettings (parent) + { } + gui_settings (const QString& file_name, QSettings::Format format, QObject *parent = nullptr) : QSettings (file_name, format, parent) @@ -58,6 +67,10 @@ ~gui_settings (void) = default; + QString file_name (void) const; + + QString directory_name (void) const; + using QSettings::value; QVariant value (const gui_pref& pref) const @@ -119,6 +132,30 @@ QKeySequence sc_def_value (const sc_pref& pref) const; + // config_icon_theme, icon, get_default_font_family, + // get_default_font, and possibly reload and check could be global + // functions instead of member functions. But at least for the icon + // function, defining it as a member function means that we can + // create a single gui_settings object and access multiple icon + // objects rather than having to create a separate settings object + // each time that an icon is needed. OTOH, creating the base + // QSettings object is supposed to be fast, so that may not matter. + // Hmm. + + void config_icon_theme (void); + + QIcon icon (const QString& icon_name, bool octave_only = false, + const QString& icon_alt_name = QString ()); + + QString get_default_font_family (void); + + QStringList get_default_font (void); + + void reload (void); + + private: + + void check (void); }; } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/history-dock-widget.cc --- a/libgui/src/history-dock-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/history-dock-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -38,6 +38,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-global.h" #include "gui-preferences-hw.h" +#include "gui-settings.h" #include "history-dock-widget.h" #include "octave-qobject.h" @@ -87,21 +88,17 @@ void history_dock_widget::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (! settings) - return; - - settings->setValue (hw_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (hw_filter_shown.key, m_filter_shown); + settings.setValue (hw_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (hw_filter_shown.key, m_filter_shown); QStringList mru; for (int i = 0; i < m_filter->count (); i++) mru.append (m_filter->itemText (i)); - settings->setValue (hw_mru_list.key, mru); + settings.setValue (hw_mru_list.key, mru); - settings->sync (); + settings.sync (); octave_dock_widget::save_settings (); } @@ -153,13 +150,13 @@ if (index.isValid () && index.column () == 0) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - menu.addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, + menu.addAction (settings.icon ("edit-copy"), tr ("Copy"), this, &history_dock_widget::handle_contextmenu_copy); menu.addAction (tr ("Evaluate"), this, &history_dock_widget::handle_contextmenu_evaluate); - menu.addAction (rmgr.icon ("document-new"), tr ("Create script"), this, + menu.addAction (settings.icon ("document-new"), tr ("Create script"), this, &history_dock_widget::handle_contextmenu_create_script); } if (m_filter_shown) @@ -330,17 +327,15 @@ widget ()->setLayout (hist_layout); // Init state of the filter - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - m_filter_shown - = settings->value (hw_filter_shown).toBool (); + gui_settings settings; + + m_filter_shown = settings.value (hw_filter_shown).toBool (); m_filter_widget->setVisible (m_filter_shown); - m_filter->addItems (settings->value (hw_mru_list).toStringList ()); + m_filter->addItems (settings.value (hw_mru_list).toStringList ()); - bool filter_state - = settings->value (hw_filter_active).toBool (); + bool filter_state = settings.value (hw_filter_active).toBool (); m_filter_checkbox->setChecked (filter_state); filter_activate (filter_state); @@ -359,15 +354,17 @@ m_history_list_view->setTextElideMode (Qt::ElideRight); } - void history_dock_widget::notice_settings (const gui_settings *settings) + void history_dock_widget::notice_settings (void) { + gui_settings settings; + QFont font = QFont (); font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); - font.setFamily (settings->value (cs_font.key, default_font).toString ()); - font.setPointSize (settings->value (cs_font_size).toInt ()); + font.setFamily (settings.value (cs_font.key, default_font).toString ()); + font.setPointSize (settings.value (cs_font_size).toInt ()); m_history_list_view->setFont (font); } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/history-dock-widget.h --- a/libgui/src/history-dock-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/history-dock-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -67,7 +67,7 @@ void append_history (const QString& hist_entry); void clear_history (void); void save_settings (void); - void notice_settings (const gui_settings *); + void notice_settings (void); private slots: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/interpreter-qobject.cc --- a/libgui/src/interpreter-qobject.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/interpreter-qobject.cc Tue Dec 06 15:17:16 2022 -0500 @@ -82,7 +82,7 @@ emit ready (); - graphics_init (interp, m_octave_qobj); + graphics_init (interp); // Start executing commands in the command window. diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/file-editor-interface.h --- a/libgui/src/m-editor/file-editor-interface.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/file-editor-interface.h Tue Dec 06 15:17:16 2022 -0500 @@ -30,7 +30,6 @@ #include #include -#include "gui-settings.h" #include "octave-dock-widget.h" namespace octave @@ -74,7 +73,7 @@ virtual void empty_script (bool, bool) = 0; - virtual void restore_session (gui_settings *) = 0; + virtual void restore_session (void) = 0; virtual void enable_menu_shortcuts (bool enable) = 0; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/file-editor-tab.cc --- a/libgui/src/m-editor/file-editor-tab.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/file-editor-tab.cc Tue Dec 06 15:17:16 2022 -0500 @@ -71,6 +71,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-ed.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "gui-utils.h" #include "marker.h" #include "octave-qobject.h" @@ -266,13 +267,12 @@ connect (this, &file_editor_tab::do_save_file_signal, this, &file_editor_tab::do_save_file); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings) - notice_settings (settings, true); + notice_settings (true); + + gui_settings settings; // encoding, not updated with the settings - m_encoding = settings->value (ed_default_enc.key, "UTF-8").toString (); + m_encoding = settings.value (ed_default_enc.key, "UTF-8").toString (); m_enc_indicator->setText (m_encoding); // no changes in encoding yet m_new_encoding = m_encoding; @@ -713,8 +713,7 @@ { QsciLexer *lexer = m_edit_area->lexer (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; if (m_lexer_apis) { @@ -743,9 +742,9 @@ // get settings which infos are used for octave bool octave_builtins - = settings->value (ed_code_completion_octave_builtins).toBool (); + = settings.value (ed_code_completion_octave_builtins).toBool (); bool octave_functions - = settings->value (ed_code_completion_octave_functions).toBool (); + = settings.value (ed_code_completion_octave_functions).toBool (); QCoreApplication::setApplicationName (tmp_app_name); // Restore name @@ -883,8 +882,9 @@ if (update_apis_only) return; // We are done here - int mode = settings->value (ed_color_mode).toInt (); - rmgr.read_lexer_settings (lexer, settings, mode); + int mode = settings.value (ed_color_mode).toInt (); + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + rmgr.read_lexer_settings (lexer, mode); m_edit_area->setCaretForegroundColor (lexer->color (0)); m_edit_area->setIndentationGuidesForegroundColor (lexer->color (0)); @@ -908,7 +908,7 @@ m_edit_area->setFoldMarginColors (bgm, fgm); QColor current_line_bg - = settings->color_value (ed_highlight_current_line_color, mode); + = settings.color_value (ed_highlight_current_line_color, mode); if (current_line_bg == settings_color_no_change) bgm = interpolate_color (bg, fg, 0.5, 0.1); // It is the "auto" color else @@ -923,7 +923,7 @@ // fix line number width with respect to the font size of the lexer and // set the line numbers font depending on the lexer's font - if (settings->value (ed_show_line_numbers).toBool ()) + if (settings.value (ed_show_line_numbers).toBool ()) { // Line numbers width auto_margin_width (); @@ -932,7 +932,7 @@ QFont line_numbers_font = lexer->defaultFont (); int font_size = line_numbers_font.pointSize (); font_size = font_size - + settings->value (ed_line_numbers_size).toInt (); + + settings.value (ed_line_numbers_size).toInt (); if (font_size < 4) font_size = 4; line_numbers_font.setPointSize (font_size); @@ -1535,20 +1535,19 @@ if (input_str) { bool ok; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; used_comment_str = QInputDialog::getText (this, tr ("Comment selected text"), tr ("Comment string to use:\n"), QLineEdit::Normal, - settings->value (ed_last_comment_str, comment_str.at (0)).toString (), + settings.value (ed_last_comment_str, comment_str.at (0)).toString (), &ok); if ((! ok) || used_comment_str.isEmpty ()) return; // No input, do nothing else - settings->setValue (ed_last_comment_str, used_comment_str); // Store last + settings.setValue (ed_last_comment_str, used_comment_str); // Store last } } else @@ -1824,10 +1823,10 @@ QByteArray text_data = file.readAll (); // remove newline at end of file if we add one again when saving - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (ed_force_newline).toBool ()) + + gui_settings settings; + + if (settings.value (ed_force_newline).toBool ()) { const QByteArray eol_lf = QByteArray (1, 0x0a); const QByteArray eol_cr = QByteArray (1, 0x0d); @@ -1968,10 +1967,10 @@ int count_lf = text.count (eol_lf) - count_crlf; // isolated lf int count_cr = text.count (eol_cr) - count_crlf; // isolated cr - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + QsciScintilla::EolMode eol_mode - = static_cast (settings->value (ed_default_eol_mode).toInt ()); + = static_cast (settings.value (ed_default_eol_mode).toInt ()); int count_max = 0; @@ -2052,12 +2051,11 @@ { update_window_title (false); // window title (no modification) - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; // set the eol mode from the settings or depending on the OS if the entry is // missing in the settings - m_edit_area->setEolMode (static_cast (settings->value (ed_default_eol_mode).toInt ())); + m_edit_area->setEolMode (static_cast (settings.value (ed_default_eol_mode).toInt ())); update_eol_indicator (); @@ -2229,10 +2227,10 @@ m_file_system_watcher.removePath (file_to_save); // Remove trailing white spaces if desired - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (ed_rm_trailing_spaces).toBool ()) + + gui_settings settings; + + if (settings.value (ed_rm_trailing_spaces).toBool ()) { // Replace trailing spaces, make sure edit area is writable, // which is not the case when saving at exit or when closing @@ -2280,7 +2278,7 @@ QApplication::setOverrideCursor (Qt::WaitCursor); out << m_edit_area->text (); - if (settings->value (ed_force_newline).toBool () + if (settings.value (ed_force_newline).toBool () && m_edit_area->text ().length ()) out << m_edit_area->eol_string (); // Add newline if desired @@ -2385,9 +2383,10 @@ fileDialog->setOption (QFileDialog::HideNameFilterDetails, false); // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) { // Qt file dialogs fileDialog->setOption(QFileDialog::DontUseNativeDialog); @@ -2688,16 +2687,15 @@ } } - void file_editor_tab::notice_settings (const gui_settings *settings, bool init) + void file_editor_tab::notice_settings (bool init) { - if (! settings) - return; + gui_settings settings; if (! init) update_lexer_settings (); // code folding - if (settings->value (ed_code_folding).toBool ()) + if (settings.value (ed_code_folding).toBool ()) { m_edit_area->setMarginType (3, QsciScintilla::SymbolMargin); m_edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle, 3); @@ -2708,19 +2706,19 @@ } // status bar - if (settings->value (ed_show_edit_status_bar).toBool ()) + if (settings.value (ed_show_edit_status_bar).toBool ()) m_status_bar->show (); else m_status_bar->hide (); //highlight current line color m_edit_area->setCaretLineVisible - (settings->value (ed_highlight_current_line).toBool ()); + (settings.value (ed_highlight_current_line).toBool ()); // auto completion - bool match_keywords = settings->value + bool match_keywords = settings.value (ed_code_completion_keywords).toBool (); - bool match_document = settings->value + bool match_document = settings.value (ed_code_completion_document).toBool (); QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone; @@ -2734,30 +2732,30 @@ m_edit_area->setAutoCompletionSource (source); m_edit_area->setAutoCompletionReplaceWord - (settings->value (ed_code_completion_replace).toBool ()); + (settings.value (ed_code_completion_replace).toBool ()); m_edit_area->setAutoCompletionCaseSensitivity - (settings->value (ed_code_completion_case).toBool ()); - - if (settings->value (ed_code_completion).toBool ()) + (settings.value (ed_code_completion_case).toBool ()); + + if (settings.value (ed_code_completion).toBool ()) m_edit_area->setAutoCompletionThreshold - (settings->value (ed_code_completion_threshold).toInt ()); + (settings.value (ed_code_completion_threshold).toInt ()); else m_edit_area->setAutoCompletionThreshold (-1); - if (settings->value (ed_show_white_space).toBool ()) - if (settings->value (ed_show_white_space_indent).toBool ()) + if (settings.value (ed_show_white_space).toBool ()) + if (settings.value (ed_show_white_space_indent).toBool ()) m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent); else m_edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible); else m_edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible); - m_edit_area->setEolVisibility (settings->value (ed_show_eol_chars).toBool ()); + m_edit_area->setEolVisibility (settings.value (ed_show_eol_chars).toBool ()); m_save_as_desired_eol = static_cast - (settings->value (ed_default_eol_mode).toInt ()); - - if (settings->value (ed_show_line_numbers).toBool ()) + (settings.value (ed_default_eol_mode).toInt ()); + + if (settings.value (ed_show_line_numbers).toBool ()) { m_edit_area->setMarginLineNumbers (2, true); auto_margin_width (); @@ -2770,46 +2768,46 @@ disconnect (m_edit_area, SIGNAL (linesChanged ()), nullptr, nullptr); } - m_smart_indent = settings->value (ed_auto_indent).toBool (); + m_smart_indent = settings.value (ed_auto_indent).toBool (); m_edit_area->setAutoIndent (m_smart_indent); m_edit_area->setTabIndents - (settings->value (ed_tab_indents_line).toBool ()); + (settings.value (ed_tab_indents_line).toBool ()); m_edit_area->setBackspaceUnindents - (settings->value (ed_backspace_unindents_line).toBool ()); + (settings.value (ed_backspace_unindents_line).toBool ()); m_edit_area->setIndentationGuides - (settings->value (ed_show_indent_guides).toBool ()); + (settings.value (ed_show_indent_guides).toBool ()); m_edit_area->setIndentationsUseTabs - (settings->value (ed_indent_uses_tabs).toBool ()); + (settings.value (ed_indent_uses_tabs).toBool ()); m_edit_area->setIndentationWidth - (settings->value (ed_indent_width).toInt ()); + (settings.value (ed_indent_width).toInt ()); m_edit_area->setTabWidth - (settings->value (ed_tab_width).toInt ()); + (settings.value (ed_tab_width).toInt ()); m_ind_char_width = 1; if (m_edit_area->indentationsUseTabs ()) m_ind_char_width = m_edit_area->tabWidth (); m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETHSCROLLBAR, - settings->value (ed_show_hscroll_bar).toBool ()); + settings.value (ed_show_hscroll_bar).toBool ()); m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTH,-1); m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETSCROLLWIDTHTRACKING,true); update_window_title (m_edit_area->isModified ()); - m_auto_endif = settings->value (ed_auto_endif).toInt (); + m_auto_endif = settings.value (ed_auto_endif).toInt (); // long line marker - int line_length = settings->value (ed_long_line_column).toInt (); + int line_length = settings.value (ed_long_line_column).toInt (); m_edit_area->setEdgeColumn (line_length); - if (settings->value (ed_long_line_marker).toBool ()) + if (settings.value (ed_long_line_marker).toBool ()) { - if (settings->value (ed_long_line_marker_line).toBool ()) + if (settings.value (ed_long_line_marker_line).toBool ()) m_edit_area->setEdgeMode (QsciScintilla::EdgeLine); else { - if (settings->value (ed_long_line_marker_background) + if (settings.value (ed_long_line_marker_background) .toBool ()) m_edit_area->setEdgeMode (QsciScintilla::EdgeBackground); else @@ -2823,36 +2821,36 @@ m_edit_area->setWrapVisualFlags (QsciScintilla::WrapFlagByBorder); m_edit_area->setWrapIndentMode (QsciScintilla::WrapIndentSame); - if (settings->value (ed_wrap_lines).toBool ()) + if (settings.value (ed_wrap_lines).toBool ()) m_edit_area->setWrapMode (QsciScintilla::WrapWord); else m_edit_area->setWrapMode (QsciScintilla::WrapNone); - if (settings->value (ed_break_lines).toBool ()) + if (settings.value (ed_break_lines).toBool ()) m_line_break = line_length; else m_line_break = 0; m_line_break_comments = - settings->value (ed_break_lines_comments).toBool (); + settings.value (ed_break_lines_comments).toBool (); // highlight all occurrences of a word selected by a double click m_highlight_all_occurrences = - settings->value (ed_highlight_all_occurrences).toBool (); + settings.value (ed_highlight_all_occurrences).toBool (); // reload changed files m_always_reload_changed_files = - settings->value (ed_always_reload_changed_files).toBool (); + settings.value (ed_always_reload_changed_files).toBool (); // Set cursor blinking depending on the settings. // QScintilla ignores the application global settings, so some special // handling is required bool cursor_blinking; - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); if (cursor_blinking) m_edit_area->SendScintilla (QsciScintillaBase::SCI_SETCARETPERIOD, 500); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/file-editor-tab.h --- a/libgui/src/m-editor/file-editor-tab.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/file-editor-tab.h Tue Dec 06 15:17:16 2022 -0500 @@ -36,7 +36,6 @@ #include #include -#include "gui-settings.h" #include "marker.h" #include "octave-qscintilla.h" #include "qt-interpreter-events.h" @@ -138,7 +137,7 @@ Qt::KeyboardModifiers state); // Tells the editor tab to react on changed settings. - void notice_settings (const gui_settings *settings, bool init = false); + void notice_settings (bool init = false); // Change to a different editor tab by identifier tag. void change_editor_state (const QWidget *ID); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/file-editor.cc --- a/libgui/src/m-editor/file-editor.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/file-editor.cc Tue Dec 06 15:17:16 2022 -0500 @@ -50,6 +50,7 @@ #include "gui-preferences-ed.h" #include "gui-preferences-sc.h" #include "gui-preferences-global.h" +#include "gui-settings.h" #include "main-window.h" #include "octave-qobject.h" #include "octave-qtutils.h" @@ -181,10 +182,10 @@ void file_editor::handle_enter_debug_mode (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - QString sc_run = settings->sc_value (sc_edit_run_run_file); - QString sc_cont = settings->sc_value (sc_main_debug_continue); + gui_settings settings; + + QString sc_run = settings.sc_value (sc_edit_run_run_file); + QString sc_cont = settings.sc_value (sc_main_debug_continue); if (sc_run == sc_cont) m_run_action->setShortcut (QKeySequence ()); // prevent ambiguous shortcuts @@ -265,10 +266,10 @@ return; // not yet ready but got visibility changed signals } - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (global_use_custom_editor.key, - global_use_custom_editor.def).toBool ()) + gui_settings settings; + + if (settings.value (global_use_custom_editor.key, + global_use_custom_editor.def).toBool ()) return; // do not open an empty script in the external editor bool real_visible; @@ -318,27 +319,29 @@ request_new_file (""); } - void file_editor::restore_session (gui_settings *settings) + void file_editor::restore_session (void) { + gui_settings settings; + //restore previous session - if (! settings->value (ed_restore_session).toBool ()) + if (! settings.value (ed_restore_session).toBool ()) return; // get the data from the settings file QStringList sessionFileNames - = settings->value (ed_session_names).toStringList (); + = settings.value (ed_session_names).toStringList (); QStringList session_encodings - = settings->value (ed_session_enc).toStringList (); + = settings.value (ed_session_enc).toStringList (); QStringList session_index - = settings->value (ed_session_ind).toStringList (); + = settings.value (ed_session_ind).toStringList (); QStringList session_lines - = settings->value (ed_session_lines).toStringList (); + = settings.value (ed_session_lines).toStringList (); QStringList session_bookmarks - = settings->value (ed_session_bookmarks).toStringList (); + = settings.value (ed_session_bookmarks).toStringList (); // fill a list of the struct and sort it (depending on index) QList s_data; @@ -440,8 +443,7 @@ // together with encoding and the tab index void file_editor::save_session (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; QStringList fetFileNames; QStringList fet_encodings; @@ -473,12 +475,13 @@ } } - settings->setValue (ed_session_names.key, fetFileNames); - settings->setValue (ed_session_enc.key, fet_encodings); - settings->setValue (ed_session_ind.key, fet_index); - settings->setValue (ed_session_lines.key, fet_lines); - settings->setValue (ed_session_bookmarks.key, fet_bookmarks); - settings->sync (); + settings.setValue (ed_session_names.key, fetFileNames); + settings.setValue (ed_session_enc.key, fet_encodings); + settings.setValue (ed_session_ind.key, fet_index); + settings.setValue (ed_session_lines.key, fet_lines); + settings.setValue (ed_session_bookmarks.key, fet_bookmarks); + + settings.sync (); } bool file_editor::check_closing (void) @@ -901,9 +904,9 @@ m_find_dialog->close (); if (isFloating ()) - m_find_dialog = new find_dialog (m_octave_qobj, this, this); + m_find_dialog = new find_dialog (this, this); else - m_find_dialog = new find_dialog (m_octave_qobj, this, parentWidget ()); + m_find_dialog = new find_dialog (this, parentWidget ()); // Add required actions m_find_dialog->addAction (m_find_next_action); @@ -974,7 +977,7 @@ QObject *fileEditorTab = sender (); if (fileEditorTab) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; for (int i = 0; i < m_tab_widget->count (); i++) { @@ -987,7 +990,7 @@ m_current_tab_modified = modified; if (modified) - m_tab_widget->setTabIcon (i, rmgr.icon ("document-save")); + m_tab_widget->setTabIcon (i, settings.icon ("document-save")); else m_tab_widget->setTabIcon (i, QIcon ()); } @@ -1273,9 +1276,11 @@ m_tmp_closed_files.clear (); } - void file_editor::notice_settings (const gui_settings *settings) + void file_editor::notice_settings (void) { - int size_idx = settings->value (global_icon_size).toInt (); + gui_settings settings; + + int size_idx = settings.value (global_icon_size).toInt (); size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 QStyle *st = style (); @@ -1284,8 +1289,8 @@ // Tab position and rotation QTabWidget::TabPosition pos - = static_cast (settings->value (ed_tab_position).toInt ()); - bool rotated = settings->value (ed_tabs_rotated).toBool (); + = static_cast (settings.value (ed_tab_position).toInt ()); + bool rotated = settings.value (ed_tabs_rotated).toBool (); m_tab_widget->setTabPosition (pos); @@ -1308,7 +1313,7 @@ height = is; // Calculate possibly limited width and set the elide mode - int chars = settings->value (ed_tabs_max_width).toInt (); + int chars = settings.value (ed_tabs_max_width).toInt (); int width = 9999; if (chars > 0) width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth (); @@ -1349,23 +1354,23 @@ m_tab_widget->setStyleSheet (style_sheet); bool show_it; - show_it = settings->value (ed_show_line_numbers).toBool (); + show_it = settings.value (ed_show_line_numbers).toBool (); m_show_linenum_action->setChecked (show_it); - show_it = settings->value (ed_show_white_space).toBool (); + show_it = settings.value (ed_show_white_space).toBool (); m_show_whitespace_action->setChecked (show_it); - show_it = settings->value (ed_show_eol_chars).toBool (); + show_it = settings.value (ed_show_eol_chars).toBool (); m_show_eol_action->setChecked (show_it); - show_it = settings->value (ed_show_indent_guides).toBool (); + show_it = settings.value (ed_show_indent_guides).toBool (); m_show_indguide_action->setChecked (show_it); - show_it = settings->value (ed_long_line_marker).toBool (); + show_it = settings.value (ed_long_line_marker).toBool (); m_show_longline_action->setChecked (show_it); - show_it = settings->value (ed_show_toolbar).toBool (); + show_it = settings.value (ed_show_toolbar).toBool (); m_show_toolbar_action->setChecked (show_it); m_tool_bar->setVisible (show_it); - show_it = settings->value (ed_show_edit_status_bar).toBool (); + show_it = settings.value (ed_show_edit_status_bar).toBool (); m_show_statusbar_action->setChecked (show_it); - show_it = settings->value (ed_show_hscroll_bar).toBool (); + show_it = settings.value (ed_show_hscroll_bar).toBool (); m_show_hscrollbar_action->setChecked (show_it); set_shortcuts (); @@ -1375,7 +1380,7 @@ m_find_dialog->setWindowIcon (windowIcon ()); // Relay signal to file editor tabs. - emit fetab_settings_changed (settings); + emit fetab_settings_changed (); } void file_editor::set_shortcuts (void) @@ -1483,9 +1488,8 @@ if (m_closed && visible) { m_closed = false; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - restore_session (settings); + + restore_session (); } empty_script (false, visible); @@ -1549,10 +1553,9 @@ const QString& cond, int index, const QString& bookmarks) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_use_custom_editor).toBool ()) + gui_settings settings; + + if (settings.value (global_use_custom_editor).toBool ()) { // Custom editor if (debug_pointer || breakpoint_marker) @@ -1562,8 +1565,7 @@ return; // Custom editor called } - bool show_dbg_file - = settings->value (ed_show_dbg_file).toBool (); + bool show_dbg_file = settings.value (ed_show_dbg_file).toBool (); if (openFileName.isEmpty ()) { @@ -1677,7 +1679,7 @@ bool create_file = true; QMessageBox *msgBox; - if (! settings->value (ed_create_new_file).toBool ()) + if (! settings.value (ed_create_new_file).toBool ()) { msgBox = new QMessageBox (QMessageBox::Question, tr ("Octave Editor"), @@ -1849,9 +1851,9 @@ // handler for the close event void file_editor::closeEvent (QCloseEvent *e) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (ed_hiding_closes_files).toBool ()) + gui_settings settings; + + if (settings.value (ed_hiding_closes_files).toBool ()) { if (check_closing ()) { @@ -1931,12 +1933,12 @@ m_tab_widget = new file_editor_tab_widget (editor_widget, this); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - // the mru-list and an empty array of actions - gui_settings *settings = rmgr.get_settings (); - m_mru_files = settings->value (ed_mru_file_list).toStringList (); - m_mru_files_encodings = settings->value (ed_mru_file_encodings) + + gui_settings settings; + + m_mru_files = settings.value (ed_mru_file_list).toStringList (); + m_mru_files_encodings = settings.value (ed_mru_file_encodings) .toStringList (); if (m_mru_files_encodings.count () != m_mru_files.count ()) @@ -1975,33 +1977,33 @@ m_fileMenu->addSeparator (); m_save_action - = add_action (m_fileMenu, rmgr.icon ("document-save"), + = add_action (m_fileMenu, settings.icon ("document-save"), tr ("&Save File"), SLOT (request_save_file (bool))); m_save_as_action - = add_action (m_fileMenu, rmgr.icon ("document-save-as"), + = add_action (m_fileMenu, settings.icon ("document-save-as"), tr ("Save File &As..."), SLOT (request_save_file_as (bool))); m_fileMenu->addSeparator (); m_close_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), + = add_action (m_fileMenu, settings.icon ("window-close", false), tr ("&Close"), SLOT (request_close_file (bool))); m_close_all_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), + = add_action (m_fileMenu, settings.icon ("window-close", false), tr ("Close All"), SLOT (request_close_all_files (bool))); m_close_others_action - = add_action (m_fileMenu, rmgr.icon ("window-close", false), + = add_action (m_fileMenu, settings.icon ("window-close", false), tr ("Close Other Files"), SLOT (request_close_other_files (bool))); m_fileMenu->addSeparator (); m_print_action - = add_action (m_fileMenu, rmgr.icon ("document-print"), + = add_action (m_fileMenu, settings.icon ("document-print"), tr ("Print..."), SLOT (request_print_file (bool))); // edit menu (undo, copy, paste and select all later via main window) @@ -2009,19 +2011,19 @@ m_edit_menu = add_menu (m_menu_bar, tr ("&Edit")); m_redo_action - = add_action (m_edit_menu, rmgr.icon ("edit-redo"), + = add_action (m_edit_menu, settings.icon ("edit-redo"), tr ("&Redo"), SLOT (request_redo (bool))); m_redo_action->setEnabled (false); m_edit_menu->addSeparator (); m_cut_action - = add_action (m_edit_menu, rmgr.icon ("edit-cut"), + = add_action (m_edit_menu, settings.icon ("edit-cut"), tr ("Cu&t"), SLOT (request_cut (bool))); m_cut_action->setEnabled (false); m_find_action - = add_action (m_edit_menu, rmgr.icon ("edit-find-replace"), + = add_action (m_edit_menu, settings.icon ("edit-find-replace"), tr ("&Find and Replace..."), SLOT (request_find (bool))); m_find_next_action @@ -2173,12 +2175,12 @@ m_edit_menu->addSeparator (); m_preferences_action - = add_action (m_edit_menu, rmgr.icon ("preferences-system"), + = add_action (m_edit_menu, settings.icon ("preferences-system"), tr ("&Preferences..."), SLOT (request_preferences (bool))); m_styles_preferences_action - = add_action (m_edit_menu, rmgr.icon ("preferences-system"), + = add_action (m_edit_menu, settings.icon ("preferences-system"), tr ("&Styles Preferences..."), SLOT (request_styles_preferences (bool))); @@ -2233,16 +2235,16 @@ view_menu->addSeparator (); m_zoom_in_action - = add_action (view_menu, rmgr.icon ("view-zoom-in"), tr ("Zoom &In"), + = add_action (view_menu, settings.icon ("view-zoom-in"), tr ("Zoom &In"), SLOT (zoom_in (bool))); m_zoom_out_action - = add_action (view_menu, rmgr.icon ("view-zoom-out"), tr ("Zoom &Out"), - SLOT (zoom_out (bool))); + = add_action (view_menu, settings.icon ("view-zoom-out"), + tr ("Zoom &Out"), SLOT (zoom_out (bool))); m_zoom_normal_action - = add_action (view_menu, rmgr.icon ("view-zoom-original"), tr ("&Normal Size"), - SLOT (zoom_normal (bool))); + = add_action (view_menu, settings.icon ("view-zoom-original"), + tr ("&Normal Size"), SLOT (zoom_normal (bool))); view_menu->addSeparator (); @@ -2258,22 +2260,22 @@ m_debug_menu = add_menu (m_menu_bar, tr ("&Debug")); m_toggle_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-toggle"), + = add_action (m_debug_menu, settings.icon ("bp-toggle"), tr ("Toggle &Breakpoint"), SLOT (request_toggle_breakpoint (bool))); m_next_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-next"), + = add_action (m_debug_menu, settings.icon ("bp-next"), tr ("&Next Breakpoint"), SLOT (request_next_breakpoint (bool))); m_previous_breakpoint_action - = add_action (m_debug_menu, rmgr.icon ("bp-prev"), + = add_action (m_debug_menu, settings.icon ("bp-prev"), tr ("Pre&vious Breakpoint"), SLOT (request_previous_breakpoint (bool))); m_remove_all_breakpoints_action - = add_action (m_debug_menu, rmgr.icon ("bp-rm-all"), + = add_action (m_debug_menu, settings.icon ("bp-rm-all"), tr ("&Remove All Breakpoints"), SLOT (request_remove_breakpoint (bool))); @@ -2287,7 +2289,7 @@ m_run_action = add_action (_run_menu, - rmgr.icon ("system-run"), + settings.icon ("system-run"), tr ("Save File and Run / Continue"), SLOT (request_run_file (bool))); @@ -2493,7 +2495,7 @@ // Signals from the file_editor or main-win non-trivial operations connect (this, &file_editor::fetab_settings_changed, - f, [=] (const gui_settings *settings) { f->notice_settings (settings); }); + f, [=] () { f->notice_settings (); }); connect (this, &file_editor::fetab_change_request, f, &file_editor_tab::change_editor_state); @@ -2677,21 +2679,22 @@ } // save actual mru-list in settings - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - settings->setValue (ed_mru_file_list.key, m_mru_files); - settings->setValue (ed_mru_file_encodings.key, m_mru_files_encodings); - settings->sync (); + + gui_settings settings; + + settings.setValue (ed_mru_file_list.key, m_mru_files); + settings.setValue (ed_mru_file_encodings.key, m_mru_files_encodings); + + settings.sync (); } bool file_editor::call_custom_editor (const QString& file_name, int line) { // Check if the user wants to use a custom file editor. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_use_custom_editor.key, + + gui_settings settings; + + if (settings.value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()) { // use the external editor interface for handling the call @@ -2709,12 +2712,11 @@ void file_editor::toggle_preference (const gui_pref& preference) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - bool old = settings->value (preference).toBool (); - settings->setValue (preference.key, ! old); - notice_settings (settings); + gui_settings settings; + + bool old = settings.value (preference).toBool (); + settings.setValue (preference.key, ! old); + notice_settings (); } // Function for closing the files in a removed directory diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/file-editor.h --- a/libgui/src/m-editor/file-editor.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/file-editor.h Tue Dec 06 15:17:16 2022 -0500 @@ -124,11 +124,11 @@ void check_actions (void); void empty_script (bool startup, bool visible); - void restore_session (gui_settings *settings); + void restore_session (void); signals: - void fetab_settings_changed (const gui_settings *settings); + void fetab_settings_changed (void); void fetab_change_request (const QWidget *ID); // Save is a ping-pong type of communication void fetab_save_file (const QWidget *ID, const QString& fileName, @@ -287,7 +287,7 @@ void handle_file_renamed (bool load_new = true); // Tells the editor to react on changed settings. - void notice_settings (const gui_settings *settings); + void notice_settings (void); void set_shortcuts (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/find-dialog.cc --- a/libgui/src/m-editor/find-dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/find-dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -84,14 +84,12 @@ #include "gui-preferences-ed.h" #include "gui-utils.h" #include "resource-manager.h" -#include "octave-qobject.h" namespace octave { - find_dialog::find_dialog (base_qobject& oct_qobj, - octave_dock_widget *ed, QWidget *p) - : QDialog (p), m_octave_qobj (oct_qobj), m_editor (ed), - m_in_sel (false), m_sel_beg (-1), m_sel_end (-1) + find_dialog::find_dialog (octave_dock_widget *ed, QWidget *p) + : QDialog (p), m_editor (ed), m_in_sel (false), + m_sel_beg (-1), m_sel_end (-1) { setWindowTitle (tr ("Editor: Find and Replace")); @@ -218,8 +216,7 @@ void find_dialog::save_settings () { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *s = rmgr.get_settings (); + gui_settings settings; // Save position QPoint dlg_pos = pos (); @@ -232,7 +229,7 @@ m_last_position = QPoint (dlg_pos.x (), y); - s->setValue (ed_fdlg_pos.key, m_last_position); + settings.setValue (ed_fdlg_pos.key, m_last_position); // Is current search/replace text in the mru list? mru_update (m_search_line_edit); @@ -242,12 +239,12 @@ QStringList mru; for (int i = 0; i < m_search_line_edit->count (); i++) mru.append (m_search_line_edit->itemText (i)); - s->setValue (ed_fdlg_search.key, mru); + settings.setValue (ed_fdlg_search.key, mru); mru.clear (); for (int i = 0; i < m_replace_line_edit->count (); i++) mru.append (m_replace_line_edit->itemText (i)); - s->setValue (ed_fdlg_replace.key, mru); + settings.setValue (ed_fdlg_replace.key, mru); // Store dialog's options int opts = 0 @@ -259,29 +256,28 @@ + m_whole_words_check_box->isChecked () * FIND_DLG_WORDS + m_backward_check_box->isChecked () * FIND_DLG_BACK + m_search_selection_check_box->isChecked () * FIND_DLG_SEL; - s->setValue (ed_fdlg_opts.key, opts); + settings.setValue (ed_fdlg_opts.key, opts); - s->sync (); + settings.sync (); } void find_dialog::restore_settings (QPoint ed_bottom_right) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *s = rmgr.get_settings (); + gui_settings settings; // Get mru lists for search and replace text - QStringList mru = s->value (ed_fdlg_search.key).toStringList (); + QStringList mru = settings.value (ed_fdlg_search.key).toStringList (); while (mru.length () > m_mru_length) mru.removeLast (); m_search_line_edit->addItems (mru); - mru = s->value (ed_fdlg_replace.key).toStringList (); + mru = settings.value (ed_fdlg_replace.key).toStringList (); while (mru.length () > m_mru_length) mru.removeLast (); m_replace_line_edit->addItems (mru); // Get the dialog's options - int opts = s->value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt (); + int opts = settings.value (ed_fdlg_opts.key, ed_fdlg_opts.def).toInt (); m_extension->setVisible (FIND_DLG_MORE & opts); m_case_check_box->setChecked (FIND_DLG_CASE & opts); @@ -298,7 +294,7 @@ QRect default_geometry (xp, yp, sizeHint ().width (), sizeHint ().height ()); // Last position from settings - m_last_position = s->value (ed_fdlg_pos.key, QPoint (xp, yp)).toPoint (); + m_last_position = settings.value (ed_fdlg_pos.key, QPoint (xp, yp)).toPoint (); QRect last_geometry (m_last_position, QSize (sizeHint ().width (), sizeHint ().height ())); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/find-dialog.h --- a/libgui/src/m-editor/find-dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/find-dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -79,7 +79,6 @@ namespace octave { - class base_qobject; class file_editor; class find_dialog : public QDialog @@ -88,7 +87,7 @@ public: - find_dialog (base_qobject& oct_qobj, octave_dock_widget *ed, QWidget *p); + find_dialog (octave_dock_widget *ed, QWidget *p); //! Set dialog visible or not and storing the new visibility state void set_visible (bool visible); @@ -122,8 +121,6 @@ private: - base_qobject& m_octave_qobj; - //! Save position and the search options in the given settings void save_settings (); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/m-editor/octave-qscintilla.cc --- a/libgui/src/m-editor/octave-qscintilla.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/m-editor/octave-qscintilla.cc Tue Dec 06 15:17:16 2022 -0500 @@ -54,6 +54,7 @@ #include "file-editor-tab.h" #include "gui-preferences-ed.h" +#include "gui-settings.h" // FIXME: hardwired marker numbers? #include "marker.h" #include "octave-qobject.h" @@ -430,20 +431,20 @@ case SCLEX_MATLAB: #endif { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + int comment_string; if (comment) { // The commenting string is requested - if (settings->contains (ed_comment_str.key)) + if (settings.contains (ed_comment_str.key)) // new version (radio buttons) - comment_string = settings->value (ed_comment_str).toInt (); + comment_string = settings.value (ed_comment_str).toInt (); else // old version (combo box) - comment_string = settings->value (ed_comment_str_old.key, - ed_comment_str.def).toInt (); + comment_string = settings.value (ed_comment_str_old.key, + ed_comment_str.def).toInt (); return (QStringList (ed_comment_strings.at (comment_string))); } @@ -452,7 +453,7 @@ QStringList c_str; // The possible uncommenting string(s) are requested - comment_string = settings->value (ed_uncomment_str).toInt (); + comment_string = settings.value (ed_uncomment_str).toInt (); for (int i = 0; i < ed_comment_strings_count; i++) { @@ -908,9 +909,10 @@ }); // Disable opening a file at a breakpoint in case keyboard () is used - gui_settings *settings = rmgr.get_settings (); - bool show_dbg_file = settings->value (ed_show_dbg_file).toBool (); - settings->setValue (ed_show_dbg_file.key, false); + gui_settings settings; + + bool show_dbg_file = settings.value (ed_show_dbg_file).toBool (); + settings.setValue (ed_show_dbg_file.key, false); // Let the interpreter execute the tmp file emit interpreter_event @@ -1035,8 +1037,10 @@ // possible lines from commands at a debug prompt must be // taken into consideration. resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (ed_show_dbg_file.key, show_dbg_file); + gui_settings settings; + + settings.setValue (ed_show_dbg_file.key, show_dbg_file); + rmgr.remove_tmp_file (tmp_file); rmgr.remove_tmp_file (tmp_hist); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/main-window.cc --- a/libgui/src/main-window.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/main-window.cc Tue Dec 06 15:17:16 2022 -0500 @@ -100,7 +100,7 @@ m_file_browser_window (nullptr), m_editor_window (nullptr), m_workspace_window (nullptr), - m_external_editor (new external_editor_interface (this, m_octave_qobj)), + m_external_editor (new external_editor_interface (this)), m_active_editor (m_external_editor), m_settings_dlg (nullptr), m_find_files_dlg (nullptr), m_set_path_dlg (nullptr), m_clipboard (QApplication::clipboard ()), @@ -111,23 +111,27 @@ { resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - if (rmgr.is_first_run ()) + gui_settings settings; + + if (! settings.value (global_skip_welcome_wizard).toBool ()) { // Before wizard. m_octave_qobj.config_translators (); - welcome_wizard welcomeWizard (m_octave_qobj); + welcome_wizard welcomeWizard; if (welcomeWizard.exec () == QDialog::Rejected) exit (1); + settings.setValue (global_skip_welcome_wizard.key, QVariant (true)); + // Install settings file. - rmgr.reload_settings (); + settings.reload (); } else { // Get settings file. - rmgr.reload_settings (); + settings.reload (); // After settings. m_octave_qobj.config_translators (); @@ -135,7 +139,7 @@ setObjectName (gui_obj_name_main_window); - rmgr.config_icon_theme (); + settings.config_icon_theme (); rmgr.update_network_settings (); @@ -174,24 +178,15 @@ m_default_style = qapp->style ()->objectName (); m_default_palette = qapp->palette (); - gui_settings *settings = rmgr.get_settings (); - bool connect_to_web = true; QDateTime last_checked; int serial = 0; m_active_dock = nullptr; - if (settings) - { - connect_to_web - = settings->value (nr_allow_connection).toBool (); - - last_checked - = settings->value (nr_last_time).toDateTime (); - - serial = settings->value (nr_last_news).toInt (); - m_default_encoding = settings->value (ed_default_enc).toString (); - } + connect_to_web = settings.value (nr_allow_connection).toBool (); + last_checked = settings.value (nr_last_time).toDateTime (); + serial = settings.value (nr_last_news).toInt (); + m_default_encoding = settings.value (ed_default_enc).toString (); QDateTime current = QDateTime::currentDateTime (); QDateTime one_day_ago = current.addDays (-1); @@ -508,11 +503,10 @@ { bool closenow = true; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings->value (global_prompt_to_exit.key, - global_prompt_to_exit.def).toBool ()) + gui_settings settings; + + if (settings.value (global_prompt_to_exit.key, + global_prompt_to_exit.def).toBool ()) { int ans = QMessageBox::question (this, tr ("Octave"), tr ("Are you sure you want to exit Octave?"), @@ -648,11 +642,7 @@ void main_window::request_reload_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (settings) - emit settings_changed (settings); + emit settings_changed (); } void main_window::report_status_message (const QString& statusMessage) @@ -664,9 +654,10 @@ { // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; QString file @@ -689,9 +680,10 @@ { // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; QString file = file_arg; @@ -904,15 +896,13 @@ QString::fromStdString (message)); } - void main_window::notice_settings (const gui_settings *settings, - bool update_by_worker) + void main_window::notice_settings (bool update_by_worker) { - if (! settings) - return; + gui_settings settings; // Get desired style from preferences or take the default one if // the desired one is not found - QString preferred_style = settings->value (global_style).toString (); + QString preferred_style = settings.value (global_style).toString (); if (preferred_style == global_style.def.toString ()) preferred_style = m_default_style; @@ -938,7 +928,7 @@ } // the widget's icons (when floating) - QString icon_set = settings->value (dw_icon_set).toString (); + QString icon_set = settings.value (dw_icon_set).toString (); QString icon; for (auto *widget : dock_widget_list ()) @@ -954,26 +944,26 @@ } } - int size_idx = settings->value (global_icon_size).toInt (); + int size_idx = settings.value (global_icon_size).toInt (); size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 QStyle *st = style (); int icon_size = st->pixelMetric (global_icon_sizes[size_idx]); m_main_tool_bar->setIconSize (QSize (icon_size, icon_size)); - if (settings->value (global_status_bar).toBool ()) + if (settings.value (global_status_bar).toBool ()) m_status_bar->show (); else m_status_bar->hide (); m_prevent_readline_conflicts - = settings->value (sc_prevent_rl_conflicts).toBool (); + = settings.value (sc_prevent_rl_conflicts).toBool (); m_prevent_readline_conflicts_menu - = settings->value (sc_prevent_rl_conflicts_menu).toBool (); + = settings.value (sc_prevent_rl_conflicts_menu).toBool (); m_suppress_dbg_location - = ! settings->value (cs_dbg_location).toBool (); + = ! settings.value (cs_dbg_location).toBool (); resource_manager& rmgr = m_octave_qobj.get_resource_manager (); rmgr.update_network_settings (); @@ -991,7 +981,7 @@ // Check whether some octave internal preferences have to be updated QString new_default_encoding - = settings->value (ed_default_enc).toString (); + = settings.value (ed_default_enc).toString (); // Do not update internal pref only if a) this update was not initiated // by the worker and b) the pref has really changes if (! update_by_worker && (new_default_encoding != m_default_encoding)) @@ -1003,10 +993,10 @@ // getting the cursor blink preferences from all OS environments bool cursor_blinking; - if (settings->contains (global_cursor_blinking.key)) - cursor_blinking = settings->value (global_cursor_blinking).toBool (); + if (settings.contains (global_cursor_blinking.key)) + cursor_blinking = settings.value (global_cursor_blinking).toBool (); else - cursor_blinking = settings->value (cs_cursor_blinking).toBool (); + cursor_blinking = settings.value (cs_cursor_blinking).toBool (); if (cursor_blinking) QApplication::setCursorFlashTime (1000); // 1000 ms flash time @@ -1084,9 +1074,10 @@ { // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = QFileDialog::ShowDirsOnly; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; QString dir @@ -1339,10 +1330,10 @@ // Open file isn't a file_editor_tab or editor function since the file // might be opened in an external editor. Hence, functionality is here. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; + bool is_internal = m_editor_window - && ! settings->value (global_use_custom_editor.key, + && ! settings.value (global_use_custom_editor.key, global_use_custom_editor.def).toBool (); // Create a NonModal message. @@ -1358,7 +1349,7 @@ fileDialog->setDirectory (m_current_directory_combo_box->itemText (0)); // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. - if (! settings->value (global_use_native_dialogs).toBool ()) + if (! settings.value (global_use_native_dialogs).toBool ()) fileDialog->setOption(QFileDialog::DontUseNativeDialog); connect (fileDialog, &QFileDialog::filesSelected, @@ -1383,9 +1374,10 @@ // editor window or the main window. The latter is chosen, if a custom // editor is used or qscintilla is not available QWidget *p = m_editor_window; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! p || settings->value (global_use_custom_editor.key, + + gui_settings settings; + + if (! p || settings.value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()) p = this; QString new_name = QInputDialog::getText (p, tr ("New Function"), @@ -1397,10 +1389,10 @@ if (new_name.rightRef (2) != ".m") new_name.append (".m"); // check whether new files are created without prompt - if (! settings->value (ed_create_new_file).toBool ()) + if (! settings.value (ed_create_new_file).toBool ()) { // no, so enable this settings and wait for end of new file loading - settings->setValue (ed_create_new_file.key, true); + settings.setValue (ed_create_new_file.key, true); connect (m_editor_window, SIGNAL (file_loaded_signal (void)), this, SLOT (restore_create_file_setting (void))); } @@ -1546,24 +1538,18 @@ void main_window::read_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - { - qDebug ("Error: gui_settings pointer from resource manager is NULL."); - return; - } - - set_window_layout (settings); + gui_settings settings; + + set_window_layout (); // restore the list of the last directories - QStringList curr_dirs = settings->value (mw_dir_list).toStringList (); + QStringList curr_dirs = settings.value (mw_dir_list).toStringList (); for (int i=0; i < curr_dirs.size (); i++) { m_current_directory_combo_box->addItem (curr_dirs.at (i)); } - emit settings_changed (settings); + + emit settings_changed (); } void main_window::init_terminal_size (void) @@ -1571,15 +1557,17 @@ emit init_terminal_size_signal (); } - void main_window::set_window_layout (gui_settings *settings) + void main_window::set_window_layout (void) { + gui_settings settings; + // For resetting from some inconsistent state, first reset layout // without saving or showing it do_reset_windows (true, false); // Restore main window state and geometry from settings file or, in case // of an error (no pref values yet), from the default layout. - if (! restoreGeometry (settings->value (mw_geometry).toByteArray ())) + if (! restoreGeometry (settings.value (mw_geometry).toByteArray ())) { do_reset_windows (true); return; @@ -1608,7 +1596,7 @@ | Qt::WindowCloseButtonHint); } - if (! restoreState (settings->value (mw_state).toByteArray ())) + if (! restoreState (settings.value (mw_state).toByteArray ())) { do_reset_windows (true); return; @@ -1631,9 +1619,9 @@ bool floating = false; bool visible = true; - floating = settings->value + floating = settings.value (dw_is_floating.key.arg (name), dw_is_floating.def).toBool (); - visible = settings->value + visible = settings.value (dw_is_visible.key.arg (name), dw_is_visible.def).toBool (); // If floating, make window from widget. @@ -1643,8 +1631,8 @@ if (visible) { - if (settings->value (dw_is_minimized.key.arg (name), - dw_is_minimized.def).toBool ()) + if (settings.value (dw_is_minimized.key.arg (name), + dw_is_minimized.def).toBool ()) widget->showMinimized (); else widget->setVisible (true); @@ -1668,24 +1656,18 @@ void main_window::write_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings) - { - qDebug ("Error: gui_settings pointer from resource manager is NULL."); - return; - } - - settings->setValue (mw_geometry.key, saveGeometry ()); - settings->setValue (mw_state.key, saveState ()); + gui_settings settings; + + settings.setValue (mw_geometry.key, saveGeometry ()); + settings.setValue (mw_state.key, saveState ()); // write the list of recently used directories QStringList curr_dirs; for (int i=0; icount (); i++) { curr_dirs.append (m_current_directory_combo_box->itemText (i)); } - settings->setValue (mw_dir_list.key, curr_dirs); - settings->sync (); + settings.setValue (mw_dir_list.key, curr_dirs); + settings.sync (); } void main_window::copyClipboard (void) @@ -1751,30 +1733,27 @@ void main_window::handle_octave_ready (void) { // actions after the startup files are executed - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + + gui_settings settings; QDir startup_dir = QDir (); // current octave dir after startup - if (settings) + if (settings.value (global_restore_ov_dir).toBool ()) { - if (settings->value (global_restore_ov_dir).toBool ()) - { - // restore last dir from previous session - QStringList curr_dirs - = settings->value (mw_dir_list).toStringList (); - if (curr_dirs.length () > 0) - startup_dir = QDir (curr_dirs.at (0)); // last dir prev. session - } - else if (! settings->value (global_ov_startup_dir).toString ().isEmpty ()) - { - // do not restore but there is a startup dir configured - startup_dir - = QDir (settings->value (global_ov_startup_dir).toString ()); - } - - update_default_encoding (settings->value (ed_default_enc).toString ()); + // restore last dir from previous session + QStringList curr_dirs + = settings.value (mw_dir_list).toStringList (); + if (curr_dirs.length () > 0) + startup_dir = QDir (curr_dirs.at (0)); // last dir prev. session } + else if (! settings.value (global_ov_startup_dir).toString ().isEmpty ()) + { + // do not restore but there is a startup dir configured + startup_dir + = QDir (settings.value (global_ov_startup_dir).toString ()); + } + + update_default_encoding (settings.value (ed_default_enc).toString ()); if (! startup_dir.exists ()) { @@ -1791,7 +1770,7 @@ // This can not be done when the editor is created because all functions // must be known for the lexer's auto completion information m_editor_window->empty_script (true, false); - m_editor_window->restore_session (settings); + m_editor_window->restore_session (); #endif } @@ -1823,7 +1802,7 @@ if (m_set_path_dlg) // m_set_path_dlg is a guarded pointer! return; - m_set_path_dlg = new set_path_dialog (this, m_octave_qobj); + m_set_path_dlg = new set_path_dialog (this); m_set_path_dlg->setModal (false); m_set_path_dlg->setAttribute (Qt::WA_DeleteOnClose); @@ -1859,7 +1838,7 @@ if (! m_find_files_dlg) { - m_find_files_dlg = new find_files_dialog (this, m_octave_qobj); + m_find_files_dlg = new find_files_dialog (this); connect (m_find_files_dlg, &find_files_dialog::finished, this, &main_window::find_files_finished); @@ -1928,9 +1907,10 @@ void main_window::restore_create_file_setting (void) { // restore the new files creation setting - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (ed_create_new_file.key, false); + + gui_settings settings; + + settings.setValue (ed_create_new_file.key, false); disconnect (m_editor_window, SIGNAL (file_loaded_signal (void)), this, SLOT (restore_create_file_setting (void))); } @@ -2072,8 +2052,9 @@ connect (qApp, &QApplication::focusChanged, this, &main_window::focus_changed); + // Default argument requires wrapper. connect (this, &main_window::settings_changed, - this, [=] (const gui_settings *settings) { notice_settings (settings); }); + this, [=] () { notice_settings (); }); // Connections for signals from the interpreter thread where the slot // should be executed by the gui thread @@ -2216,10 +2197,10 @@ construct_new_menu (file_menu); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; m_open_action = add_action ( - file_menu, rmgr.icon ("document-open"), tr ("Open..."), + file_menu, settings.icon ("document-open"), tr ("Open..."), SLOT (request_open_file (void)), this); m_open_action->setToolTip (tr ("Open an existing file in editor")); @@ -2261,10 +2242,10 @@ { QMenu *new_menu = p->addMenu (tr ("New")); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; m_new_script_action = add_action ( - new_menu, rmgr.icon ("document-new"), tr ("New Script"), + new_menu, settings.icon ("document-new"), tr ("New Script"), SLOT (request_new_script (void)), this); m_new_function_action = add_action ( @@ -2282,20 +2263,21 @@ QKeySequence ctrl_shift = Qt::ControlModifier + Qt::ShiftModifier; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; + m_undo_action - = edit_menu->addAction (rmgr.icon ("edit-undo"), tr ("Undo")); + = edit_menu->addAction (settings.icon ("edit-undo"), tr ("Undo")); m_undo_action->setShortcutContext (Qt::ApplicationShortcut); edit_menu->addSeparator (); m_copy_action - = edit_menu->addAction (rmgr.icon ("edit-copy"), tr ("Copy"), this, + = edit_menu->addAction (settings.icon ("edit-copy"), tr ("Copy"), this, &main_window::copyClipboard); m_copy_action->setShortcutContext (Qt::ApplicationShortcut); m_paste_action - = edit_menu->addAction (rmgr.icon ("edit-paste"), tr ("Paste"), this, + = edit_menu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this, &main_window::pasteClipboard); m_paste_action->setShortcutContext (Qt::ApplicationShortcut); @@ -2311,7 +2293,7 @@ edit_menu->addSeparator (); m_find_files_action - = edit_menu->addAction (rmgr.icon ("edit-find"), tr ("Find Files...")); + = edit_menu->addAction (settings.icon ("edit-find"), tr ("Find Files...")); edit_menu->addSeparator (); @@ -2330,7 +2312,7 @@ = edit_menu->addAction (tr ("Set Path")); m_preferences_action - = edit_menu->addAction (rmgr.icon ("preferences-system"), + = edit_menu->addAction (settings.icon ("preferences-system"), tr ("Preferences...")); connect (m_find_files_action, &QAction::triggered, @@ -2368,8 +2350,9 @@ const QString& item, const char *member) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - QAction *action = add_action (m_debug_menu, rmgr.icon (QString (icon)), + gui_settings settings; + + QAction *action = add_action (m_debug_menu, settings.icon (QString (icon)), item, member); action->setEnabled (false); @@ -2625,12 +2608,14 @@ // need to delete these upon destroying this main_window. m_main_tool_bar->addWidget (new QLabel (tr ("Current Directory: "))); m_main_tool_bar->addWidget (m_current_directory_combo_box); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + + gui_settings settings; + QAction *current_dir_up - = m_main_tool_bar->addAction (rmgr.icon ("folder-up", false, "go-up"), + = m_main_tool_bar->addAction (settings.icon ("folder-up", false, "go-up"), tr ("One directory up")); QAction *current_dir_search - = m_main_tool_bar->addAction (rmgr.icon ("folder"), + = m_main_tool_bar->addAction (settings.icon ("folder"), tr ("Browse directories")); connect (m_current_directory_combo_box, SIGNAL (activated (const QString&)), @@ -2652,9 +2637,9 @@ void main_window::focus_console_after_command (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings->value (cs_focus_cmd).toBool ()) + gui_settings settings; + + if (settings.value (cs_focus_cmd).toBool ()) focus_command_window (); } @@ -2902,11 +2887,10 @@ if (save) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - settings->setValue (mw_geometry.key, saveGeometry ()); - settings->setValue (mw_state.key, saveState ()); + gui_settings settings; + + settings.setValue (mw_geometry.key, saveGeometry ()); + settings.setValue (mw_state.key, saveState ()); } focus_command_window (); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/main-window.h --- a/libgui/src/main-window.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/main-window.h Tue Dec 06 15:17:16 2022 -0500 @@ -52,7 +52,6 @@ #include "interpreter-qobject.h" #include "led-indicator.h" #include "octave-dock-widget.h" -#include "octave-qobject.h" #include "qt-interpreter-events.h" #include "set-path-dialog.h" #include "terminal-dock-widget.h" @@ -65,6 +64,7 @@ { class interpreter; + class base_qobject; class settings_dialog; //! Represents the main window. @@ -99,7 +99,7 @@ void active_dock_changed (octave_dock_widget *, octave_dock_widget *); void editor_focus_changed (bool); - void settings_changed (const gui_settings *); + void settings_changed (void); void init_terminal_size_signal (void); void init_window_menu (void); void new_file_signal (const QString&); @@ -156,8 +156,7 @@ void process_settings_dialog_request (const QString& desired_tab = QString ()); void show_about_octave (void); - void notice_settings (const gui_settings *settings, - bool update_by_worker = false); + void notice_settings (bool update_by_worker = false); QPalette getFusionDarkPalette(); void prepare_to_exit (void); void go_to_previous_widget (void); @@ -199,7 +198,7 @@ void read_settings (void); void init_terminal_size (void); - void set_window_layout (gui_settings *settings); + void set_window_layout (void); void write_settings (void); void copyClipboard (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/news-reader.cc --- a/libgui/src/news-reader.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/news-reader.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,8 +33,8 @@ #include #include "news-reader.h" -#include "octave-qobject.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "url-transfer.h" #include "version.h" @@ -68,16 +68,12 @@ { if (m_serial >= 0) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (settings) - { - settings->setValue (nr_last_time.key, - QDateTime::currentDateTime ()); + settings.setValue (nr_last_time.key, + QDateTime::currentDateTime ()); - settings->sync (); - } + settings.sync (); QString tag ("community-news-page-serial="); @@ -95,13 +91,8 @@ if (curr_page_serial > m_serial) { - if (settings) - { - settings->setValue (nr_last_news.key, - curr_page_serial); - - settings->sync (); - } + settings.setValue (nr_last_news.key, curr_page_serial); + settings.sync (); } else return; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/news-reader.h --- a/libgui/src/news-reader.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/news-reader.h Tue Dec 06 15:17:16 2022 -0500 @@ -31,18 +31,15 @@ namespace octave { - class base_qobject; - class news_reader : public QObject { Q_OBJECT public: - news_reader (base_qobject& oct_qobj, const QString& base_url, - const QString& page, int serial = -1, - bool connect_to_web = false) - : QObject (), m_octave_qobj (oct_qobj), m_base_url (base_url), + news_reader (const QString& base_url, const QString& page, + int serial = -1, bool connect_to_web = false) + : QObject (), m_base_url (base_url), m_page (page), m_serial (serial), m_connect_to_web (connect_to_web) { } @@ -58,8 +55,6 @@ private: - base_qobject& m_octave_qobj; - QString m_base_url; QString m_page; int m_serial; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/octave-dock-widget.cc --- a/libgui/src/octave-dock-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/octave-dock-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -73,13 +73,13 @@ } } - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; // the custom (extra) title bar of the widget m_title_widget = new QWidget (); m_dock_action = new QAction - (rmgr.icon ("widget-undock", true), "", this); + (settings.icon ("widget-undock", true), "", this); m_dock_action->setToolTip (tr ("Undock widget")); m_dock_button = new QToolButton (m_title_widget); m_dock_button->setDefaultAction (m_dock_action); @@ -87,7 +87,7 @@ m_dock_button->setIconSize (QSize (m_icon_size, m_icon_size)); m_close_action = new QAction - (rmgr.icon ("widget-close", true), "", this); + (settings.icon ("widget-close", true), "", this); m_close_action->setToolTip (tr ("Close widget")); m_close_button = new QToolButton (m_title_widget); m_close_button->setDefaultAction (m_close_action); @@ -258,8 +258,7 @@ | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - handle_settings (rmgr.get_settings ()); + handle_settings (); } void @@ -315,8 +314,9 @@ // adjust the (un)dock icon if (titleBarWidget ()) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_dock_action->setIcon (rmgr.icon ("widget-dock" + m_icon_color, true)); + gui_settings settings; + + m_dock_action->setIcon (settings.icon ("widget-dock" + m_icon_color, true)); m_dock_action->setToolTip (tr ("Dock widget")); } else @@ -343,15 +343,15 @@ void octave_dock_widget::make_widget (bool) { + gui_settings settings; + bool vis = isVisible (); // Since floating widget has no parent, we have to read it - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); if (m_main_window) { - settings->setValue (mw_state.key, m_main_window->saveState ()); + settings.setValue (mw_state.key, m_main_window->saveState ()); // Stay window, otherwise will bounce back to window by default // because there is no layout information for this widget in the @@ -360,7 +360,7 @@ m_main_window->addDockWidget (Qt::BottomDockWidgetArea, this); m_adopted = false; // recover old window states, hide and re-show new added widget - m_main_window->restoreState (settings->value (mw_state.key).toByteArray ()); + m_main_window->restoreState (settings.value (mw_state.key).toByteArray ()); setFloating (false); // restore size using setGeometry instead of restoreGeometry // following this post: @@ -374,7 +374,7 @@ this, &octave_dock_widget::make_window); if (titleBarWidget ()) { - m_dock_action->setIcon (rmgr.icon ("widget-undock" + m_icon_color, true)); + m_dock_action->setIcon (settings.icon ("widget-undock" + m_icon_color, true)); m_dock_action->setToolTip (tr ("Undock widget")); } else @@ -472,28 +472,27 @@ } void - octave_dock_widget::handle_settings (const gui_settings *settings) + octave_dock_widget::handle_settings (void) { - if (! settings) - return; + gui_settings settings; - m_focus_follows_mouse = settings->value (dw_focus_follows_mouse).toBool (); + m_focus_follows_mouse = settings.value (dw_focus_follows_mouse).toBool (); m_custom_style - = settings->value (dw_title_custom_style).toBool (); + = settings.value (dw_title_custom_style).toBool (); - m_title_3d = settings->value (dw_title_3d.key, dw_title_3d.def).toInt (); + m_title_3d = settings.value (dw_title_3d.key, dw_title_3d.def).toInt (); m_fg_color - = settings->value (dw_title_fg_color).value (); + = settings.value (dw_title_fg_color).value (); m_fg_color_active - = settings->value (dw_title_fg_color_active).value (); + = settings.value (dw_title_fg_color_active).value (); - m_bg_color = settings->value (dw_title_bg_color).value (); + m_bg_color = settings.value (dw_title_bg_color).value (); m_bg_color_active - = settings->value (dw_title_bg_color_active).value (); + = settings.value (dw_title_bg_color_active).value (); QColor bcol (m_bg_color); QColor bcola (m_bg_color_active); @@ -536,7 +535,7 @@ } m_recent_float_geom - = settings->value (dw_float_geometry.key.arg (objectName ()), + = settings.value (dw_float_geometry.key.arg (objectName ()), default_floating_size).toRect (); adjust_to_screen (m_recent_float_geom, default_floating_size); @@ -545,14 +544,14 @@ // saveGeomety to new QRect setting (see comment for restoring size // of docked widgets) QVariant dock_geom - = settings->value (dw_dock_geometry.key.arg (objectName ()), - default_dock_size); + = settings.value (dw_dock_geometry.key.arg (objectName ()), + default_dock_size); if (dock_geom.canConvert (QMetaType::QRect)) m_recent_dock_geom = dock_geom.toRect (); else m_recent_dock_geom = dw_dock_geometry.def.toRect (); - notice_settings (settings); // call individual handler + notice_settings (); // call individual handler set_style (false); @@ -587,27 +586,24 @@ void octave_dock_widget::save_settings (void) { + gui_settings settings; + // save state of this dock-widget QString name = objectName (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - return; store_geometry (); // conditional needed? if (! m_recent_float_geom.isNull ()) - settings->setValue (dw_float_geometry.key.arg (name), m_recent_float_geom); + settings.setValue (dw_float_geometry.key.arg (name), m_recent_float_geom); if (! m_recent_dock_geom.isEmpty ()) - settings->setValue (dw_dock_geometry.key.arg (name), m_recent_dock_geom); - settings->setValue (dw_is_visible.key.arg (name), isVisible ()); // store visibility - settings->setValue (dw_is_floating.key.arg (name), isFloating ()); // store floating - settings->setValue (dw_is_minimized.key.arg (name), isMinimized ()); // store minimized + settings.setValue (dw_dock_geometry.key.arg (name), m_recent_dock_geom); + settings.setValue (dw_is_visible.key.arg (name), isVisible ()); // store visibility + settings.setValue (dw_is_floating.key.arg (name), isFloating ()); // store floating + settings.setValue (dw_is_minimized.key.arg (name), isMinimized ()); // store minimized - settings->sync (); + settings.sync (); } bool octave_dock_widget::eventFilter (QObject *obj, QEvent *e) @@ -805,13 +801,14 @@ QString full_close_icon = "widget-close" + icon_col; if (titleBarWidget ()) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; + titleBarWidget ()->setStyleSheet (css_foreground + css_background); css_button = QString ("QToolButton {background: transparent; border: 0px;}"); m_dock_button->setStyleSheet (css_button); m_close_button->setStyleSheet (css_button); - m_dock_action->setIcon (rmgr.icon (full_dock_icon, true)); - m_close_action->setIcon (rmgr.icon (full_close_icon, true)); + m_dock_action->setIcon (settings.icon (full_dock_icon, true)); + m_close_action->setIcon (settings.icon (full_close_icon, true)); } else { @@ -834,26 +831,5 @@ m_predecessor_widget->setFocus (); m_predecessor_widget = nullptr; - - // FIXME: Until cset bda0c5b38bda, the wrong keys "Dockwidget/..." were used - // here. This had no effect in Qt4, but does in Qt5. In the following, the - // four incorrect keys are updated if still present in the settings files. - // The keys are also used in the settings dialog, but - // octave_dock_widget::handle_settings is already called at program start. - // These tests can be removed in a future version of Octave (version 6). - - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - - rmgr.update_settings_key ("Dockwidgets/title_bg_color", - dw_title_bg_color.key); - - rmgr.update_settings_key ("Dockwidgets/title_bg_color_active", - dw_title_bg_color_active.key); - - rmgr.update_settings_key ("Dockwidgets/title_fg_color", - dw_title_fg_color.key); - - rmgr.update_settings_key ("Dockwidgets/title_fg_color_active", - dw_title_fg_color_active.key); } } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/octave-dock-widget.h --- a/libgui/src/octave-dock-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/octave-dock-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -31,7 +31,6 @@ #include #include -#include "gui-settings.h" #include "qt-interpreter-events.h" namespace octave @@ -126,13 +125,13 @@ virtual void handle_visibility (bool visible); - virtual void notice_settings (const gui_settings *) { } + virtual void notice_settings (void) { } virtual void save_settings (void); void init_window_menu_entry (void); - void handle_settings (const gui_settings *); + void handle_settings (void); void handle_active_dock_changed (octave_dock_widget *, octave_dock_widget *); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/octave-qobject.cc --- a/libgui/src/octave-qobject.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/octave-qobject.cc Tue Dec 06 15:17:16 2022 -0500 @@ -46,6 +46,7 @@ #include "community-news.h" #include "documentation-dock-widget.h" #include "files-dock-widget.h" +#include "gui-settings.h" #include "history-dock-widget.h" #include "interpreter-qobject.h" #include "main-window.h" @@ -176,7 +177,7 @@ m_argv (m_app_context.sys_argv ()), m_qapplication (new octave_qapplication (m_argc, m_argv)), m_resource_manager (), - m_shortcut_manager (*this), + m_shortcut_manager (), m_qt_tr (new QTranslator ()), m_gui_tr (new QTranslator ()), m_qsci_tr (new QTranslator ()), @@ -208,11 +209,6 @@ QTextCodec::setCodecForLocale (QTextCodec::codecForName ("UTF-8")); #endif - // Initialize global Qt application metadata. - - QCoreApplication::setApplicationName ("GNU Octave"); - QCoreApplication::setApplicationVersion (OCTAVE_VERSION); - // Register octave_value_list for connecting thread crossing signals. qRegisterMetaType ("octave_value_list"); @@ -311,11 +307,14 @@ else { // Get settings file. - m_resource_manager.reload_settings (); + gui_settings settings; + + settings.reload (); // After settings. config_translators (); - m_resource_manager.config_icon_theme (); + + settings.config_icon_theme (); // Initilize the shortcut-manager m_shortcut_manager.init_data (); @@ -731,7 +730,7 @@ { if (! m_community_news) m_community_news - = QPointer (new community_news (*this, serial)); + = QPointer (new community_news (serial)); return m_community_news; } @@ -739,7 +738,7 @@ QPointer base_qobject::release_notes_widget (void) { if (! m_release_notes) - m_release_notes = QPointer (new release_notes (*this)); + m_release_notes = QPointer (new release_notes ()); return m_release_notes; } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/qt-application.cc --- a/libgui/src/qt-application.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/qt-application.cc Tue Dec 06 15:17:16 2022 -0500 @@ -27,6 +27,10 @@ # include "config.h" #endif +#include +#include +#include + #include "main-window.h" #include "octave-qobject.h" #include "qt-application.h" @@ -42,6 +46,31 @@ namespace octave { + qt_application::qt_application (const std::string& organization_name, + const std::string& application_name, + const std::string& application_version, + int argc, char **argv) + : application (argc, argv) + { + if (! organization_name.empty ()) + QCoreApplication::setOrganizationName + (QString::fromStdString (organization_name)); + + if (! application_name.empty ()) + QCoreApplication::setApplicationName + (QString::fromStdString (application_name)); + + if (! application_version.empty ()) + QCoreApplication::setApplicationVersion + (QString::fromStdString (application_version)); + + // FIXME: Is there a better place for this? + QSettings::setDefaultFormat (QSettings::IniFormat); + + // This should probably happen early. + sysdep_init (); + } + qt_application::qt_application (int argc, char **argv) : application (argc, argv) { diff -r 9089bd969b37 -r bd9da634f00d libgui/src/qt-application.h --- a/libgui/src/qt-application.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/qt-application.h Tue Dec 06 15:17:16 2022 -0500 @@ -26,6 +26,8 @@ #if ! defined (octave_qt_application_h) #define octave_qt_application_h 1 +#include + #include "octave.h" namespace octave @@ -45,6 +47,11 @@ { public: + qt_application (const std::string& organization_name, + const std::string& application_name, + const std::string& application_version, + int argc, char **argv); + qt_application (int argc, char **argv); // No copying, at least not yet. diff -r 9089bd969b37 -r bd9da634f00d libgui/src/qt-interpreter-events.cc --- a/libgui/src/qt-interpreter-events.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/qt-interpreter-events.cc Tue Dec 06 15:17:16 2022 -0500 @@ -39,6 +39,7 @@ #include "dialog.h" #include "gui-preferences-ed.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "qt-interpreter-events.h" #include "qt-utils.h" @@ -109,7 +110,7 @@ qt_interpreter_events::qt_interpreter_events (base_qobject& oct_qobj) : interpreter_events (), m_octave_qobj (oct_qobj), - m_uiwidget_creator (oct_qobj), m_result (), m_mutex (), + m_uiwidget_creator (), m_result (), m_mutex (), m_waitcondition () { qRegisterMetaType ("QIntList"); @@ -323,10 +324,9 @@ bool qt_interpreter_events::prompt_new_edit_file (const std::string& file) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (! settings || settings->value (ed_create_new_file).toBool ()) + if (settings.value (ed_create_new_file).toBool ()) return true; std::string abs_fname = sys::env::make_absolute (file); @@ -438,8 +438,9 @@ { QMutexLocker autolock (&m_mutex); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_result = QVariant::fromValue (rmgr.icon (name)); + gui_settings settings; + + m_result = QVariant::fromValue (settings.icon (name)); wake_all (); } @@ -684,10 +685,9 @@ { QMutexLocker autolock (&m_mutex); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - QString read_value = settings->value (key).toString (); + QString read_value = settings.value (key).toString (); // Some preferences need extra handling QString adjusted_value = gui_preference_adjust (key, value); @@ -695,9 +695,9 @@ if (! adjusted_value.isEmpty () && (read_value != adjusted_value)) { // Change settings only for new, non-empty values - settings->setValue (key, QVariant (adjusted_value)); + settings.setValue (key, QVariant (adjusted_value)); - emit settings_changed (settings, true); // true: changed by worker + emit settings_changed (true); // true: changed by worker } m_result = read_value; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/qt-interpreter-events.h --- a/libgui/src/qt-interpreter-events.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/qt-interpreter-events.h Tue Dec 06 15:17:16 2022 -0500 @@ -36,7 +36,6 @@ #include #include "dialog.h" -#include "gui-settings.h" #include "event-manager.h" @@ -303,7 +302,7 @@ void get_named_icon_signal (const QString& name); - void settings_changed (const gui_settings *, bool); + void settings_changed (bool); void apply_new_settings (void); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/release-notes.cc --- a/libgui/src/release-notes.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/release-notes.cc Tue Dec 06 15:17:16 2022 -0500 @@ -40,22 +40,22 @@ #include "gui-utils.h" #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" +#include "gui-settings.h" #include "news-reader.h" -#include "octave-qobject.h" #include "defaults.h" namespace octave { - release_notes::release_notes (base_qobject& oct_qobj) + release_notes::release_notes (void) : QWidget (nullptr), m_browser (nullptr) { - resource_manager& rmgr = oct_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; // The icon - QString icon_set = settings->value (dw_icon_set).toString (); + QString icon_set = settings.value (dw_icon_set).toString (); + if (icon_set != "NONE") m_release_notes_icon = dw_icon_set_names[icon_set] + "ReleaseWidget.png"; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/release-notes.h --- a/libgui/src/release-notes.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/release-notes.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,15 +33,13 @@ namespace octave { - class base_qobject; - class release_notes : public QWidget { Q_OBJECT public: - release_notes (base_qobject& qct_qobj); + release_notes (void); ~release_notes (void) = default; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/resource-manager.cc --- a/libgui/src/resource-manager.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/resource-manager.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,12 +33,10 @@ #include #include +#include #include #include -#include -#include #include -#include #include #include @@ -48,7 +46,7 @@ #include "gui-preferences-cs.h" #include "gui-preferences-ed.h" #include "gui-preferences-global.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "resource-manager.h" #include "variable-editor.h" #include "workspace-model.h" @@ -58,70 +56,15 @@ #include "oct-env.h" #include "defaults.h" -#include "error.h" -#include "help.h" namespace octave { resource_manager::resource_manager (void) - : m_settings_directory (), m_settings_file (), m_settings (nullptr), - m_default_settings (nullptr), m_temporary_files (), m_icon_fallbacks () - { - // Let gui_settings decide where to put the ini file with gui preferences - m_default_settings - = new gui_settings (QSettings::IniFormat, QSettings::UserScope, - "octave", "octave-gui"); - - m_settings_file = m_default_settings->fileName (); - - QFileInfo sfile (m_settings_file); - m_settings_directory = sfile.absolutePath (); - - QString xdg_config_home - = QString::fromLocal8Bit (qgetenv ("XDG_CONFIG_HOME")); - - if ((! sfile.exists ()) && xdg_config_home.isEmpty ()) - { - // File does not exist yet: Look for a settings file at the old - // location ($HOME/.config/octave/qt-settings) for impoting all - // available keys into the new settings file. - // Do not look for an old settings file if XDG_CONFIG_HOME is set, - // since then a nonexistent new settings file does not necessarily - // indicate a first run of octave with new config file locations. -#if defined (HAVE_QSTANDARDPATHS) - QString home_path - = QStandardPaths::writableLocation (QStandardPaths::HomeLocation); -#else - QString home_path - = QDesktopServices::storageLocation (QDesktopServices::HomeLocation); -#endif - - QString old_settings_directory = home_path + "/.config/octave"; - QString old_settings_file = old_settings_directory + "/qt-settings"; - - QFile ofile (old_settings_file); - - if (ofile.exists ()) - { - // Old settings file exists; create a gui_settings object related - // to it and copy all available keys to the new settings - gui_settings old_settings (old_settings_file, QSettings::IniFormat); - - QStringList keys = old_settings.allKeys (); - for (int i = 0; i < keys.count(); i++) - m_default_settings->setValue (keys.at(i), - old_settings.value(keys.at(i))); - - m_default_settings->sync (); // Done, make sure keys are written - } - } - } + : m_temporary_files () + { } resource_manager::~resource_manager (void) { - delete m_settings; - delete m_default_settings; - for (int i = m_temporary_files.count () - 1; i >=0; i--) remove_tmp_file (m_temporary_files.at (i)); } @@ -131,7 +74,7 @@ // get environment variable for the locale dir (e.g. from run-octave) std::string dldir = sys::env::getenv ("OCTAVE_LOCALE_DIR"); if (dldir.empty ()) - dldir = config::oct_locale_dir (); // env-var empty, load the default location + dldir = config::oct_locale_dir (); // env-var empty, load the default location return QString::fromStdString (dldir); } @@ -149,12 +92,11 @@ // FIXME: can we somehow ensure that the settings object will always // be initialize and valid? - if (m_settings) - { - // get the locale from the settings if already available - language = m_settings->value (global_language.key, - global_language.def).toString (); - } + gui_settings settings; + + // get the locale from the settings if already available + language = settings.value (global_language.key, + global_language.def).toString (); // load the translations depending on the settings if (language == "SYSTEM") @@ -171,11 +113,11 @@ { // load the translation files depending on the given locale name loaded = qt_tr->load ("qt_" + language, qt_trans_dir); - if (! loaded) // try lower case + if (! loaded) // try lower case qt_tr->load ("qt_" + language.toLower (), qt_trans_dir); loaded = qsci_tr->load ("qscintilla_" + language, qt_trans_dir); - if (! loaded) // try lower case + if (! loaded) // try lower case qsci_tr->load ("qscintilla_" + language.toLower (), qt_trans_dir); gui_tr->load (language, get_gui_translation_dir ()); @@ -183,216 +125,6 @@ } - void resource_manager::config_icon_theme (void) - { - m_icon_fallbacks.clear (); - - int theme = global_icon_theme_index.def.toInt (); - - if (m_settings) - { - // check for new and old setting and use old if required - if (! m_settings->contains (global_icon_theme_index.key)) - { - // new pref does not exist - if (m_settings->value (global_icon_theme).toBool ()) - theme = ICON_THEME_SYSTEM; - else - theme = ICON_THEME_OCTAVE; - m_settings->setValue (global_icon_theme_index.key, theme); // add new - m_settings->remove (global_icon_theme.key); // remove deprecated key - } - else - { - // get new settings - theme = m_settings->value (global_icon_theme_index).toInt (); - } - } - - QIcon::setThemeName (global_all_icon_themes.at (theme)); - - // set the required fallback search paths - switch (theme) - { - case ICON_THEME_SYSTEM: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); - break; - case ICON_THEME_TANGO: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_OCTAVE); - break; - case ICON_THEME_OCTAVE: - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_TANGO); - break; - } - - m_icon_fallbacks << global_icon_paths.at (ICON_THEME_CURSORS); - } - - gui_settings * resource_manager::get_settings (void) const - { - if (! m_settings) - { - QString msg (QT_TR_NOOP ("Octave has lost its settings.\n" - "This should not happen.\n\n" - "Please report this bug.\n\n" - "Octave GUI must be closed now.")); - - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg); - exit (1); - } - - return m_settings; - } - - gui_settings * resource_manager::get_default_settings (void) const - { - if (! m_default_settings) - { - QString msg (QT_TR_NOOP ("Octave has lost its default settings.\n" - "This should not happen.\n" - "Please report this bug.\n\n" - "Octave GUI must be closed now.")); - - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg); - exit (1); - } - - return m_default_settings; - } - - QString resource_manager::get_settings_directory (void) - { - return m_settings_directory; - } - - QString resource_manager::get_settings_file (void) - { - return m_settings_file; - } - - QString resource_manager::get_default_font_family (void) - { - QString default_family; - - // Get all available fixed width fonts via a font combobox - QFontComboBox font_combo_box; - font_combo_box.setFontFilters (QFontComboBox::MonospacedFonts); - QStringList fonts; - - for (int index = 0; index < font_combo_box.count(); index++) - fonts << font_combo_box.itemText(index); - -#if defined (Q_OS_MAC) - // Use hard coded default on macOS, since selection of fixed width - // default font is unreliable (see bug #59128). - // Test for macOS default fixed width font - if (fonts.contains (global_mono_font.def.toString ())) - default_family = global_mono_font.def.toString (); -#endif - - // If default font is still empty (on all other platforms or - // if macOS default font is not available): use QFontDatabase - if (default_family.isEmpty ()) - { - // Get the system's default monospaced font - QFont fixed_font = QFontDatabase::systemFont (QFontDatabase::FixedFont); - default_family = fixed_font.defaultFamily (); - - // Since this might be unreliable, test all available fixed width fonts - if (! fonts.contains (default_family)) - { - // Font returned by QFontDatabase is not in fixed fonts list. - // Fallback: take first from this list - default_family = fonts[0]; - } - } - - // Test env variable which has preference - std::string env_default_family = sys::env::getenv ("OCTAVE_DEFAULT_FONT"); - if (! env_default_family.empty ()) - default_family = QString::fromStdString (env_default_family); - - return default_family; - } - - QStringList resource_manager::get_default_font (void) - { - QString default_family = get_default_font_family (); - - // determine the fefault font size of the system - // FIXME: QApplication::font () does not return the monospace font, - // but the size should be probably near to the monospace font - QFont font = QApplication::font (); - - int font_size = font.pointSize (); - if (font_size == -1) - font_size = static_cast (std::floor(font.pointSizeF ())); - - // check for valid font size, otherwise take default 10 - QString default_font_size = "10"; - if (font_size > 0) - default_font_size = QString::number (font_size); - - std::string env_default_font_size - = sys::env::getenv ("OCTAVE_DEFAULT_FONT_SIZE"); - - if (! env_default_font_size.empty ()) - default_font_size = QString::fromStdString (env_default_font_size); - - QStringList result; - result << default_family; - result << default_font_size; - return result; - } - - void resource_manager::reload_settings (void) - { - // Declare some empty options, which may be set at first startup for - // writing them into the newly created settings file - QString custom_editor; - QStringList def_font; - - // Check whether the settings file does not yet exist - if (! QFile::exists (m_settings_file)) - { - // Get the default font (for terminal) - def_font = get_default_font (); - - // Get a custom editor defined as env variable - std::string env_default_editor - = sys::env::getenv ("OCTAVE_DEFAULT_EDITOR"); - - if (! env_default_editor.empty ()) - custom_editor = QString::fromStdString (env_default_editor); - } - - set_settings (m_settings_file); - - // Write some settings that were dynamically determined at first startup - if (m_settings) - { - // Custom editor - if (! custom_editor.isEmpty ()) - m_settings->setValue (global_custom_editor.key, custom_editor); - - // Default monospace font for the terminal - if (def_font.count () > 1) - { - m_settings->setValue (cs_font.key, def_font[0]); - m_settings->setValue (cs_font_size.key, def_font[1].toInt ()); - } - - // Write the default monospace font into the settings for later use by - // console and editor as fallbacks of their font preferences. - m_settings->setValue (global_mono_font.key, get_default_font_family ()); - } - } - #if defined (HAVE_QSCINTILLA) int resource_manager::get_valid_lexer_styles (QsciLexer *lexer, int *styles) { @@ -422,9 +154,10 @@ #if defined (HAVE_QSCINTILLA) void resource_manager::read_lexer_settings (QsciLexer *lexer, - gui_settings *settings, int mode, int def) { + gui_settings settings; + // Test whether the settings for lexer is already contained in the // given gui settings file. If yes, load them, if not copy them from the // default settings file. @@ -436,13 +169,13 @@ QString group ("Scintilla" + settings_color_modes_ext[m]); - settings->beginGroup (group); - settings->beginGroup (lexer->language ()); + settings.beginGroup (group); + settings.beginGroup (lexer->language ()); - QStringList lexer_keys = settings->allKeys (); + QStringList lexer_keys = settings.allKeys (); - settings->endGroup (); - settings->endGroup (); + settings.endGroup (); + settings.endGroup (); if (def == settings_reload_default_colors_flag || lexer_keys.count () == 0) { @@ -452,7 +185,7 @@ // and convert the color by inverting the lightness // Get the default font - QStringList def_font = get_default_font (); + QStringList def_font = settings.get_default_font (); QFont df (def_font[0], def_font[1].toInt ()); QFont dfa = copy_font_attributes (lexer->defaultFont (), df); lexer->setDefaultFont (dfa); @@ -464,9 +197,9 @@ for (int i = 0; i < max_style; i++) { - c = settings->get_color_value (QVariant (lexer->color (styles[i])), m); + c = settings.get_color_value (QVariant (lexer->color (styles[i])), m); lexer->setColor (c, styles[i]); - p = settings->get_color_value (QVariant (lexer->paper (styles[i])), m); + p = settings.get_color_value (QVariant (lexer->paper (styles[i])), m); lexer->setPaper (p, styles[i]); dfa = copy_font_attributes (lexer->font (styles[i]), df); lexer->setFont (dfa, styles[i]); @@ -479,75 +212,37 @@ if (def != settings_reload_default_colors_flag) { const std::string group_str = group.toStdString (); - lexer->writeSettings (*settings, group_str.c_str ()); - settings->sync (); + lexer->writeSettings (settings, group_str.c_str ()); + settings.sync (); } } else { // Found lexer keys, read the settings const std::string group_str = group.toStdString (); - lexer->readSettings (*settings, group_str.c_str ()); + lexer->readSettings (settings, group_str.c_str ()); } } #endif - void resource_manager::set_settings (const QString& file) - { - delete m_settings; - m_settings = new gui_settings (file, QSettings::IniFormat); - - if (m_settings->status () == QSettings::NoError) - { - // Test usability (force file to be really created) - m_settings->setValue ("dummy", 0); - m_settings->sync (); - } - - if (! (QFile::exists (m_settings->fileName ()) - && m_settings->isWritable () - && m_settings->status () == QSettings::NoError)) - { - QString msg - = QString (QT_TR_NOOP ("The settings file\n%1\n" - "does not exist and can not be created.\n" - "Make sure you have read and write permissions to\n%2\n\n" - "Octave GUI must be closed now.")); - - QMessageBox::critical (nullptr, - QString (QT_TR_NOOP ("Octave Critical Error")), - msg.arg (get_settings_file ()).arg (get_settings_directory ())); - - exit (1); - } - else - m_settings->remove ("dummy"); // Remove test entry - } - bool resource_manager::update_settings_key (const QString& old_key, const QString& new_key) { - if (m_settings->contains (old_key)) + gui_settings settings; + + if (settings.contains (old_key)) { - QVariant preference = m_settings->value (old_key); - m_settings->setValue (new_key, preference); - m_settings->remove (old_key); + QVariant preference = settings.value (old_key); + settings.setValue (new_key, preference); + settings.remove (old_key); return true; } return false; } - bool resource_manager::is_first_run (void) const - { - return ! QFile::exists (m_settings_file); - } - void resource_manager::update_network_settings (void) { - if (! m_settings) - return; - QNetworkProxy proxy; // Assume no proxy and empty proxy data @@ -559,11 +254,13 @@ QString pass; QUrl proxy_url = QUrl (); - if (m_settings->value (global_use_proxy.key, global_use_proxy.def).toBool ()) + gui_settings settings; + + if (settings.value (global_use_proxy.key, global_use_proxy.def).toBool ()) { // Use a proxy, collect all required information QString proxy_type_string - = m_settings->value (global_proxy_type.key, global_proxy_type.def).toString (); + = settings.value (global_proxy_type.key, global_proxy_type.def).toString (); // The proxy type for the Qt proxy settings if (proxy_type_string == "Socks5Proxy") @@ -575,14 +272,14 @@ if (proxy_type_string == "HttpProxy" || proxy_type_string == "Socks5Proxy") { - host = m_settings->value (global_proxy_host.key, - global_proxy_host.def).toString (); - port = m_settings->value (global_proxy_port.key, - global_proxy_port.def).toInt (); - user = m_settings->value (global_proxy_user.key, - global_proxy_user.def).toString (); - pass = m_settings->value (global_proxy_pass.key, - global_proxy_pass.def).toString (); + host = settings.value (global_proxy_host.key, + global_proxy_host.def).toString (); + port = settings.value (global_proxy_port.key, + global_proxy_port.def).toInt (); + user = settings.value (global_proxy_user.key, + global_proxy_user.def).toString (); + pass = settings.value (global_proxy_pass.key, + global_proxy_pass.def).toString (); if (proxy_type_string == "HttpProxy") scheme = "http"; else if (proxy_type_string == "Socks5Proxy") @@ -651,28 +348,6 @@ sys::env::putenv ("HTTPS_PROXY", proxy_url_str); } - QIcon resource_manager::icon (const QString& icon_name, bool octave_only, - const QString& icon_alt_name) - { - if (octave_only) - return QIcon (global_icon_paths.at (ICON_THEME_OCTAVE) + icon_name + ".png"); - - if (QIcon::hasThemeIcon (icon_name)) - return QIcon (QIcon::fromTheme (icon_name)); - else if ((! icon_alt_name.isEmpty ()) && QIcon::hasThemeIcon (icon_alt_name)) - return QIcon (QIcon::fromTheme (icon_alt_name)); - - for (int i = 0; i < m_icon_fallbacks.length (); i++ ) - { - QString icon_file (m_icon_fallbacks.at (i) + icon_name + ".png"); - if (QFile (icon_file).exists ()) - return QIcon (icon_file); - } - - //QIcon::setThemeName (current_theme); - return QIcon (); - } - // get a list of all available encodings void resource_manager::get_codecs (QStringList *codecs) { @@ -721,7 +396,9 @@ if (enc.isEmpty ()) { - enc = m_settings->value (ed_default_enc).toString (); + gui_settings settings; + + enc = settings.value (ed_default_enc).toString (); if (enc.isEmpty ()) // still empty? { diff -r 9089bd969b37 -r bd9da634f00d libgui/src/resource-manager.h --- a/libgui/src/resource-manager.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/resource-manager.h Tue Dec 06 15:17:16 2022 -0500 @@ -27,7 +27,6 @@ #define octave_resource_manager_h 1 #include -#include #include #if defined (HAVE_QSCINTILLA) # include @@ -35,8 +34,6 @@ #include #include -#include "gui-settings.h" - namespace octave { class resource_manager : public QObject @@ -61,19 +58,6 @@ void config_translators (QTranslator *qt_tr, QTranslator *qsci_tr, QTranslator *gui_tr); - void config_icon_theme (void); - - gui_settings * get_settings (void) const; - - gui_settings * get_default_settings (void) const; - - QString get_settings_directory (void); - - QString get_settings_file (void); - - QString get_default_font_family (void); - - QStringList get_default_font (void); QPointer create_tmp_file (const QString& extension = QString (), @@ -81,25 +65,15 @@ void remove_tmp_file (QPointer tmp_file); - void reload_settings (void); - #if defined (HAVE_QSCINTILLA) int get_valid_lexer_styles (QsciLexer *lexer, int *styles); - void read_lexer_settings (QsciLexer *lexer, gui_settings *settings, - int mode = 0, int def = 0); + void read_lexer_settings (QsciLexer *lexer, int mode = 0, int def = 0); #endif - void set_settings (const QString& file); - bool update_settings_key (const QString& new_key, const QString& old_key); - bool is_first_run (void) const; - void update_network_settings (void); - QIcon icon (const QString& icon_name, bool octave_only = false, - const QString& icon_alt_name = QString ()); - void get_codecs (QStringList *codecs); void combo_encoding (QComboBox *combo, const QString& current = QString ()); @@ -115,17 +89,7 @@ */ QFont copy_font_attributes (const QFont& attr, const QFont& base) const; - QString m_settings_directory; - - QString m_settings_file; - - gui_settings *m_settings; - - gui_settings *m_default_settings; - QList m_temporary_files; - - QStringList m_icon_fallbacks; }; } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/set-path-dialog.cc --- a/libgui/src/set-path-dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/set-path-dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -50,7 +50,7 @@ #include #include "gui-preferences-pd.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "octave-qtutils.h" #include "set-path-dialog.h" #include "set-path-model.h" @@ -59,8 +59,8 @@ namespace octave { - set_path_dialog::set_path_dialog (QWidget *parent, base_qobject& oct_qobj) - : QDialog (parent), m_octave_qobj (oct_qobj) + set_path_dialog::set_path_dialog (QWidget *parent) + : QDialog (parent) { setWindowTitle (tr ("Set Path")); @@ -168,10 +168,9 @@ setLayout (main_layout); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - restoreGeometry ( - settings->value(pd_geometry.key).toByteArray()); + gui_settings settings; + + restoreGeometry (settings.value(pd_geometry.key).toByteArray()); } void set_path_dialog::update_model (void) @@ -297,11 +296,11 @@ m_path_list->scrollTo (m->index (row_count - 1)); } - void set_path_dialog::save_settings () + void set_path_dialog::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - settings->setValue (pd_geometry.key, saveGeometry ()); + gui_settings settings; + + settings.setValue (pd_geometry.key, saveGeometry ()); } void set_path_dialog::closeEvent (QCloseEvent *e) diff -r 9089bd969b37 -r bd9da634f00d libgui/src/set-path-dialog.h --- a/libgui/src/set-path-dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/set-path-dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -41,8 +41,6 @@ namespace octave { - class base_qobject; - class set_path_dialog : public QDialog { Q_OBJECT @@ -53,7 +51,7 @@ // in the dialog. That may only be done after the intepreter_event // signal connections are made to the Octave interpreter. - set_path_dialog (QWidget *parent, base_qobject& oct_qobj); + set_path_dialog (QWidget *parent); virtual ~set_path_dialog (void) = default; @@ -96,8 +94,6 @@ void add_dir_common (bool subdirs); - base_qobject& m_octave_qobj; - QLabel *m_info_label; QPushButton *m_reload_button; QPushButton *m_save_button; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/settings-dialog.cc --- a/libgui/src/settings-dialog.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/settings-dialog.cc Tue Dec 06 15:17:16 2022 -0500 @@ -79,22 +79,12 @@ { setupUi (this); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - - if (! settings) - { - QMessageBox msgBox - (QMessageBox::Warning, tr ("Octave Preferences"), - tr ("Unable to save preferences. Missing preferences file or unknown directory.")); - - msgBox.exec (); - - return; - } + gui_settings settings; // look for available language files and the actual settings + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); QString qm_dir_name = rmgr.get_gui_translation_dir (); + QDir qm_dir (qm_dir_name); QFileInfoList qm_files = qm_dir.entryInfoList (QStringList ("*.qm"), QDir::Files | QDir::Readable, QDir::Name); @@ -104,7 +94,7 @@ // System at beginning comboBox_language->insertItem (0, tr ("System setting")); comboBox_language->insertSeparator (1); // separator after System - QString language = settings->value (global_language.key, + QString language = settings.value (global_language.key, global_language.def).toString (); if (language == global_language.def.toString ()) language = tr ("System setting"); @@ -120,7 +110,7 @@ combo_styles->addItems (styles); combo_styles->insertItem (0, global_style.def.toString ()); combo_styles->insertSeparator (1); - QString current_style = settings->value (global_style).toString (); + QString current_style = settings.value (global_style).toString (); if (current_style == global_style.def.toString ()) current_style = global_style.def.toString (); selected = combo_styles->findText (current_style); @@ -134,12 +124,12 @@ icon_size_group->addButton (icon_size_small); icon_size_group->addButton (icon_size_normal); icon_size_group->addButton (icon_size_large); - int icon_size = settings->value (global_icon_size).toInt (); + int icon_size = settings.value (global_icon_size).toInt (); icon_size_normal->setChecked (true); // the default icon_size_small->setChecked (icon_size < 0); icon_size_large->setChecked (icon_size > 0); combo_box_icon_theme->addItems (global_all_icon_theme_names); - int theme = settings->value (global_icon_theme_index.key).toInt (); + int theme = settings.value (global_icon_theme_index.key).toInt (); combo_box_icon_theme->setCurrentIndex (theme); // which icon has to be selected @@ -148,14 +138,14 @@ icon_group->addButton (general_icon_graphic); icon_group->addButton (general_icon_letter); QString widget_icon_set = - settings->value (dw_icon_set).toString (); + settings.value (dw_icon_set).toString (); general_icon_octave->setChecked (true); // the default (if invalid set) general_icon_octave->setChecked (widget_icon_set == "NONE"); general_icon_graphic->setChecked (widget_icon_set == "GRAPHIC"); general_icon_letter->setChecked (widget_icon_set == "LETTER"); // custom title bar of dock widget - QColor bg_color = settings->value (dw_title_bg_color).value (); + QColor bg_color = settings.value (dw_title_bg_color).value (); m_widget_title_bg_color = new color_picker (bg_color); m_widget_title_bg_color->setEnabled (false); layout_widget_bgtitle->addWidget (m_widget_title_bg_color, 0); @@ -163,7 +153,7 @@ connect (cb_widget_custom_style, &QCheckBox::toggled, m_widget_title_bg_color, &color_picker::setEnabled); - QColor bg_color_active = settings->value (dw_title_bg_color_active).value (); + QColor bg_color_active = settings.value (dw_title_bg_color_active).value (); m_widget_title_bg_color_active = new color_picker (bg_color_active); m_widget_title_bg_color_active->setEnabled (false); layout_widget_bgtitle_active->addWidget (m_widget_title_bg_color_active, 0); @@ -171,7 +161,7 @@ connect (cb_widget_custom_style, &QCheckBox::toggled, m_widget_title_bg_color_active, &color_picker::setEnabled); - QColor fg_color = settings->value (dw_title_fg_color).value (); + QColor fg_color = settings.value (dw_title_fg_color).value (); m_widget_title_fg_color = new color_picker (fg_color); m_widget_title_fg_color->setEnabled (false); layout_widget_fgtitle->addWidget (m_widget_title_fg_color, 0); @@ -179,7 +169,7 @@ connect (cb_widget_custom_style, &QCheckBox::toggled, m_widget_title_fg_color, &color_picker::setEnabled); - QColor fg_color_active = settings->value (dw_title_fg_color_active).value (); + QColor fg_color_active = settings.value (dw_title_fg_color_active).value (); m_widget_title_fg_color_active = new color_picker (fg_color_active); m_widget_title_fg_color_active->setEnabled (false); layout_widget_fgtitle_active->addWidget (m_widget_title_fg_color_active, 0); @@ -187,48 +177,48 @@ connect (cb_widget_custom_style, &QCheckBox::toggled, m_widget_title_fg_color_active, &color_picker::setEnabled); - sb_3d_title->setValue (settings->value (dw_title_3d.key, + sb_3d_title->setValue (settings.value (dw_title_3d.key, dw_title_3d.def).toInt ()); - cb_widget_custom_style->setChecked (settings->value (dw_title_custom_style).toBool ()); + cb_widget_custom_style->setChecked (settings.value (dw_title_custom_style).toBool ()); // Native file dialogs. // FIXME: This preference can be deprecated / removed if all display // managers, especially KDE, run those dialogs without hangs or // delays from the start (bug #54607). - cb_use_native_file_dialogs->setChecked (settings->value (global_use_native_dialogs).toBool ()); + cb_use_native_file_dialogs->setChecked (settings.value (global_use_native_dialogs).toBool ()); // Cursor blinking: consider old terminal related setting if not yet set // FIXME: This pref. can be deprecated / removed if Qt adds support for // getting the cursor blink preferences from all OS environments - if (settings->contains (global_cursor_blinking.key)) + if (settings.contains (global_cursor_blinking.key)) { // Preference exists, read its value - cb_cursor_blinking->setChecked (settings->value + cb_cursor_blinking->setChecked (settings.value (global_cursor_blinking.key, global_cursor_blinking.def).toBool ()); } else { // Pref. does not exist, so take old terminal related pref. - cb_cursor_blinking->setChecked (settings->value + cb_cursor_blinking->setChecked (settings.value (cs_cursor_blinking.key, cs_cursor_blinking.def).toBool ()); } // focus follows mouse cb_focus_follows_mouse->setChecked ( - settings->value (dw_focus_follows_mouse).toBool ()); + settings.value (dw_focus_follows_mouse).toBool ()); // prompt on exit cb_prompt_to_exit->setChecked ( - settings->value (global_prompt_to_exit.key, global_prompt_to_exit.def).toBool ()); + settings.value (global_prompt_to_exit.key, global_prompt_to_exit.def).toBool ()); // Main status bar cb_status_bar->setChecked ( - settings->value (global_status_bar.key, global_status_bar.def).toBool ()); + settings.value (global_status_bar.key, global_status_bar.def).toBool ()); // Octave startup cb_restore_octave_dir->setChecked ( - settings->value (global_restore_ov_dir.key, global_restore_ov_dir.def).toBool ()); - le_octave_dir->setText (settings->value (global_ov_startup_dir.key, + settings.value (global_restore_ov_dir.key, global_restore_ov_dir.def).toBool ()); + le_octave_dir->setText (settings.value (global_ov_startup_dir.key, global_ov_startup_dir.def).toString ()); connect (pb_octave_dir, &QPushButton::pressed, @@ -238,66 +228,66 @@ // editor // useCustomFileEditor->setChecked ( - settings->value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()); + settings.value (global_use_custom_editor.key, global_use_custom_editor.def).toBool ()); customFileEditor->setText ( - settings->value (global_custom_editor.key, global_custom_editor.def).toString ()); - editor_showLineNumbers->setChecked (settings->value (ed_show_line_numbers).toBool ()); - editor_linenr_size->setValue (settings->value (ed_line_numbers_size).toInt ()); + settings.value (global_custom_editor.key, global_custom_editor.def).toString ()); + editor_showLineNumbers->setChecked (settings.value (ed_show_line_numbers).toBool ()); + editor_linenr_size->setValue (settings.value (ed_line_numbers_size).toInt ()); rmgr.combo_encoding (editor_combo_encoding); - editor_highlightCurrentLine->setChecked (settings->value (ed_highlight_current_line).toBool ()); - editor_long_line_marker->setChecked (settings->value (ed_long_line_marker).toBool ()); + editor_highlightCurrentLine->setChecked (settings.value (ed_highlight_current_line).toBool ()); + editor_long_line_marker->setChecked (settings.value (ed_long_line_marker).toBool ()); bool long_line = - settings->value (ed_long_line_marker_line).toBool (); + settings.value (ed_long_line_marker_line).toBool (); editor_long_line_marker_line->setChecked (long_line); bool long_back = - settings->value (ed_long_line_marker_background).toBool (); + settings.value (ed_long_line_marker_background).toBool (); editor_long_line_marker_background->setChecked (long_back); if (! (long_line || long_back)) editor_long_line_marker_line->setChecked (true); - editor_long_line_column->setValue (settings->value (ed_long_line_column).toInt ()); - editor_break_checkbox->setChecked (settings->value (ed_break_lines).toBool ()); - editor_break_comments_checkbox->setChecked (settings->value (ed_break_lines_comments).toBool ()); - editor_wrap_checkbox->setChecked (settings->value (ed_wrap_lines).toBool ()); - cb_edit_status_bar->setChecked (settings->value (ed_show_edit_status_bar).toBool ()); - cb_edit_tool_bar->setChecked (settings->value (ed_show_toolbar).toBool ()); - cb_code_folding->setChecked (settings->value (ed_code_folding).toBool ()); - editor_highlight_all_occurrences->setChecked (settings->value (ed_highlight_all_occurrences).toBool ()); + editor_long_line_column->setValue (settings.value (ed_long_line_column).toInt ()); + editor_break_checkbox->setChecked (settings.value (ed_break_lines).toBool ()); + editor_break_comments_checkbox->setChecked (settings.value (ed_break_lines_comments).toBool ()); + editor_wrap_checkbox->setChecked (settings.value (ed_wrap_lines).toBool ()); + cb_edit_status_bar->setChecked (settings.value (ed_show_edit_status_bar).toBool ()); + cb_edit_tool_bar->setChecked (settings.value (ed_show_toolbar).toBool ()); + cb_code_folding->setChecked (settings.value (ed_code_folding).toBool ()); + editor_highlight_all_occurrences->setChecked (settings.value (ed_highlight_all_occurrences).toBool ()); - editor_auto_endif->setCurrentIndex (settings->value (ed_auto_endif).toInt () ); - editor_codeCompletion->setChecked (settings->value (ed_code_completion).toBool ()); - editor_spinbox_ac_threshold->setValue (settings->value (ed_code_completion_threshold).toInt ()); - editor_checkbox_ac_keywords->setChecked (settings->value (ed_code_completion_keywords).toBool ()); + editor_auto_endif->setCurrentIndex (settings.value (ed_auto_endif).toInt () ); + editor_codeCompletion->setChecked (settings.value (ed_code_completion).toBool ()); + editor_spinbox_ac_threshold->setValue (settings.value (ed_code_completion_threshold).toInt ()); + editor_checkbox_ac_keywords->setChecked (settings.value (ed_code_completion_keywords).toBool ()); editor_checkbox_ac_builtins->setEnabled (editor_checkbox_ac_keywords->isChecked ()); editor_checkbox_ac_functions->setEnabled (editor_checkbox_ac_keywords->isChecked ()); - editor_checkbox_ac_builtins->setChecked (settings->value (ed_code_completion_octave_builtins).toBool ()); - editor_checkbox_ac_functions->setChecked (settings->value (ed_code_completion_octave_functions).toBool ()); - editor_checkbox_ac_document->setChecked (settings->value (ed_code_completion_document).toBool ()); - editor_checkbox_ac_case->setChecked (settings->value (ed_code_completion_case).toBool ()); - editor_checkbox_ac_replace->setChecked (settings->value (ed_code_completion_replace).toBool ()); - editor_ws_checkbox->setChecked (settings->value (ed_show_white_space).toBool ()); - editor_ws_indent_checkbox->setChecked (settings->value (ed_show_white_space_indent).toBool ()); - cb_show_eol->setChecked (settings->value (ed_show_eol_chars).toBool ()); - cb_show_hscrollbar->setChecked (settings->value (ed_show_hscroll_bar).toBool ()); + editor_checkbox_ac_builtins->setChecked (settings.value (ed_code_completion_octave_builtins).toBool ()); + editor_checkbox_ac_functions->setChecked (settings.value (ed_code_completion_octave_functions).toBool ()); + editor_checkbox_ac_document->setChecked (settings.value (ed_code_completion_document).toBool ()); + editor_checkbox_ac_case->setChecked (settings.value (ed_code_completion_case).toBool ()); + editor_checkbox_ac_replace->setChecked (settings.value (ed_code_completion_replace).toBool ()); + editor_ws_checkbox->setChecked (settings.value (ed_show_white_space).toBool ()); + editor_ws_indent_checkbox->setChecked (settings.value (ed_show_white_space_indent).toBool ()); + cb_show_eol->setChecked (settings.value (ed_show_eol_chars).toBool ()); + cb_show_hscrollbar->setChecked (settings.value (ed_show_hscroll_bar).toBool ()); for (int i = 0; i < ed_tab_position_names.length (); i++) editor_combox_tab_pos->insertItem (i, tr (ed_tab_position_names.at (i).toStdString ().data ())); editor_combox_tab_pos->setCurrentIndex - (settings->value (ed_tab_position).toInt ()); + (settings.value (ed_tab_position).toInt ()); - editor_cb_tabs_rotated->setChecked (settings->value (ed_tabs_rotated).toBool ()); - editor_sb_tabs_max_width->setValue (settings->value (ed_tabs_max_width).toInt ()); + editor_cb_tabs_rotated->setChecked (settings.value (ed_tabs_rotated).toBool ()); + editor_sb_tabs_max_width->setValue (settings.value (ed_tabs_max_width).toInt ()); int selected_comment_string, selected_uncomment_string; - if (settings->contains (ed_comment_str.key)) // new version (radio buttons) - selected_comment_string = settings->value (ed_comment_str).toInt (); + if (settings.contains (ed_comment_str.key)) // new version (radio buttons) + selected_comment_string = settings.value (ed_comment_str).toInt (); else // old version (combo box) - selected_comment_string = settings->value (ed_comment_str_old.key, ed_comment_str.def).toInt (); + selected_comment_string = settings.value (ed_comment_str_old.key, ed_comment_str.def).toInt (); - selected_uncomment_string = settings->value (ed_uncomment_str).toInt (); + selected_uncomment_string = settings.value (ed_uncomment_str).toInt (); for (int i = 0; i < ed_comment_strings_count; i++) { @@ -320,33 +310,33 @@ } - combo_eol_mode->setCurrentIndex (settings->value (ed_default_eol_mode).toInt ()); - editor_auto_ind_checkbox->setChecked (settings->value (ed_auto_indent).toBool ()); - editor_tab_ind_checkbox->setChecked (settings->value (ed_tab_indents_line).toBool ()); - editor_bs_unind_checkbox->setChecked (settings->value (ed_backspace_unindents_line).toBool ()); - editor_ind_guides_checkbox->setChecked (settings->value (ed_show_indent_guides).toBool ()); - editor_ind_width_spinbox->setValue (settings->value (ed_indent_width).toInt ()); - editor_ind_uses_tabs_checkbox->setChecked (settings->value (ed_indent_uses_tabs).toBool ()); - editor_tab_width_spinbox->setValue (settings->value (ed_tab_width).toInt ()); - editor_restoreSession->setChecked (settings->value (ed_restore_session).toBool ()); - editor_create_new_file->setChecked (settings->value (ed_create_new_file).toBool ()); - editor_reload_changed_files->setChecked (settings->value (ed_always_reload_changed_files).toBool ()); - editor_force_newline->setChecked (settings->value (ed_force_newline).toBool ()); - editor_remove_trailing_spaces->setChecked (settings->value (ed_rm_trailing_spaces).toBool ()); - editor_hiding_closes_files->setChecked (settings->value (ed_hiding_closes_files).toBool ()); - editor_show_dbg_file->setChecked (settings->value (ed_show_dbg_file).toBool ()); + combo_eol_mode->setCurrentIndex (settings.value (ed_default_eol_mode).toInt ()); + editor_auto_ind_checkbox->setChecked (settings.value (ed_auto_indent).toBool ()); + editor_tab_ind_checkbox->setChecked (settings.value (ed_tab_indents_line).toBool ()); + editor_bs_unind_checkbox->setChecked (settings.value (ed_backspace_unindents_line).toBool ()); + editor_ind_guides_checkbox->setChecked (settings.value (ed_show_indent_guides).toBool ()); + editor_ind_width_spinbox->setValue (settings.value (ed_indent_width).toInt ()); + editor_ind_uses_tabs_checkbox->setChecked (settings.value (ed_indent_uses_tabs).toBool ()); + editor_tab_width_spinbox->setValue (settings.value (ed_tab_width).toInt ()); + editor_restoreSession->setChecked (settings.value (ed_restore_session).toBool ()); + editor_create_new_file->setChecked (settings.value (ed_create_new_file).toBool ()); + editor_reload_changed_files->setChecked (settings.value (ed_always_reload_changed_files).toBool ()); + editor_force_newline->setChecked (settings.value (ed_force_newline).toBool ()); + editor_remove_trailing_spaces->setChecked (settings.value (ed_rm_trailing_spaces).toBool ()); + editor_hiding_closes_files->setChecked (settings.value (ed_hiding_closes_files).toBool ()); + editor_show_dbg_file->setChecked (settings.value (ed_show_dbg_file).toBool ()); // terminal - QString default_font = settings->value (global_mono_font).toString (); - terminal_fontName->setCurrentFont (QFont (settings->value (cs_font.key, default_font).toString ())); - terminal_fontSize->setValue (settings->value (cs_font_size).toInt ()); - terminal_history_buffer->setValue (settings->value (cs_hist_buffer).toInt ()); - terminal_cursorUseForegroundColor->setChecked (settings->value (cs_cursor_use_fgcol).toBool ()); - terminal_focus_command->setChecked (settings->value (cs_focus_cmd).toBool ()); - terminal_print_dbg_location->setChecked (settings->value (cs_dbg_location).toBool ()); + QString default_font = settings.value (global_mono_font).toString (); + terminal_fontName->setCurrentFont (QFont (settings.value (cs_font.key, default_font).toString ())); + terminal_fontSize->setValue (settings.value (cs_font_size).toInt ()); + terminal_history_buffer->setValue (settings.value (cs_hist_buffer).toInt ()); + terminal_cursorUseForegroundColor->setChecked (settings.value (cs_cursor_use_fgcol).toBool ()); + terminal_focus_command->setChecked (settings.value (cs_focus_cmd).toBool ()); + terminal_print_dbg_location->setChecked (settings.value (cs_dbg_location).toBool ()); QString cursor_type - = settings->value (cs_cursor).toString (); + = settings.value (cs_cursor).toString (); QStringList items; items << QString ("0") << QString ("1") << QString ("2"); @@ -364,28 +354,28 @@ } } - read_terminal_colors (settings); + read_terminal_colors (); // file browser connect (sync_octave_directory, &QCheckBox::toggled, this, &settings_dialog::set_disabled_pref_file_browser_dir); - sync_octave_directory->setChecked (settings->value (fb_sync_octdir).toBool ()); - cb_restore_file_browser_dir->setChecked (settings->value (fb_restore_last_dir).toBool ()); - le_file_browser_dir->setText (settings->value (fb_startup_dir.key).toString ()); + sync_octave_directory->setChecked (settings.value (fb_sync_octdir).toBool ()); + cb_restore_file_browser_dir->setChecked (settings.value (fb_restore_last_dir).toBool ()); + le_file_browser_dir->setText (settings.value (fb_startup_dir.key).toString ()); connect (pb_file_browser_dir, &QPushButton::pressed, this, &settings_dialog::get_file_browser_dir); - le_file_browser_extensions->setText (settings->value (fb_txt_file_ext).toString ()); + le_file_browser_extensions->setText (settings.value (fb_txt_file_ext).toString ()); - checkbox_allow_web_connect->setChecked (settings->value (nr_allow_connection).toBool ()); + checkbox_allow_web_connect->setChecked (settings.value (nr_allow_connection).toBool ()); // Proxy - bool use_proxy = settings->value (global_use_proxy.key, global_use_proxy.def).toBool (); + bool use_proxy = settings.value (global_use_proxy.key, global_use_proxy.def).toBool (); use_proxy_server->setChecked (use_proxy); // Fill combo box and activate current one - QString proxy_type_string = settings->value (global_proxy_type.key, global_proxy_type.def).toString (); + QString proxy_type_string = settings.value (global_proxy_type.key, global_proxy_type.def).toString (); proxy_type->addItems (global_proxy_all_types); for (int i = 0; i < global_proxy_all_types.length (); i++) { @@ -396,10 +386,10 @@ } } // Fill all line edits - proxy_host_name->setText (settings->value (global_proxy_host.key, global_proxy_host.def).toString ()); - proxy_port->setText (settings->value (global_proxy_port.key, global_proxy_port.def).toString ()); - proxy_username->setText (settings->value (global_proxy_user.key, global_proxy_user.def).toString ()); - proxy_password->setText (settings->value (global_proxy_pass.key, global_proxy_pass.def).toString ()); + proxy_host_name->setText (settings.value (global_proxy_host.key, global_proxy_host.def).toString ()); + proxy_port->setText (settings.value (global_proxy_port.key, global_proxy_port.def).toString ()); + proxy_username->setText (settings.value (global_proxy_user.key, global_proxy_user.def).toString ()); + proxy_password->setText (settings.value (global_proxy_pass.key, global_proxy_pass.def).toString ()); // Connect relevant signals for dis-/enabling some elements connect (proxy_type, QOverload::of (&QComboBox::currentIndexChanged), this, &settings_dialog::proxy_items_update); @@ -409,37 +399,37 @@ proxy_items_update (); // Workspace - read_workspace_colors (settings); + read_workspace_colors (); // variable editor - varedit_columnWidth->setValue (settings->value (ve_column_width).toInt ()); - varedit_rowHeight->setValue (settings->value (ve_row_height).toInt ()); + varedit_columnWidth->setValue (settings.value (ve_column_width).toInt ()); + varedit_rowHeight->setValue (settings.value (ve_row_height).toInt ()); - varedit_font->setCurrentFont (QFont (settings->value (ve_font_name.key, - settings->value (cs_font.key, default_font)).toString ())); - varedit_fontSize->setValue (settings->value (ve_font_size).toInt ()); + varedit_font->setCurrentFont (QFont (settings.value (ve_font_name.key, + settings.value (cs_font.key, default_font)).toString ())); + varedit_fontSize->setValue (settings.value (ve_font_size).toInt ()); connect (varedit_useTerminalFont, &QCheckBox::toggled, varedit_font, &QFontComboBox::setDisabled); connect (varedit_useTerminalFont, &QCheckBox::toggled, varedit_fontSize, &QSpinBox::setDisabled); - varedit_useTerminalFont->setChecked (settings->value (ve_use_terminal_font).toBool ()); + varedit_useTerminalFont->setChecked (settings.value (ve_use_terminal_font).toBool ()); varedit_font->setDisabled (varedit_useTerminalFont->isChecked ()); varedit_fontSize->setDisabled (varedit_useTerminalFont->isChecked ()); - varedit_alternate->setChecked (settings->value (ve_alternate_rows).toBool ()); + varedit_alternate->setChecked (settings.value (ve_alternate_rows).toBool ()); // variable editor colors - read_varedit_colors (settings); + read_varedit_colors (); // shortcuts shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); cb_prevent_readline_conflicts->setChecked ( - settings->value (sc_prevent_rl_conflicts.key, + settings.value (sc_prevent_rl_conflicts.key, sc_prevent_rl_conflicts.def).toBool ()); cb_prevent_readline_conflicts_menu->setChecked ( - settings->value (sc_prevent_rl_conflicts_menu.key, + settings.value (sc_prevent_rl_conflicts_menu.key, sc_prevent_rl_conflicts_menu.def).toBool ()); // initialize the tree view with all shortcut data @@ -457,7 +447,7 @@ #if defined (HAVE_QSCINTILLA) - int mode = settings->value (ed_color_mode).toInt (); + int mode = settings.value (ed_color_mode).toInt (); QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ()), group_box_editor_styles); @@ -469,7 +459,7 @@ pb_reload_default_colors->setToolTip (tr (settings_reload_styles_tooltip.toStdString ().data ())); color_picker *current_line_color = new color_picker ( - settings->value (ed_highlight_current_line_color.key + + settings.value (ed_highlight_current_line_color.key + settings_color_modes_ext[mode], ed_highlight_current_line_color.def).value (), this); current_line_color->setObjectName (ed_highlight_current_line_color.key); @@ -509,8 +499,8 @@ this, &settings_dialog::button_clicked); // restore last geometry - if (settings->contains (sd_geometry.key)) - restoreGeometry (settings->value (sd_geometry).toByteArray ()); + if (settings.contains (sd_geometry.key)) + restoreGeometry (settings.value (sd_geometry).toByteArray ()); else setGeometry (QRect (10, 50, 1000, 600)); } @@ -519,10 +509,9 @@ { if (tab.isEmpty ()) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (settings) - tabWidget->setCurrentIndex (settings->value (sd_last_tab).toInt ()); + gui_settings settings; + + tabWidget->setCurrentIndex (settings.value (sd_last_tab).toInt ()); } else { @@ -549,9 +538,10 @@ { // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts |= QFileDialog::DontUseNativeDialog; QString dir = QFileDialog::getExistingDirectory @@ -575,12 +565,12 @@ || button_role == QDialogButtonBox::AcceptRole) { // save last settings dialog's geometry and close - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + + gui_settings settings; - settings->setValue (sd_last_tab.key, tabWidget->currentIndex ()); - settings->setValue (sd_geometry.key, saveGeometry ()); - settings->sync (); + settings.setValue (sd_last_tab.key, tabWidget->currentIndex ()); + settings.setValue (sd_geometry.key, saveGeometry ()); + settings.sync (); close (); } @@ -655,8 +645,7 @@ { #if defined (HAVE_QSCINTILLA) - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; QCheckBox *cb_color_mode = group_box_editor_styles->findChild (ed_color_mode.key); @@ -671,12 +660,12 @@ if (def != settings_reload_default_colors_flag) { // Get current value from settings or the default - c_picker->set_color (settings->color_value (ed_highlight_current_line_color, m)); + c_picker->set_color (settings.color_value (ed_highlight_current_line_color, m)); } else { // Get the default value - c_picker->set_color (settings->get_color_value (ed_highlight_current_line_color.def, m)); + c_picker->set_color (settings.get_color_value (ed_highlight_current_line_color.def, m)); } } @@ -686,40 +675,40 @@ # if defined (HAVE_LEXER_OCTAVE) lexer = new QsciLexerOctave (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; # elif defined (HAVE_LEXER_MATLAB) lexer = new QsciLexerMatlab (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; # endif lexer = new QsciLexerCPP (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new QsciLexerJava (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new QsciLexerPerl (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new QsciLexerBatch (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new QsciLexerDiff (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new QsciLexerBash (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; lexer = new octave_txt_lexer (); - update_lexer (lexer, settings, m, def); + update_lexer (lexer, m, def); delete lexer; #else @@ -731,13 +720,12 @@ #if defined (HAVE_QSCINTILLA) - void settings_dialog::update_lexer (QsciLexer *lexer, gui_settings *settings, - int mode, int def) + void settings_dialog::update_lexer (QsciLexer *lexer, int mode, int def) { // Get lexer settings and copy from default settings if not yet // available in normal settings file resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.read_lexer_settings (lexer, settings, mode, def); + rmgr.read_lexer_settings (lexer, mode, def); // When reloading default styles, the style tabs do already exists. // Otherwise, check if they exist or not. @@ -757,7 +745,7 @@ { // This is not an update, call get_lexer_settings for building // the settings tab - get_lexer_settings (lexer, settings); + get_lexer_settings (lexer); return; } @@ -834,8 +822,7 @@ } - void settings_dialog::get_lexer_settings (QsciLexer *lexer, - gui_settings *settings) + void settings_dialog::get_lexer_settings (QsciLexer *lexer) { resource_manager& rmgr = m_octave_qobj.get_resource_manager (); @@ -925,13 +912,14 @@ scroll_area->setWidget (scroll_area_contents); tabs_editor_lexers->addTab (scroll_area, lexer->language ()); - tabs_editor_lexers->setCurrentIndex (settings->value (sd_last_editor_styles_tab).toInt ()); + gui_settings settings; + + tabs_editor_lexers->setCurrentIndex (settings.value (sd_last_editor_styles_tab).toInt ()); } - void settings_dialog::write_lexer_settings (QsciLexer *lexer, - gui_settings *settings) + void settings_dialog::write_lexer_settings (QsciLexer *lexer) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; QCheckBox *cb_color_mode = group_box_editor_styles->findChild (ed_color_mode.key); @@ -939,13 +927,16 @@ if (cb_color_mode && cb_color_mode->isChecked ()) mode = 1; - settings->setValue (ed_color_mode.key, mode); + settings.setValue (ed_color_mode.key, mode); QWidget *tab = tabs_editor_lexers-> findChild (QString (lexer->language ()) + "_styles"); int styles[ed_max_lexer_styles]; // array for saving valid styles // (enum is not continuous) + + resource_manager& rmgr = m_octave_qobj.get_resource_manager (); int max_style = rmgr.get_valid_lexer_styles (lexer, styles); + QFontComboBox *select_font; QSpinBox *font_size; QCheckBox *attrib_font[3]; @@ -955,11 +946,11 @@ color = findChild (ed_highlight_current_line_color.key); if (color) - settings->setValue (ed_highlight_current_line_color.key + settings.setValue (ed_highlight_current_line_color.key + settings_color_modes_ext[mode], color->color ()); QString default_font_name - = settings->value (global_mono_font).toString (); + = settings.value (global_mono_font).toString (); QFont default_font = QFont (default_font_name, 10, -1, 0); QColor default_color = QColor (); @@ -1024,19 +1015,18 @@ const std::string group = QString ("Scintilla" + settings_color_modes_ext[mode]).toStdString (); - lexer->writeSettings (*settings, group.c_str ()); + lexer->writeSettings (settings, group.c_str ()); - settings->setValue (sd_last_editor_styles_tab.key, - tabs_editor_lexers->currentIndex ()); - settings->sync (); + settings.setValue (sd_last_editor_styles_tab.key, + tabs_editor_lexers->currentIndex ()); + settings.sync (); } #endif void settings_dialog::write_changed_settings (bool closing) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; // the icon set QString widget_icon_set = "NONE"; @@ -1044,87 +1034,87 @@ widget_icon_set = "LETTER"; else if (general_icon_graphic->isChecked ()) widget_icon_set = "GRAPHIC"; - settings->setValue (dw_icon_set.key, widget_icon_set); + settings.setValue (dw_icon_set.key, widget_icon_set); // language QString language = comboBox_language->currentText (); if (language == tr ("System setting")) language = global_language.def.toString (); - settings->setValue (global_language.key, language); + settings.setValue (global_language.key, language); // style QString selected_style = combo_styles->currentText (); if (selected_style == global_style.def.toString ()) selected_style = global_style.def.toString (); - settings->setValue (global_style.key, selected_style); + settings.setValue (global_style.key, selected_style); // dock widget title bar - settings->setValue (dw_title_custom_style.key, cb_widget_custom_style->isChecked ()); - settings->setValue (dw_title_3d.key, sb_3d_title->value ()); - settings->setValue (dw_title_bg_color.key, m_widget_title_bg_color->color ()); - settings->setValue (dw_title_bg_color_active.key, m_widget_title_bg_color_active->color ()); - settings->setValue (dw_title_fg_color.key, m_widget_title_fg_color->color ()); - settings->setValue (dw_title_fg_color_active.key, m_widget_title_fg_color_active->color ()); + settings.setValue (dw_title_custom_style.key, cb_widget_custom_style->isChecked ()); + settings.setValue (dw_title_3d.key, sb_3d_title->value ()); + settings.setValue (dw_title_bg_color.key, m_widget_title_bg_color->color ()); + settings.setValue (dw_title_bg_color_active.key, m_widget_title_bg_color_active->color ()); + settings.setValue (dw_title_fg_color.key, m_widget_title_fg_color->color ()); + settings.setValue (dw_title_fg_color_active.key, m_widget_title_fg_color_active->color ()); // icon size and theme int icon_size = icon_size_large->isChecked () - icon_size_small->isChecked (); - settings->setValue (global_icon_size.key, icon_size); - settings->setValue (global_icon_theme_index.key, combo_box_icon_theme->currentIndex ()); + settings.setValue (global_icon_size.key, icon_size); + settings.setValue (global_icon_theme_index.key, combo_box_icon_theme->currentIndex ()); // native file dialogs - settings->setValue (global_use_native_dialogs.key, cb_use_native_file_dialogs->isChecked ()); + settings.setValue (global_use_native_dialogs.key, cb_use_native_file_dialogs->isChecked ()); // cursor blinking - settings->setValue (global_cursor_blinking.key, cb_cursor_blinking->isChecked ()); + settings.setValue (global_cursor_blinking.key, cb_cursor_blinking->isChecked ()); // focus follows mouse - settings->setValue (dw_focus_follows_mouse.key, cb_focus_follows_mouse->isChecked ()); + settings.setValue (dw_focus_follows_mouse.key, cb_focus_follows_mouse->isChecked ()); // promp to exit - settings->setValue (global_prompt_to_exit.key, cb_prompt_to_exit->isChecked ()); + settings.setValue (global_prompt_to_exit.key, cb_prompt_to_exit->isChecked ()); // status bar - settings->setValue (global_status_bar.key, cb_status_bar->isChecked ()); + settings.setValue (global_status_bar.key, cb_status_bar->isChecked ()); // Octave startup - settings->setValue (global_restore_ov_dir.key, cb_restore_octave_dir->isChecked ()); - settings->setValue (global_ov_startup_dir.key, le_octave_dir->text ()); + settings.setValue (global_restore_ov_dir.key, cb_restore_octave_dir->isChecked ()); + settings.setValue (global_ov_startup_dir.key, le_octave_dir->text ()); //editor - settings->setValue (global_use_custom_editor.key, useCustomFileEditor->isChecked ()); - settings->setValue (global_custom_editor.key, customFileEditor->text ()); - settings->setValue (ed_show_line_numbers.key, editor_showLineNumbers->isChecked ()); - settings->setValue (ed_line_numbers_size.key, editor_linenr_size->value ()); - settings->setValue (ed_highlight_current_line.key, editor_highlightCurrentLine->isChecked ()); - settings->setValue (ed_long_line_marker.key, editor_long_line_marker->isChecked ()); - settings->setValue (ed_long_line_marker_line.key, editor_long_line_marker_line->isChecked ()); - settings->setValue (ed_long_line_marker_background.key, editor_long_line_marker_background->isChecked ()); - settings->setValue (ed_long_line_column.key, editor_long_line_column->value ()); - settings->setValue (ed_break_lines.key, editor_break_checkbox->isChecked ()); - settings->setValue (ed_break_lines_comments.key, editor_break_comments_checkbox->isChecked ()); - settings->setValue (ed_wrap_lines.key, editor_wrap_checkbox->isChecked ()); - settings->setValue (ed_code_folding.key, cb_code_folding->isChecked ()); - settings->setValue (ed_show_edit_status_bar.key, cb_edit_status_bar->isChecked ()); - settings->setValue (ed_show_toolbar.key, cb_edit_tool_bar->isChecked ()); - settings->setValue (ed_highlight_all_occurrences.key, editor_highlight_all_occurrences->isChecked ()); - settings->setValue (ed_code_completion.key, editor_codeCompletion->isChecked ()); - settings->setValue (ed_code_completion_threshold.key, editor_spinbox_ac_threshold->value ()); - settings->setValue (ed_code_completion_keywords.key, editor_checkbox_ac_keywords->isChecked ()); - settings->setValue (ed_code_completion_octave_builtins.key, editor_checkbox_ac_builtins->isChecked ()); - settings->setValue (ed_code_completion_octave_functions.key, editor_checkbox_ac_functions->isChecked ()); - settings->setValue (ed_code_completion_document.key, editor_checkbox_ac_document->isChecked ()); - settings->setValue (ed_code_completion_case.key, editor_checkbox_ac_case->isChecked ()); - settings->setValue (ed_code_completion_replace.key, editor_checkbox_ac_replace->isChecked ()); - settings->setValue (ed_auto_endif.key, editor_auto_endif->currentIndex ()); - settings->setValue (ed_show_white_space.key, editor_ws_checkbox->isChecked ()); - settings->setValue (ed_show_white_space_indent.key, editor_ws_indent_checkbox->isChecked ()); - settings->setValue (ed_show_eol_chars.key, cb_show_eol->isChecked ()); - settings->setValue (ed_show_hscroll_bar.key, cb_show_hscrollbar->isChecked ()); - settings->setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ()); + settings.setValue (global_use_custom_editor.key, useCustomFileEditor->isChecked ()); + settings.setValue (global_custom_editor.key, customFileEditor->text ()); + settings.setValue (ed_show_line_numbers.key, editor_showLineNumbers->isChecked ()); + settings.setValue (ed_line_numbers_size.key, editor_linenr_size->value ()); + settings.setValue (ed_highlight_current_line.key, editor_highlightCurrentLine->isChecked ()); + settings.setValue (ed_long_line_marker.key, editor_long_line_marker->isChecked ()); + settings.setValue (ed_long_line_marker_line.key, editor_long_line_marker_line->isChecked ()); + settings.setValue (ed_long_line_marker_background.key, editor_long_line_marker_background->isChecked ()); + settings.setValue (ed_long_line_column.key, editor_long_line_column->value ()); + settings.setValue (ed_break_lines.key, editor_break_checkbox->isChecked ()); + settings.setValue (ed_break_lines_comments.key, editor_break_comments_checkbox->isChecked ()); + settings.setValue (ed_wrap_lines.key, editor_wrap_checkbox->isChecked ()); + settings.setValue (ed_code_folding.key, cb_code_folding->isChecked ()); + settings.setValue (ed_show_edit_status_bar.key, cb_edit_status_bar->isChecked ()); + settings.setValue (ed_show_toolbar.key, cb_edit_tool_bar->isChecked ()); + settings.setValue (ed_highlight_all_occurrences.key, editor_highlight_all_occurrences->isChecked ()); + settings.setValue (ed_code_completion.key, editor_codeCompletion->isChecked ()); + settings.setValue (ed_code_completion_threshold.key, editor_spinbox_ac_threshold->value ()); + settings.setValue (ed_code_completion_keywords.key, editor_checkbox_ac_keywords->isChecked ()); + settings.setValue (ed_code_completion_octave_builtins.key, editor_checkbox_ac_builtins->isChecked ()); + settings.setValue (ed_code_completion_octave_functions.key, editor_checkbox_ac_functions->isChecked ()); + settings.setValue (ed_code_completion_document.key, editor_checkbox_ac_document->isChecked ()); + settings.setValue (ed_code_completion_case.key, editor_checkbox_ac_case->isChecked ()); + settings.setValue (ed_code_completion_replace.key, editor_checkbox_ac_replace->isChecked ()); + settings.setValue (ed_auto_endif.key, editor_auto_endif->currentIndex ()); + settings.setValue (ed_show_white_space.key, editor_ws_checkbox->isChecked ()); + settings.setValue (ed_show_white_space_indent.key, editor_ws_indent_checkbox->isChecked ()); + settings.setValue (ed_show_eol_chars.key, cb_show_eol->isChecked ()); + settings.setValue (ed_show_hscroll_bar.key, cb_show_hscrollbar->isChecked ()); + settings.setValue (ed_default_eol_mode.key, combo_eol_mode->currentIndex ()); - settings->setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ()); - settings->setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ()); - settings->setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ()); + settings.setValue (ed_tab_position.key, editor_combox_tab_pos->currentIndex ()); + settings.setValue (ed_tabs_rotated.key, editor_cb_tabs_rotated->isChecked ()); + settings.setValue (ed_tabs_max_width.key, editor_sb_tabs_max_width->value ()); // Comment strings int rb_uncomment = 0; @@ -1132,56 +1122,56 @@ { if (m_rb_comment_strings[i]->isChecked ()) { - settings->setValue (ed_comment_str.key, i); + settings.setValue (ed_comment_str.key, i); if (i < 3) - settings->setValue (ed_comment_str_old.key, i); + settings.setValue (ed_comment_str_old.key, i); else - settings->setValue (ed_comment_str_old.key, ed_comment_str.def); + settings.setValue (ed_comment_str_old.key, ed_comment_str.def); } if (m_rb_uncomment_strings[i]->isChecked ()) rb_uncomment = rb_uncomment + (1 << i); } - settings->setValue (ed_uncomment_str.key, rb_uncomment); + settings.setValue (ed_uncomment_str.key, rb_uncomment); - settings->setValue (ed_default_enc.key, editor_combo_encoding->currentText ()); - settings->setValue (ed_auto_indent.key, editor_auto_ind_checkbox->isChecked ()); - settings->setValue (ed_tab_indents_line.key, editor_tab_ind_checkbox->isChecked ()); - settings->setValue (ed_backspace_unindents_line.key, editor_bs_unind_checkbox->isChecked ()); - settings->setValue (ed_show_indent_guides.key, editor_ind_guides_checkbox->isChecked ()); - settings->setValue (ed_indent_width.key, editor_ind_width_spinbox->value ()); - settings->setValue (ed_indent_uses_tabs.key, editor_ind_uses_tabs_checkbox->isChecked ()); - settings->setValue (ed_tab_width.key, editor_tab_width_spinbox->value ()); - settings->setValue (ed_restore_session.key, editor_restoreSession->isChecked ()); - settings->setValue (ed_create_new_file.key, editor_create_new_file->isChecked ()); - settings->setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ()); - settings->setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ()); - settings->setValue (ed_force_newline.key, editor_force_newline->isChecked ()); - settings->setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ()); - settings->setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ()); + settings.setValue (ed_default_enc.key, editor_combo_encoding->currentText ()); + settings.setValue (ed_auto_indent.key, editor_auto_ind_checkbox->isChecked ()); + settings.setValue (ed_tab_indents_line.key, editor_tab_ind_checkbox->isChecked ()); + settings.setValue (ed_backspace_unindents_line.key, editor_bs_unind_checkbox->isChecked ()); + settings.setValue (ed_show_indent_guides.key, editor_ind_guides_checkbox->isChecked ()); + settings.setValue (ed_indent_width.key, editor_ind_width_spinbox->value ()); + settings.setValue (ed_indent_uses_tabs.key, editor_ind_uses_tabs_checkbox->isChecked ()); + settings.setValue (ed_tab_width.key, editor_tab_width_spinbox->value ()); + settings.setValue (ed_restore_session.key, editor_restoreSession->isChecked ()); + settings.setValue (ed_create_new_file.key, editor_create_new_file->isChecked ()); + settings.setValue (ed_hiding_closes_files.key, editor_hiding_closes_files->isChecked ()); + settings.setValue (ed_always_reload_changed_files.key, editor_reload_changed_files->isChecked ()); + settings.setValue (ed_force_newline.key, editor_force_newline->isChecked ()); + settings.setValue (ed_rm_trailing_spaces.key, editor_remove_trailing_spaces->isChecked ()); + settings.setValue (ed_show_dbg_file.key, editor_show_dbg_file->isChecked ()); // file browser - settings->setValue (fb_sync_octdir.key, sync_octave_directory->isChecked ()); - settings->setValue (fb_restore_last_dir.key, cb_restore_file_browser_dir->isChecked ()); - settings->setValue (fb_startup_dir.key, le_file_browser_dir->text ()); - settings->setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ()); + settings.setValue (fb_sync_octdir.key, sync_octave_directory->isChecked ()); + settings.setValue (fb_restore_last_dir.key, cb_restore_file_browser_dir->isChecked ()); + settings.setValue (fb_startup_dir.key, le_file_browser_dir->text ()); + settings.setValue (fb_txt_file_ext.key, le_file_browser_extensions->text ()); // network - settings->setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ()); - settings->setValue (global_use_proxy.key, use_proxy_server->isChecked ()); - settings->setValue (global_proxy_type.key, proxy_type->currentText ()); - settings->setValue (global_proxy_host.key, proxy_host_name->text ()); - settings->setValue (global_proxy_port.key, proxy_port->text ()); - settings->setValue (global_proxy_user.key, proxy_username->text ()); - settings->setValue (global_proxy_pass.key, proxy_password->text ()); + settings.setValue (nr_allow_connection.key, checkbox_allow_web_connect->isChecked ()); + settings.setValue (global_use_proxy.key, use_proxy_server->isChecked ()); + settings.setValue (global_proxy_type.key, proxy_type->currentText ()); + settings.setValue (global_proxy_host.key, proxy_host_name->text ()); + settings.setValue (global_proxy_port.key, proxy_port->text ()); + settings.setValue (global_proxy_user.key, proxy_username->text ()); + settings.setValue (global_proxy_pass.key, proxy_password->text ()); // command window - settings->setValue (cs_font_size.key, terminal_fontSize->value ()); - settings->setValue (cs_font.key, terminal_fontName->currentFont ().family ()); - settings->setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ()); - settings->setValue (cs_focus_cmd.key, terminal_focus_command->isChecked ()); - settings->setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ()); - settings->setValue (cs_hist_buffer.key, terminal_history_buffer->value ()); - write_terminal_colors (settings); + settings.setValue (cs_font_size.key, terminal_fontSize->value ()); + settings.setValue (cs_font.key, terminal_fontName->currentFont ().family ()); + settings.setValue (cs_cursor_use_fgcol.key, terminal_cursorUseForegroundColor->isChecked ()); + settings.setValue (cs_focus_cmd.key, terminal_focus_command->isChecked ()); + settings.setValue (cs_dbg_location.key, terminal_print_dbg_location->isChecked ()); + settings.setValue (cs_hist_buffer.key, terminal_history_buffer->value ()); + write_terminal_colors (); // the cursor QString cursor_type; @@ -1191,7 +1181,7 @@ else cursor_type = cs_cursor.def.toString (); - settings->setValue (cs_cursor.key, cursor_type); + settings.setValue (cs_cursor.key, cursor_type); #if defined (HAVE_QSCINTILLA) // editor styles: create lexer, get dialog contents, and write settings @@ -1200,71 +1190,74 @@ #if defined (HAVE_LEXER_OCTAVE) lexer = new QsciLexerOctave (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; #elif defined (HAVE_LEXER_MATLAB) lexer = new QsciLexerMatlab (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; #endif lexer = new QsciLexerCPP (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new QsciLexerJava (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new QsciLexerPerl (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new QsciLexerBatch (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new QsciLexerDiff (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new QsciLexerBash (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; lexer = new octave_txt_lexer (); - write_lexer_settings (lexer, settings); + write_lexer_settings (lexer); delete lexer; #endif // Workspace - write_workspace_colors (settings); + write_workspace_colors (); // Variable editor - settings->setValue (ve_column_width.key, varedit_columnWidth->value ()); - settings->setValue (ve_row_height.key, varedit_rowHeight->value ()); - settings->setValue (ve_use_terminal_font.key, varedit_useTerminalFont->isChecked ()); - settings->setValue (ve_alternate_rows.key, varedit_alternate->isChecked ()); - settings->setValue (ve_font_name.key, varedit_font->currentFont ().family ()); - settings->setValue (ve_font_size.key, varedit_fontSize->value ()); - write_varedit_colors (settings); + settings.setValue (ve_column_width.key, varedit_columnWidth->value ()); + settings.setValue (ve_row_height.key, varedit_rowHeight->value ()); + settings.setValue (ve_use_terminal_font.key, varedit_useTerminalFont->isChecked ()); + settings.setValue (ve_alternate_rows.key, varedit_alternate->isChecked ()); + settings.setValue (ve_font_name.key, varedit_font->currentFont ().family ()); + settings.setValue (ve_font_size.key, varedit_fontSize->value ()); + write_varedit_colors (); // shortcuts - settings->setValue (sc_prevent_rl_conflicts.key, cb_prevent_readline_conflicts->isChecked ()); - settings->setValue (sc_prevent_rl_conflicts_menu.key, cb_prevent_readline_conflicts_menu->isChecked ()); + settings.setValue (sc_prevent_rl_conflicts.key, cb_prevent_readline_conflicts->isChecked ()); + settings.setValue (sc_prevent_rl_conflicts_menu.key, cb_prevent_readline_conflicts_menu->isChecked ()); + shortcut_manager& scmgr = m_octave_qobj.get_shortcut_manager (); scmgr.write_shortcuts (settings, closing); - settings->sync (); + settings.sync (); } - void settings_dialog::read_workspace_colors (gui_settings *settings) + void settings_dialog::read_workspace_colors (void) { + gui_settings settings; + // Construct the grid with all color related settings QGridLayout *style_grid = new QGridLayout (); QVector description (ws_colors_count); @@ -1273,7 +1266,7 @@ int column = 0; const int color_columns = 3; // place colors in so many columns int row = 0; - int mode = settings->value (ws_color_mode).toInt (); + int mode = settings.value (ws_color_mode).toInt (); m_ws_enable_colors = new QCheckBox (tr ("Enable attribute colors")); style_grid->addWidget (m_ws_enable_colors, row++, column, 1, 4); @@ -1283,7 +1276,7 @@ connect (m_ws_enable_colors, &QCheckBox::toggled, m_ws_hide_tool_tips, &QCheckBox::setEnabled); m_ws_hide_tool_tips->setChecked - (settings->value (ws_hide_tool_tips).toBool ()); + (settings.value (ws_hide_tool_tips).toBool ()); QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); @@ -1299,7 +1292,7 @@ pb_reload_default_colors, &QPushButton::setEnabled); style_grid->addWidget (pb_reload_default_colors, row+1, column++); - bool colors_enabled = settings->value (ws_enable_colors).toBool (); + bool colors_enabled = settings.value (ws_enable_colors).toBool (); for (int i = 0; i < ws_colors_count; i++) { @@ -1310,7 +1303,7 @@ connect (m_ws_enable_colors, &QCheckBox::toggled, description[i], &QLabel::setEnabled); - QColor setting_color = settings->color_value (ws_colors[i], mode); + QColor setting_color = settings.color_value (ws_colors[i], mode); color[i] = new color_picker (setting_color); color[i]->setObjectName (ws_colors[i].key); color[i]->setMinimumSize (30, 10); @@ -1354,8 +1347,7 @@ if (cb_color_mode && cb_color_mode->isChecked ()) m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; color_picker *c_picker; @@ -1367,21 +1359,23 @@ if (def != settings_reload_default_colors_flag) { // Get current value from settings or the default - c_picker->set_color (settings->color_value (ws_colors[i], m)); + c_picker->set_color (settings.color_value (ws_colors[i], m)); } else { // Get the default value - c_picker->set_color (settings->get_color_value (ws_colors[i].def, m)); + c_picker->set_color (settings.get_color_value (ws_colors[i].def, m)); } } } } - void settings_dialog::write_workspace_colors (gui_settings *settings) + void settings_dialog::write_workspace_colors (void) { - settings->setValue (ws_enable_colors.key, m_ws_enable_colors->isChecked ()); - settings->setValue (ws_hide_tool_tips.key, m_ws_hide_tool_tips->isChecked ()); + gui_settings settings; + + settings.setValue (ws_enable_colors.key, m_ws_enable_colors->isChecked ()); + settings.setValue (ws_hide_tool_tips.key, m_ws_hide_tool_tips->isChecked ()); QCheckBox *cb_color_mode = workspace_colors_box->findChild (ws_color_mode.key); @@ -1396,21 +1390,23 @@ { color = workspace_colors_box->findChild (ws_colors[i].key); if (color) - settings->set_color_value (ws_colors[i], color->color (), mode); + settings.set_color_value (ws_colors[i], color->color (), mode); } - settings->setValue (ws_color_mode.key, mode); + settings.setValue (ws_color_mode.key, mode); - settings->sync (); + settings.sync (); } - void settings_dialog::read_terminal_colors (gui_settings *settings) + void settings_dialog::read_terminal_colors (void) { + gui_settings settings; + QGridLayout *style_grid = new QGridLayout (); QVector description (cs_colors_count); QVector color (cs_colors_count); - int mode = settings->value (cs_color_mode).toInt (); + int mode = settings.value (cs_color_mode).toInt (); QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); @@ -1430,7 +1426,7 @@ description[i] = new QLabel (" " + tr (cs_color_names.at (i).toStdString ().data ())); description[i]->setAlignment (Qt::AlignRight); - QColor setting_color = settings->color_value (cs_colors[i], mode); + QColor setting_color = settings.color_value (cs_colors[i], mode); color[i] = new color_picker (setting_color); color[i]->setObjectName (cs_colors[i].key); color[i]->setMinimumSize (30, 10); @@ -1463,8 +1459,7 @@ if (cb_color_mode && cb_color_mode->isChecked ()) m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; color_picker *c_picker; @@ -1476,18 +1471,18 @@ if (def != settings_reload_default_colors_flag) { // Get current value from settings or the default - c_picker->set_color (settings->color_value (cs_colors[i], m)); + c_picker->set_color (settings.color_value (cs_colors[i], m)); } else { // Get the default value - c_picker->set_color (settings->get_color_value (cs_colors[i].def, m)); + c_picker->set_color (settings.get_color_value (cs_colors[i].def, m)); } } } } - void settings_dialog::write_terminal_colors (gui_settings *settings) + void settings_dialog::write_terminal_colors (void) { QCheckBox *cb_color_mode = terminal_colors_box->findChild (cs_color_mode.key); @@ -1496,27 +1491,31 @@ if (cb_color_mode && cb_color_mode->isChecked ()) mode = 1; + gui_settings settings; + color_picker *color; for (int i = 0; i < cs_color_names.size (); i++) { color = terminal_colors_box->findChild (cs_colors[i].key); if (color) - settings->set_color_value (cs_colors[i], color->color (), mode); + settings.set_color_value (cs_colors[i], color->color (), mode); } - settings->setValue (cs_color_mode.key, mode); + settings.setValue (cs_color_mode.key, mode); - settings->sync (); + settings.sync (); } - void settings_dialog::read_varedit_colors (gui_settings *settings) + void settings_dialog::read_varedit_colors (void) { + gui_settings settings; + QGridLayout *style_grid = new QGridLayout (); QVector description (ve_colors_count); QVector color (ve_colors_count); - int mode = settings->value (ve_color_mode).toInt (); + int mode = settings.value (ve_color_mode).toInt (); QCheckBox *cb_color_mode = new QCheckBox (tr (settings_color_modes.toStdString ().data ())); cb_color_mode->setToolTip (tr (settings_color_modes_tooltip.toStdString ().data ())); @@ -1537,7 +1536,7 @@ + tr (ve_color_names.at (i).toStdString ().data ())); description[i]->setAlignment (Qt::AlignRight); - QColor setting_color = settings->color_value (ve_colors[i], mode); + QColor setting_color = settings.color_value (ve_colors[i], mode); color[i] = new color_picker (setting_color); color[i]->setObjectName (ve_colors[i].key); color[i]->setMinimumSize (30, 10); @@ -1570,8 +1569,7 @@ if (cb_color_mode && cb_color_mode->isChecked ()) m = 1; - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; color_picker *c_picker; @@ -1583,18 +1581,18 @@ if (def != settings_reload_default_colors_flag) { // Get current value from settings or the default - c_picker->set_color (settings->color_value (ve_colors[i], m)); + c_picker->set_color (settings.color_value (ve_colors[i], m)); } else { // Get the default value - c_picker->set_color (settings->get_color_value (ve_colors[i].def, m)); + c_picker->set_color (settings.get_color_value (ve_colors[i].def, m)); } } } } - void settings_dialog::write_varedit_colors (gui_settings *settings) + void settings_dialog::write_varedit_colors (void) { QCheckBox *cb_color_mode = varedit_colors_box->findChild (ve_color_mode.key); @@ -1603,17 +1601,19 @@ if (cb_color_mode && cb_color_mode->isChecked ()) mode = 1; + gui_settings settings; + color_picker *color; for (int i = 0; i < ve_colors_count; i++) { color = varedit_colors_box->findChild (ve_colors[i].key); if (color) - settings->set_color_value (ve_colors[i], color->color (), mode); + settings.set_color_value (ve_colors[i], color->color (), mode); } - settings->setValue (ve_color_mode.key, mode); + settings.setValue (ve_color_mode.key, mode); - settings->sync (); + settings.sync (); } } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/settings-dialog.h --- a/libgui/src/settings-dialog.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/settings-dialog.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ #include "color-picker.h" #include "gui-preferences-ed.h" -#include "gui-settings.h" #include "ui-settings-dialog.h" class QsciLexer; @@ -84,21 +83,21 @@ private: #if defined (HAVE_QSCINTILLA) - void update_lexer (QsciLexer *lexer, gui_settings *settings, int mode, int def = 0); - void get_lexer_settings (QsciLexer *lexer, gui_settings *settings); - void write_lexer_settings (QsciLexer *lexer, gui_settings *settings); + void update_lexer (QsciLexer *lexer, int mode, int def = 0); + void get_lexer_settings (QsciLexer *lexer); + void write_lexer_settings (QsciLexer *lexer); #endif void write_changed_settings (bool closing); - void read_workspace_colors (gui_settings *settings); - void write_workspace_colors (gui_settings *settings); + void read_workspace_colors (void); + void write_workspace_colors (void); - void read_terminal_colors (gui_settings *settings); - void write_terminal_colors (gui_settings *settings); + void read_terminal_colors (void); + void write_terminal_colors (void); - void read_varedit_colors (gui_settings *settings); - void write_varedit_colors (gui_settings *settings); + void read_varedit_colors (void); + void write_varedit_colors (void); base_qobject& m_octave_qobj; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/shortcut-manager.cc --- a/libgui/src/shortcut-manager.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/shortcut-manager.cc Tue Dec 06 15:17:16 2022 -0500 @@ -42,10 +42,10 @@ #include #include -#include "octave-qobject.h" #include "shortcut-manager.h" #include "gui-preferences-global.h" #include "gui-preferences-sc.h" +#include "gui-settings.h" #include "error.h" namespace octave @@ -109,8 +109,7 @@ } - shortcut_manager::shortcut_manager (base_qobject& oct_qobj) - : m_octave_qobj (oct_qobj) + shortcut_manager::shortcut_manager (void) { setObjectName ("Shortcut_Manager"); @@ -122,10 +121,9 @@ void shortcut_manager::init_data (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - settings->setValue (sc_main_ctrld.key, false); // reset use fo ctrl-d + settings.setValue (sc_main_ctrld.key, false); // reset use fo ctrl-d // actions not related to specific menus or widgets @@ -309,7 +307,7 @@ } // write one or all actual shortcut set(s) into a settings file - void shortcut_manager::write_shortcuts (gui_settings *settings, + void shortcut_manager::write_shortcuts (gui_settings& settings, bool closing) { bool sc_ctrld = false; @@ -318,7 +316,7 @@ for (int i = 0; i < m_sc.count (); i++) // loop over all shortcuts { - settings->setValue (sc_group + "/" + m_sc.at (i).m_settings_key, + settings.setValue (sc_group + "/" + m_sc.at (i).m_settings_key, m_sc.at (i).m_actual_sc.toString ()); // special: check main-window for Ctrl-D (Terminal) if (m_sc.at (i).m_settings_key.startsWith (sc_main) @@ -326,7 +324,7 @@ sc_ctrld = true; } - settings->setValue (sc_main_ctrld.key, sc_ctrld); + settings.setValue (sc_main_ctrld.key, sc_ctrld); if (closing) { @@ -334,7 +332,7 @@ m_dialog = nullptr; // make sure it is zero again } - settings->sync (); // sync the settings file + settings.sync (); // sync the settings file } void shortcut_manager::set_shortcut (QAction *action, const sc_pref& scpref, @@ -355,9 +353,9 @@ if (index > -1 && index < m_sc.count ()) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - action->setShortcut (QKeySequence (settings->sc_value (scpref))); + gui_settings settings; + + action->setShortcut (QKeySequence (settings.sc_value (scpref))); } else qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; @@ -371,9 +369,9 @@ if (index > -1 && index < m_sc.count ()) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - sc->setKey (QKeySequence (settings->sc_value (scpref))); + gui_settings settings; + + sc->setKey (QKeySequence (settings.sc_value (scpref))); } else qDebug () << "Key: " << scpref.key << " not found in m_action_hash"; @@ -524,9 +522,10 @@ // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; if (action == OSC_IMPORT) @@ -554,15 +553,13 @@ else { if (action == OSC_IMPORT) - import_shortcuts (&osc_settings); // import (special action) + import_shortcuts (osc_settings); // import (special action) else if (action == OSC_EXPORT) - write_shortcuts (&osc_settings, false); // export, (save settings) + write_shortcuts (osc_settings, false); // export, (save settings) } } else - { - import_shortcuts (nullptr); - } + reset_default_shortcuts (); return true; } @@ -628,17 +625,16 @@ void shortcut_manager::init (const QString& description, const sc_pref& sc) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - QKeySequence actual = QKeySequence (settings->sc_value (sc)); + QKeySequence actual = QKeySequence (settings.sc_value (sc)); // append the new shortcut to the list shortcut_t shortcut_info; shortcut_info.m_description = description; shortcut_info.m_settings_key = sc.key; shortcut_info.m_actual_sc = actual; - shortcut_info.m_default_sc = settings->sc_def_value (sc); + shortcut_info.m_default_sc = settings.sc_def_value (sc); m_sc << shortcut_info; // insert shortcut in order to check for duplicates later @@ -651,7 +647,7 @@ = sc_main_file.mid (0, sc_main_file.indexOf ('_') + 1); if (sc.key.startsWith (main_group_prefix) && actual == QKeySequence (Qt::ControlModifier+Qt::Key_D)) - settings->setValue (sc_main_ctrld.key, true); + settings.setValue (sc_main_ctrld.key, true); } void shortcut_manager::shortcut_dialog (int index) @@ -745,27 +741,54 @@ m_dialog->exec (); } - // import a shortcut set from a given settings file or reset to - // the defaults (settings = 0) and refresh the tree view - void shortcut_manager::import_shortcuts (gui_settings *settings) + // import a shortcut set from a given settings file and refresh the + // tree view + void shortcut_manager::import_shortcuts (gui_settings& settings) { for (int i = 0; i < m_sc.count (); i++) { // update the list of all shortcuts - shortcut_t sc = m_sc.at (i); // make a copy + + // make a copy + shortcut_t sc = m_sc.at (i); - if (settings) - sc.m_actual_sc = QKeySequence ( // get new shortcut from settings - settings->value (sc_group + sc.m_settings_key,sc.m_actual_sc). - toString ()); // and use the old one as default - else - sc.m_actual_sc = QKeySequence (sc.m_default_sc); // get default shortcut + // get new shortcut from settings and use the old one as default + sc.m_actual_sc = QKeySequence (settings.value (sc_group + sc.m_settings_key, sc.m_actual_sc).toString ()); - m_sc.replace (i, sc); // replace the old with the new one + // replace the old with the new one + m_sc.replace (i, sc); // update the tree view - QTreeWidgetItem *tree_item = m_index_item_hash[i]; // get related tree item - tree_item->setText (2, sc.m_actual_sc.toString ()); // display new shortcut + // get related tree item + QTreeWidgetItem *tree_item = m_index_item_hash[i]; + + // display new shortcut + tree_item->setText (2, sc.m_actual_sc.toString ()); + } + } + + // reset to the defaults and refresh the tree view + void shortcut_manager::reset_default_shortcuts (void) + { + for (int i = 0; i < m_sc.count (); i++) + { + // update the list of all shortcuts + + // make a copy + shortcut_t sc = m_sc.at (i); + + // get default shortcut + sc.m_actual_sc = QKeySequence (sc.m_default_sc); + + // replace the old with the new one + m_sc.replace (i, sc); + + // update the tree view + // get related tree item + QTreeWidgetItem *tree_item = m_index_item_hash[i]; + + // display new shortcut + tree_item->setText (2, sc.m_actual_sc.toString ()); } } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/shortcut-manager.h --- a/libgui/src/shortcut-manager.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/shortcut-manager.h Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,7 @@ #include #include -#include "gui-settings.h" +#include "gui-preferences.h" namespace octave { @@ -61,7 +61,7 @@ }; - class base_qobject; + class gui_settings; class shortcut_manager : public QWidget { @@ -76,7 +76,7 @@ OSC_DEFAULT = 2 }; - shortcut_manager (base_qobject& oct_qobj); + shortcut_manager (void); // No copying! @@ -88,7 +88,7 @@ void init_data (void); - void write_shortcuts (gui_settings *settings, bool closing); + void write_shortcuts (gui_settings& settings, bool closing); void set_shortcut (QAction *action, const sc_pref& scpref, bool enable = true); @@ -108,7 +108,8 @@ void init (const QString&, const sc_pref& scpref); void shortcut_dialog (int); - void import_shortcuts (gui_settings *settings); + void import_shortcuts (gui_settings& settings); + void reset_default_shortcuts (void); bool overwrite_all_shortcuts (void); class shortcut_t @@ -155,8 +156,6 @@ QKeySequence m_default_sc; }; - base_qobject& m_octave_qobj; - QList m_sc; QHash m_shortcut_hash; QHash m_action_hash; diff -r 9089bd969b37 -r bd9da634f00d libgui/src/terminal-dock-widget.cc --- a/libgui/src/terminal-dock-widget.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/terminal-dock-widget.cc Tue Dec 06 15:17:16 2022 -0500 @@ -101,16 +101,16 @@ // Chose a reasonable size at startup in order to avoid truncated // startup messages - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + + gui_settings settings; QFont font = QFont (); font.setStyleHint (QFont::TypeWriter); - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); font.setFamily - (settings->value (cs_font.key, default_font).toString ()); + (settings.value (cs_font.key, default_font).toString ()); font.setPointSize - (settings->value (cs_font_size).toInt ()); + (settings.value (cs_font_size).toInt ()); QFontMetrics metrics(font); @@ -151,9 +151,9 @@ } #endif - void terminal_dock_widget::notice_settings (const gui_settings *settings) + void terminal_dock_widget::notice_settings (void) { - emit settings_changed (settings); + emit settings_changed (); } void terminal_dock_widget::init_command_prompt () diff -r 9089bd969b37 -r bd9da634f00d libgui/src/terminal-dock-widget.h --- a/libgui/src/terminal-dock-widget.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/terminal-dock-widget.h Tue Dec 06 15:17:16 2022 -0500 @@ -65,7 +65,7 @@ signals: - void settings_changed (const gui_settings *settings); + void settings_changed (void); // Note: the following four signals are // currently only used by the new experimental terminal widget. @@ -80,7 +80,7 @@ public slots: - void notice_settings (const gui_settings *settings); + void notice_settings (void); private: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/variable-editor.cc --- a/libgui/src/variable-editor.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/variable-editor.cc Tue Dec 06 15:17:16 2022 -0500 @@ -55,6 +55,7 @@ #include "gui-preferences-global.h" #include "gui-preferences-sc.h" #include "gui-preferences-ve.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "ovl.h" @@ -113,9 +114,10 @@ m_prev_geom = QRect (0, 0, 0, 0); QHBoxLayout *h_layout = m_title_widget->findChild (); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + + gui_settings settings; m_fullscreen_action - = new QAction (rmgr.icon ("view-fullscreen", false), "", this); + = new QAction (settings.icon ("view-fullscreen", false), "", this); m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); QToolButton *fullscreen_button = new QToolButton (m_title_widget); fullscreen_button->setDefaultAction (m_fullscreen_action); @@ -148,8 +150,8 @@ if (m_full_screen) { setGeometry (m_prev_geom); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false)); + gui_settings settings; + m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false)); m_full_screen = false; } m_fullscreen_action->setToolTip (tr (DOCKED_FULLSCREEN_BUTTON_TOOLTIP)); @@ -207,12 +209,12 @@ void variable_dock_widget::change_fullscreen (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; if (! m_full_screen) { m_prev_floating = isFloating (); - m_fullscreen_action->setIcon (rmgr.icon ("view-restore", false)); + m_fullscreen_action->setIcon (settings.icon ("view-restore", false)); if (m_prev_floating) m_fullscreen_action->setToolTip (tr ("Restore geometry")); else @@ -232,7 +234,7 @@ } else { - m_fullscreen_action->setIcon (rmgr.icon ("view-fullscreen", false)); + m_fullscreen_action->setIcon (settings.icon ("view-fullscreen", false)); setGeometry (m_prev_geom); if (m_prev_floating) m_fullscreen_action->setToolTip (tr (UNDOCKED_FULLSCREEN_BUTTON_TOOLTIP)); @@ -493,9 +495,10 @@ // FIXME: Remove, if for all common KDE versions (bug #54607) is resolved. int opts = 0; // No options by default. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); - if (! settings->value (global_use_native_dialogs).toBool ()) + + gui_settings settings; + + if (! settings.value (global_use_native_dialogs).toBool ()) opts = QFileDialog::DontUseNativeDialog; QString name = objectName (); @@ -642,31 +645,31 @@ variable_editor_view::add_edit_actions (QMenu *menu, const QString& qualifier_string) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - menu->addAction (rmgr.icon ("edit-cut"), + menu->addAction (settings.icon ("edit-cut"), tr ("Cut") + qualifier_string, this, &variable_editor_view::cutClipboard); - menu->addAction (rmgr.icon ("edit-copy"), + menu->addAction (settings.icon ("edit-copy"), tr ("Copy") + qualifier_string, this, &variable_editor_view::copyClipboard); - menu->addAction (rmgr.icon ("edit-paste"), + menu->addAction (settings.icon ("edit-paste"), tr ("Paste"), this, &variable_editor_view::pasteClipboard); menu->addSeparator (); - menu->addAction (rmgr.icon ("edit-delete"), + menu->addAction (settings.icon ("edit-delete"), tr ("Clear") + qualifier_string, this, &variable_editor_view::clearContent); - menu->addAction (rmgr.icon ("edit-delete"), + menu->addAction (settings.icon ("edit-delete"), tr ("Delete") + qualifier_string, this, &variable_editor_view::delete_selected); - menu->addAction (rmgr.icon ("document-new"), + menu->addAction (settings.icon ("document-new"), tr ("Variable from Selection"), this, &variable_editor_view::createVariable); } @@ -1203,13 +1206,8 @@ void variable_editor::edit_variable (const QString& name, const octave_value& val) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - if (m_stylesheet.isEmpty ()) - { - gui_settings *settings = rmgr.get_settings (); - notice_settings (settings); - } + notice_settings (); QDockWidget *existing_qdw = m_main->findChild (name); if (existing_qdw) @@ -1417,31 +1415,33 @@ } void - variable_editor::notice_settings (const gui_settings *settings) + variable_editor::notice_settings (void) { - m_main->notice_settings (settings); // update settings in parent main win + gui_settings settings; - m_default_width = settings->value (ve_column_width).toInt (); + m_main->notice_settings (); // update settings in parent main win - m_default_height = settings->value (ve_row_height).toInt (); + m_default_width = settings.value (ve_column_width).toInt (); + + m_default_height = settings.value (ve_row_height).toInt (); - m_alternate_rows = settings->value (ve_alternate_rows).toBool (); + m_alternate_rows = settings.value (ve_alternate_rows).toBool (); - m_use_terminal_font = settings->value (ve_use_terminal_font).toBool (); + m_use_terminal_font = settings.value (ve_use_terminal_font).toBool (); QString font_name; int font_size; - QString default_font = settings->value (global_mono_font).toString (); + QString default_font = settings.value (global_mono_font).toString (); if (m_use_terminal_font) { - font_name = settings->value (cs_font.key, default_font).toString (); - font_size = settings->value (cs_font_size).toInt (); + font_name = settings.value (cs_font.key, default_font).toString (); + font_size = settings.value (cs_font_size).toInt (); } else { - font_name = settings->value (ve_font_name.key, default_font).toString (); - font_size = settings->value (ve_font_size).toInt (); + font_name = settings.value (ve_font_name.key, default_font).toString (); + font_size = settings.value (ve_font_size).toInt (); } m_font = QFont (font_name, font_size); @@ -1450,11 +1450,11 @@ m_add_font_height = fm.height (); - int mode = settings->value (ve_color_mode).toInt (); + int mode = settings.value (ve_color_mode).toInt (); for (int i = 0; i < ve_colors_count; i++) { - QColor setting_color = settings->color_value (ve_colors[i], mode); + QColor setting_color = settings.color_value (ve_colors[i], mode); m_table_colors.replace (i, setting_color); } @@ -1464,7 +1464,7 @@ if (m_tool_bar) { - int size_idx = settings->value (global_icon_size).toInt (); + int size_idx = settings.value (global_icon_size).toInt (); size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2 QStyle *st = style (); @@ -1664,22 +1664,23 @@ m_tool_bar->setWindowTitle (tr ("Variable Editor Toolbar")); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); + gui_settings settings; - m_save_action = add_tool_bar_button (rmgr.icon ("document-save"), tr ("Save"), - this, SLOT (save ())); + m_save_action = add_tool_bar_button (settings.icon ("document-save"), + tr ("Save"), this, SLOT (save ())); addAction (m_save_action); m_save_action->setShortcutContext (Qt::WidgetWithChildrenShortcut); m_save_action->setStatusTip(tr("Save variable to a file")); - QAction *action = new QAction (rmgr.icon ("document-save-as"), tr ("Save in format ..."), m_tool_bar); + QAction *action = new QAction (settings.icon ("document-save-as"), + tr ("Save in format ..."), m_tool_bar); QToolButton *save_tool_button = new HoverToolButton (m_tool_bar); save_tool_button->setDefaultAction (action); save_tool_button->setText (tr ("Save in format ...")); save_tool_button->setToolTip (tr("Save variable to a file in different format")); - save_tool_button->setIcon (rmgr.icon ("document-save-as")); + save_tool_button->setIcon (settings.icon ("document-save-as")); save_tool_button->setPopupMode (QToolButton::InstantPopup); QMenu *save_menu = new ReturnFocusMenu (save_tool_button); @@ -1698,15 +1699,15 @@ m_tool_bar->addSeparator (); - action = add_tool_bar_button (rmgr.icon ("edit-cut"), tr ("Cut"), + action = add_tool_bar_button (settings.icon ("edit-cut"), tr ("Cut"), this, SLOT (cutClipboard ())); action->setStatusTip(tr("Cut data to clipboard")); - action = add_tool_bar_button (rmgr.icon ("edit-copy"), tr ("Copy"), + action = add_tool_bar_button (settings.icon ("edit-copy"), tr ("Copy"), this, SLOT (copyClipboard ())); action->setStatusTip(tr("Copy data to clipboard")); - action = add_tool_bar_button (rmgr.icon ("edit-paste"), tr ("Paste"), + action = add_tool_bar_button (settings.icon ("edit-paste"), tr ("Paste"), this, SLOT (pasteClipboard ())); action->setStatusTip(tr("Paste clipboard into variable data")); @@ -1716,14 +1717,15 @@ // QAction *print_action; /icons/fileprint.png // m_tool_bar->addSeparator (); - action = new QAction (rmgr.icon ("plot-xy-curve"), tr ("Plot"), m_tool_bar); + action = new QAction (settings.icon ("plot-xy-curve"), tr ("Plot"), + m_tool_bar); action->setToolTip (tr ("Plot Selected Data")); QToolButton *plot_tool_button = new HoverToolButton (m_tool_bar); plot_tool_button->setDefaultAction (action); plot_tool_button->setText (tr ("Plot")); plot_tool_button->setToolTip (tr ("Plot selected data")); - plot_tool_button->setIcon (rmgr.icon ("plot-xy-curve")); + plot_tool_button->setIcon (settings.icon ("plot-xy-curve")); plot_tool_button->setPopupMode (QToolButton::InstantPopup); @@ -1739,7 +1741,7 @@ m_tool_bar->addSeparator (); - action = add_tool_bar_button (rmgr.icon ("go-up"), tr ("Up"), this, + action = add_tool_bar_button (settings.icon ("go-up"), tr ("Up"), this, SLOT (levelUp ())); action->setStatusTip(tr("Go one level up in variable hierarchy")); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/variable-editor.h --- a/libgui/src/variable-editor.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/variable-editor.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,7 +32,6 @@ #include #include "dw-main-window.h" -#include "gui-settings.h" #include "octave-dock-widget.h" #include "qt-interpreter-events.h" #include "tab-bar.h" @@ -340,7 +339,7 @@ void callUpdate (const QModelIndex&, const QModelIndex&); - void notice_settings (const gui_settings *); + void notice_settings (void); void edit_variable (const QString& name, const octave_value& val); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/welcome-wizard.cc --- a/libgui/src/welcome-wizard.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/welcome-wizard.cc Tue Dec 06 15:17:16 2022 -0500 @@ -39,7 +39,7 @@ #include "gui-preferences-dw.h" #include "gui-preferences-nr.h" -#include "octave-qobject.h" +#include "gui-settings.h" #include "welcome-wizard.h" namespace octave @@ -53,10 +53,9 @@ return logo; }; - welcome_wizard::welcome_wizard (base_qobject& oct_qobj, QWidget *p) - : QDialog (p), m_octave_qobj (oct_qobj), m_page_ctor_list (), - m_page_list_iterator (), - m_current_page (initial_page::create (oct_qobj, this)), + welcome_wizard::welcome_wizard (QWidget *p) + : QDialog (p), m_page_ctor_list (), m_page_list_iterator (), + m_current_page (initial_page::create (this)), m_allow_web_connect_state (false), m_max_height (0), m_max_width (0) { @@ -117,7 +116,7 @@ delete m_current_page; delete layout (); - m_current_page = (*m_page_list_iterator) (m_octave_qobj, this); + m_current_page = (*m_page_list_iterator) (this); QVBoxLayout *new_layout = new QVBoxLayout (); setLayout (new_layout); @@ -143,23 +142,16 @@ { // Create default settings file. - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - rmgr.reload_settings (); - - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (settings) - { - settings->setValue (nr_allow_connection.key, - m_allow_web_connect_state); + settings.setValue (nr_allow_connection.key, m_allow_web_connect_state); - settings->sync (); - } + settings.sync (); QDialog::accept (); } - initial_page::initial_page (base_qobject& oct_qobj, welcome_wizard *wizard) + initial_page::initial_page (welcome_wizard *wizard) : QWidget (wizard), m_title (new QLabel (tr ("Welcome to Octave!"), this)), m_message (new QLabel (this)), @@ -171,7 +163,7 @@ ft.setPointSize (20); m_title->setFont (ft); - resource_manager& rmgr = oct_qobj.get_resource_manager (); + gui_settings settings; m_message->setText (tr ("\n" @@ -179,7 +171,7 @@ "Click 'Next' to create a configuration file and launch Octave.

\n" "

The configuration file is stored in
%1.

\n" ""). - arg (rmgr.get_settings_file ())); + arg (settings.file_name ())); m_message->setWordWrap (true); m_message->setMinimumWidth (400); @@ -217,8 +209,7 @@ connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); } - setup_community_news::setup_community_news (base_qobject&, - welcome_wizard *wizard) + setup_community_news::setup_community_news (welcome_wizard *wizard) : QWidget (wizard), m_title (new QLabel (tr ("Community News"), this)), m_message (new QLabel (this)), @@ -311,7 +302,7 @@ connect (m_cancel, &QPushButton::clicked, wizard, &welcome_wizard::reject); } - final_page::final_page (base_qobject&, welcome_wizard *wizard) + final_page::final_page (welcome_wizard *wizard) : QWidget (wizard), m_title (new QLabel (tr ("Enjoy!"), this)), m_message (new QLabel (this)), diff -r 9089bd969b37 -r bd9da634f00d libgui/src/welcome-wizard.h --- a/libgui/src/welcome-wizard.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/welcome-wizard.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,17 +32,15 @@ namespace octave { - class base_qobject; - class welcome_wizard : public QDialog { Q_OBJECT public: - typedef QWidget *(*page_creator_fptr) (base_qobject&, welcome_wizard *); + typedef QWidget *(*page_creator_fptr) (welcome_wizard *); - welcome_wizard (base_qobject& oct_qobj, QWidget *parent = nullptr); + welcome_wizard (QWidget *parent = nullptr); ~welcome_wizard (void) = default; @@ -50,8 +48,6 @@ private: - base_qobject& m_octave_qobj; - QList m_page_ctor_list; QList::iterator m_page_list_iterator; QWidget *m_current_page; @@ -77,14 +73,14 @@ public: - initial_page (base_qobject& oct_qobj, welcome_wizard *wizard); + initial_page (welcome_wizard *wizard); ~initial_page (void) = default; static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) + create (welcome_wizard *wizard) { - return new initial_page (oct_qobj, wizard); + return new initial_page (wizard); } private: @@ -103,14 +99,14 @@ public: - setup_community_news (base_qobject& oct_qobj, welcome_wizard *wizard); + setup_community_news (welcome_wizard *wizard); ~setup_community_news (void) = default; static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) + create (welcome_wizard *wizard) { - return new setup_community_news (oct_qobj, wizard); + return new setup_community_news (wizard); } private: @@ -132,14 +128,14 @@ public: - final_page (base_qobject& oct_qobj, welcome_wizard *wizard); + final_page (welcome_wizard *wizard); ~final_page (void) = default; static QWidget * - create (base_qobject& oct_qobj, welcome_wizard *wizard) + create (welcome_wizard *wizard) { - return new final_page (oct_qobj, wizard); + return new final_page (wizard); } private: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/workspace-model.cc --- a/libgui/src/workspace-model.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/workspace-model.cc Tue Dec 06 15:17:16 2022 -0500 @@ -33,7 +33,6 @@ #include "gui-preferences-ws.h" #include "gui-settings.h" -#include "octave-qobject.h" #include "workspace-model.h" #include "syminfo.h" @@ -198,15 +197,17 @@ } void - workspace_model::notice_settings (const gui_settings *settings) + workspace_model::notice_settings (void) { - m_enable_colors = settings->value (ws_enable_colors).toBool (); + gui_settings settings; - int mode = settings->value (ws_color_mode).toInt (); + m_enable_colors = settings.value (ws_enable_colors).toBool (); + + int mode = settings.value (ws_color_mode).toInt (); for (int i = 0; i < ws_colors_count; i++) { - QColor setting_color = settings->color_value (ws_colors[i], mode); + QColor setting_color = settings.color_value (ws_colors[i], mode); QPalette p (setting_color); m_storage_class_colors.replace (i, setting_color); diff -r 9089bd969b37 -r bd9da634f00d libgui/src/workspace-model.h --- a/libgui/src/workspace-model.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/workspace-model.h Tue Dec 06 15:17:16 2022 -0500 @@ -34,8 +34,6 @@ #include #include -#include "gui-settings.h" - #include "syminfo.h" // Defined for purposes of sending QList as part of signal. @@ -88,7 +86,7 @@ void clear_workspace (void); - void notice_settings (const gui_settings *); + void notice_settings (void); private: diff -r 9089bd969b37 -r bd9da634f00d libgui/src/workspace-view.cc --- a/libgui/src/workspace-view.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/workspace-view.cc Tue Dec 06 15:17:16 2022 -0500 @@ -42,6 +42,7 @@ #include #include "gui-preferences-ws.h" +#include "gui-settings.h" #include "octave-qobject.h" #include "octave-qtutils.h" #include "workspace-view.h" @@ -94,51 +95,46 @@ ws_layout->addWidget (m_view); ws_layout->setSpacing (0); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (settings) - { - m_filter_shown = settings->value (ws_filter_shown).toBool (); - m_filter_widget->setVisible (m_filter_shown); + m_filter_shown = settings.value (ws_filter_shown).toBool (); + m_filter_widget->setVisible (m_filter_shown); - ws_layout->setMargin (2); + ws_layout->setMargin (2); - // Set the empty widget to have our layout. - widget ()->setLayout (ws_layout); + // Set the empty widget to have our layout. + widget ()->setLayout (ws_layout); - // Initialize collapse/expand state of the workspace subcategories. + // Initialize collapse/expand state of the workspace subcategories. - //enable sorting (setting column and order after model was set) - m_view->setSortingEnabled (true); - // Initialize column order and width of the workspace - m_view->horizontalHeader ()->restoreState - (settings->value (ws_column_state.key).toByteArray ()); + //enable sorting (setting column and order after model was set) + m_view->setSortingEnabled (true); + // Initialize column order and width of the workspace + m_view->horizontalHeader ()->restoreState + (settings.value (ws_column_state.key).toByteArray ()); - // Set header properties for sorting - m_view->horizontalHeader ()->setSectionsClickable (true); - m_view->horizontalHeader ()->setSectionsMovable (true); - m_view->horizontalHeader ()->setSortIndicator ( - settings->value (ws_sort_column).toInt (), - static_cast (settings->value (ws_sort_order).toUInt ())); - // FIXME: use value instead of static cast after - // dropping support of Qt 5.4 + // Set header properties for sorting + m_view->horizontalHeader ()->setSectionsClickable (true); + m_view->horizontalHeader ()->setSectionsMovable (true); + m_view->horizontalHeader ()->setSortIndicator ( + settings.value (ws_sort_column).toInt (), + static_cast (settings.value (ws_sort_order).toUInt ())); + // FIXME: use value instead of static cast after + // dropping support of Qt 5.4 - m_view->horizontalHeader ()->setSortIndicatorShown (true); + m_view->horizontalHeader ()->setSortIndicatorShown (true); - m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); - connect (m_view->horizontalHeader (), - &QTableView::customContextMenuRequested, - this, &workspace_view::header_contextmenu_requested); + m_view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu); + connect (m_view->horizontalHeader (), + &QTableView::customContextMenuRequested, + this, &workspace_view::header_contextmenu_requested); - // Init state of the filter - m_filter->addItems (settings->value (ws_mru_list.key).toStringList ()); + // Init state of the filter + m_filter->addItems (settings.value (ws_mru_list.key).toStringList ()); - bool filter_state = - settings->value (ws_filter_active).toBool (); - m_filter_checkbox->setChecked (filter_state); - filter_activate (filter_state); - } + bool filter_state = settings.value (ws_filter_active).toBool (); + m_filter_checkbox->setChecked (filter_state); + filter_activate (filter_state); // Connect signals and slots. @@ -167,11 +163,12 @@ m_view->setModel (&m_filter_model); // set the sorting after the model is set, it would be ignored otherwise - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + + gui_settings settings; + m_view->sortByColumn ( - settings->value (ws_sort_column).toInt (), - static_cast (settings->value (ws_sort_order).toUInt ())); + settings.value (ws_sort_column).toInt (), + static_cast (settings.value (ws_sort_order).toUInt ())); // FIXME: use value instead of static cast after // dropping support of Qt 5.4 @@ -179,17 +176,19 @@ } void - workspace_view::notice_settings (const gui_settings *settings) + workspace_view::notice_settings (void) { - m_model->notice_settings (settings); // update colors of model first + gui_settings settings; + + m_model->notice_settings (); // update colors of model first for (int i = 0; i < ws_columns_shown.length (); i++) - m_view->setColumnHidden (i + 1, ! settings->value (ws_columns_shown_keys.at (i), true).toBool ()); + m_view->setColumnHidden (i + 1, ! settings.value (ws_columns_shown_keys.at (i), true).toBool ()); QString tool_tip; - if (settings->value (ws_enable_colors).toBool () - && ! settings->value (ws_hide_tool_tips).toBool ()) + if (settings.value (ws_enable_colors).toBool () + && ! settings.value (ws_hide_tool_tips).toBool ()) { tool_tip = QString (tr ("View the variables in the active workspace.
")); tool_tip += QString (tr ("Colors for variable attributes:")); @@ -211,29 +210,25 @@ void workspace_view::save_settings (void) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; - if (! settings) - return; - - settings->setValue (ws_column_state.key, - m_view->horizontalHeader ()->saveState ()); + settings.setValue (ws_column_state.key, + m_view->horizontalHeader ()->saveState ()); int sort_column = m_view->horizontalHeader ()->sortIndicatorSection (); Qt::SortOrder sort_order = m_view->horizontalHeader ()->sortIndicatorOrder (); - settings->setValue (ws_sort_column.key, sort_column); - settings->setValue (ws_sort_order.key, sort_order); + settings.setValue (ws_sort_column.key, sort_column); + settings.setValue (ws_sort_order.key, sort_order); - settings->setValue (ws_filter_active.key, m_filter_checkbox->isChecked ()); - settings->setValue (ws_filter_shown.key, m_filter_shown); + settings.setValue (ws_filter_active.key, m_filter_checkbox->isChecked ()); + settings.setValue (ws_filter_shown.key, m_filter_shown); QStringList mru; for (int i = 0; i < m_filter->count (); i++) mru.append (m_filter->itemText (i)); - settings->setValue (ws_mru_list.key, mru); + settings.setValue (ws_mru_list.key, mru); - settings->sync (); + settings.sync (); octave_dock_widget::save_settings (); } @@ -292,8 +287,7 @@ QMenu menu (this); QSignalMapper sig_mapper (this); - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; for (int i = 0; i < ws_columns_shown.length (); i++) { @@ -302,7 +296,7 @@ &sig_mapper, SLOT (map ())); sig_mapper.setMapping (action, i); action->setCheckable (true); - action->setChecked (settings->value (ws_columns_shown_keys.at (i), true).toBool ()); + action->setChecked (settings.value (ws_columns_shown_keys.at (i), true).toBool ()); } // FIXME: We could use @@ -328,16 +322,15 @@ void workspace_view::toggle_header (int col) { - resource_manager& rmgr = m_octave_qobj.get_resource_manager (); - gui_settings *settings = rmgr.get_settings (); + gui_settings settings; QString key = ws_columns_shown_keys.at (col); - bool shown = settings->value (key, true).toBool (); + bool shown = settings.value (key, true).toBool (); m_view->setColumnHidden (col + 1, shown); - settings->setValue (key, ! shown); - settings->sync (); + settings.setValue (key, ! shown); + settings.sync (); octave_dock_widget::save_settings (); } diff -r 9089bd969b37 -r bd9da634f00d libgui/src/workspace-view.h --- a/libgui/src/workspace-view.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libgui/src/workspace-view.h Tue Dec 06 15:17:16 2022 -0500 @@ -74,7 +74,7 @@ void setModel (workspace_model *model); - void notice_settings (const gui_settings *); + void notice_settings (void); void save_settings (void); diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/c-file-ptr-stream.h --- a/libinterp/corefcn/c-file-ptr-stream.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/c-file-ptr-stream.h Tue Dec 06 15:17:16 2022 -0500 @@ -232,39 +232,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::i_c_file_ptr_stream' instead") -typedef octave::i_c_file_ptr_stream i_c_file_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::o_c_file_ptr_stream' instead") -typedef octave::o_c_file_ptr_stream o_c_file_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::io_c_file_ptr_stream' instead") -typedef octave::io_c_file_ptr_stream io_c_file_ptr_stream; - -// FIXME: HAVE_ZLIB is not defined here because we do not (and should -// not) include config.h in this header file. We need to find a way to -// define this interface without exposing gzFile. Should this be a -// private header that can only be used if included after config.h in an -// Octave source file and not inside another header file? - -# if defined (HAVE_ZLIB) - -OCTAVE_DEPRECATED (7, "use 'octave::i_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - i_c_zfile_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::o_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - o_c_zfile_ptr_stream; - -OCTAVE_DEPRECATED (7, "use 'octave::io_c_zfile_ptr_stream' instead") -typedef octave::c_file_ptr_stream - io_c_zfile_ptr_stream; - -# endif - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/data.cc --- a/libinterp/corefcn/data.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/data.cc Tue Dec 06 15:17:16 2022 -0500 @@ -6523,7 +6523,7 @@ (@dots{}((@var{A1} * @var{A2}) * @var{A3}) * @dots{}) @end example -@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower} +@seealso{times, plus, minus, rdivide, mrdivide, mldivide, mpower, tensorprod} @end deftypefn */) { return binary_assoc_op_defun_body (octave_value::op_mul, diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/data.h --- a/libinterp/corefcn/data.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/data.h Tue Dec 06 15:17:16 2022 -0500 @@ -41,14 +41,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::do_class_concat' instead") -inline OCTINTERP_API octave_value -do_class_concat (const octave_value_list& ovl, const std::string& cattype, - int dim) -{ - return octave::do_class_concat (ovl, cattype, dim); -} #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/dot.cc --- a/libinterp/corefcn/dot.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/dot.cc Tue Dec 06 15:17:16 2022 -0500 @@ -91,7 +91,7 @@ the result is equivalent to @code{@var{X}' * @var{Y}}. Although, @code{dot} is defined for integer arrays, the output may differ from the expected result due to the limited range of integer objects. -@seealso{cross, divergence} +@seealso{cross, divergence, tensorprod} @end deftypefn */) { int nargin = args.length (); diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/error.cc --- a/libinterp/corefcn/error.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/error.cc Tue Dec 06 15:17:16 2022 -0500 @@ -901,17 +901,6 @@ last_error_stack (make_stack_map (ee.stack_info ())); } -// DEPRECATED in Octave 7. -void error_system::display_exception (const execution_exception& ee, - std::ostream& os) const -{ - if (m_beep_on_error) - os << "\a"; - - ee.display (octave_diary); - ee.display (os); -} - void error_system::display_exception (const execution_exception& ee) const { // FIXME: How should we handle beep_on_error? diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/error.h --- a/libinterp/corefcn/error.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/error.h Tue Dec 06 15:17:16 2022 -0500 @@ -334,13 +334,6 @@ OCTINTERP_API void save_exception (const execution_exception& ee); - // FIXME - //#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "second argument is no longer accepted") - OCTINTERP_API void display_exception (const execution_exception& ee, - std::ostream& os) const; - //#endif - OCTINTERP_API void display_exception (const execution_exception& ee) const; private: @@ -573,44 +566,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::defun_usage_message' instead") -inline void defun_usage_message (const std::string& msg) -{ - octave::defun_usage_message (msg); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead") -inline octave_value_list -set_warning_state (const std::string& id, const std::string& state) -{ - return octave::set_warning_state (id, state); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_warning_state' instead") -inline octave_value_list set_warning_state (const octave_value_list& args) -{ - return octave::set_warning_state (args); -} - -OCTAVE_DEPRECATED (7, "use 'octave::warning_enabled' instead") -inline int warning_enabled (const std::string& id) -{ - return octave::warning_enabled (id); -} - -OCTAVE_DEPRECATED (7, "use 'octave::disable_warning' instead") -inline void disable_warning (const std::string& id) -{ - octave::disable_warning (id); -} - -OCTAVE_DEPRECATED (7, "use 'octave::interpreter_try' instead") -inline void interpreter_try (octave::unwind_protect& uwp) -{ - octave::interpreter_try (uwp); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/graphics.in.h --- a/libinterp/corefcn/graphics.in.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/graphics.in.h Tue Dec 06 15:17:16 2022 -0500 @@ -6958,164 +6958,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_scaler' instead") -typedef octave::base_scaler base_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::lin_scaler' instead") -typedef octave::lin_scaler lin_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::log_scaler' instead") -typedef octave::log_scaler log_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::neg_log_scaler' instead") -typedef octave::neg_log_scaler neg_log_scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::scaler' instead") -typedef octave::scaler scaler; - -OCTAVE_DEPRECATED (7, "use 'octave::base_property' instead") -typedef octave::base_property base_property; - -OCTAVE_DEPRECATED (7, "use 'octave::string_property' instead") -typedef octave::string_property string_property; - -OCTAVE_DEPRECATED (7, "use 'octave::string_array_property' instead") -typedef octave::string_array_property string_array_property; - -OCTAVE_DEPRECATED (7, "use 'octave::text_label_property' instead") -typedef octave::text_label_property text_label_property; - -OCTAVE_DEPRECATED (7, "use 'octave::radio_values' instead") -typedef octave::radio_values radio_values; - -OCTAVE_DEPRECATED (7, "use 'octave::radio_property' instead") -typedef octave::radio_property radio_property; - -OCTAVE_DEPRECATED (7, "use 'octave::color_values' instead") -typedef octave::color_values color_values; - -OCTAVE_DEPRECATED (7, "use 'octave::color_property' instead") -typedef octave::color_property color_property; - -OCTAVE_DEPRECATED (7, "use 'octave::double_property' instead") -typedef octave::double_property double_property; - -OCTAVE_DEPRECATED (7, "use 'octave::double_radio_property' instead") -typedef octave::double_radio_property double_radio_property; - -OCTAVE_DEPRECATED (7, "use 'octave::array_property' instead") -typedef octave::array_property array_property; - -OCTAVE_DEPRECATED (7, "use 'octave::row_vector_property' instead") -typedef octave::row_vector_property row_vector_property; - -OCTAVE_DEPRECATED (7, "use 'octave::bool_property' instead") -typedef octave::bool_property bool_property; - -OCTAVE_DEPRECATED (7, "use 'octave::handle_property' instead") -typedef octave::handle_property handle_property; - -OCTAVE_DEPRECATED (7, "use 'octave::any_property' instead") -typedef octave::any_property any_property; - -OCTAVE_DEPRECATED (7, "use 'octave::children_property' instead") -typedef octave::children_property children_property; - -OCTAVE_DEPRECATED (7, "use 'octave::callback_property' instead") -typedef octave::callback_property callback_property; - -OCTAVE_DEPRECATED (7, "use 'octave::property' instead") -typedef octave::property property; - -OCTAVE_DEPRECATED (7, "use 'octave::pval_vector' instead") -typedef octave::pval_vector pval_vector; - -OCTAVE_DEPRECATED (7, "use 'octave::property_list' instead") -typedef octave::property_list property_list; - -OCTAVE_DEPRECATED (7, "use 'octave::base_properties' instead") -typedef octave::base_properties base_properties; - -OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_object' instead") -typedef octave::base_graphics_object base_graphics_object; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_object' instead") -typedef octave::graphics_object graphics_object; - -OCTAVE_DEPRECATED (7, "use 'octave::root_figure' instead") -typedef octave::root_figure root_figure; - -OCTAVE_DEPRECATED (7, "use 'octave::figure' instead") -typedef octave::figure figure; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_xform' instead") -typedef octave::graphics_xform graphics_xform; - -OCTAVE_DEPRECATED (7, "use 'octave::axes' instead") -typedef octave::axes axes; - -OCTAVE_DEPRECATED (7, "use 'octave::line' instead") -typedef octave::line line; - -OCTAVE_DEPRECATED (7, "use 'octave::text' instead") -typedef octave::text text; - -OCTAVE_DEPRECATED (7, "use 'octave::image' instead") -typedef octave::image image; - -OCTAVE_DEPRECATED (7, "use 'octave::light' instead") -typedef octave::light light; - -OCTAVE_DEPRECATED (7, "use 'octave::patch' instead") -typedef octave::patch patch; - -OCTAVE_DEPRECATED (7, "use 'octave::scatter' instead") -typedef octave::scatter scatter; - -OCTAVE_DEPRECATED (7, "use 'octave::surface' instead") -typedef octave::surface surface; - -OCTAVE_DEPRECATED (7, "use 'octave::hggroup' instead") -typedef octave::hggroup hggroup; - -OCTAVE_DEPRECATED (7, "use 'octave::uimenu' instead") -typedef octave::uimenu uimenu; - -OCTAVE_DEPRECATED (7, "use 'octave::uicontextmenu' instead") -typedef octave::uicontextmenu uicontextmenu; - -OCTAVE_DEPRECATED (7, "use 'octave::uicontrol' instead") -typedef octave::uicontrol uicontrol; - -OCTAVE_DEPRECATED (7, "use 'octave::uibuttongroup' instead") -typedef octave::uibuttongroup uibuttongroup; - -OCTAVE_DEPRECATED (7, "use 'octave::uipanel' instead") -typedef octave::uipanel uipanel; - -OCTAVE_DEPRECATED (7, "use 'octave::uitable' instead") -typedef octave::uitable uitable; - -OCTAVE_DEPRECATED (7, "use 'octave::uitoolbar' instead") -typedef octave::uitoolbar uitoolbar; - -OCTAVE_DEPRECATED (7, "use 'octave::uipushtool' instead") -typedef octave::uipushtool uipushtool; - -OCTAVE_DEPRECATED (7, "use 'octave::uitoggletool' instead") -typedef octave::uitoggletool uitoggletool; - -OCTAVE_DEPRECATED (7, "use 'octave::base_graphics_event' instead") -typedef octave::base_graphics_event base_graphics_event; - -OCTAVE_DEPRECATED (7, "use 'octave::graphics_event' instead") -typedef octave::graphics_event graphics_event; - -OCTAVE_DEPRECATED (7, "use 'octave::gh_manager' instead") -typedef octave::gh_manager gh_manager; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/hook-fcn.h --- a/libinterp/corefcn/hook-fcn.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/hook-fcn.h Tue Dec 06 15:17:16 2022 -0500 @@ -214,21 +214,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::base_hook_function' instead") -typedef octave::base_hook_function base_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::hook_function' instead") -typedef octave::hook_function hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::named_hook_function' instead") -typedef octave::named_hook_function named_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::fcn_handle_hook_function' instead") -typedef octave::fcn_handle_hook_function fcn_handle_hook_function; - -OCTAVE_DEPRECATED (7, "use 'octave::hook_function_list' instead") -typedef octave::hook_function_list hook_function_list; #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/kron.cc --- a/libinterp/corefcn/kron.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/kron.cc Tue Dec 06 15:17:16 2022 -0500 @@ -275,6 +275,7 @@ @noindent Since the Kronecker product is associative, this is well-defined. +@seealso{tensorprod} @end deftypefn */) { int nargin = args.length (); diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/load-save.cc --- a/libinterp/corefcn/load-save.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/load-save.cc Tue Dec 06 15:17:16 2022 -0500 @@ -2060,13 +2060,3 @@ } OCTAVE_END_NAMESPACE(octave) - -// DEPRECATED in Octave 7 - -void -dump_octave_core (void) -{ - octave::load_save_system& load_save_sys = octave::__get_load_save_system__ (); - - load_save_sys.dump_octave_core (); -} diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/load-save.h --- a/libinterp/corefcn/load-save.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/load-save.h Tue Dec 06 15:17:16 2022 -0500 @@ -294,7 +294,4 @@ OCTAVE_END_NAMESPACE(octave) -OCTAVE_DEPRECATED (7, "use 'load_save_system::dump_octave_core' instead") -extern OCTINTERP_API void dump_octave_core (void); - #endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/ls-ascii-helper.h --- a/libinterp/corefcn/ls-ascii-helper.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/ls-ascii-helper.h Tue Dec 06 15:17:16 2022 -0500 @@ -44,29 +44,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::skip_until_newline' instead") -inline void -skip_until_newline (std::istream& is, bool keep_newline = false) -{ - return octave::skip_until_newline (is, keep_newline); -} - -OCTAVE_DEPRECATED (7, "use 'octave::skip_preceding_newline' instead") -inline void -skip_preceeding_newline (std::istream& is) -{ - return octave::skip_preceeding_newline (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_until_newline' instead") -inline std::string -read_until_newline (std::istream& is, bool keep_newline = false) -{ - return octave::read_until_newline (is, keep_newline); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/ls-utils.h --- a/libinterp/corefcn/ls-utils.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/ls-utils.h Tue Dec 06 15:17:16 2022 -0500 @@ -40,22 +40,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead") -inline save_type -get_save_type (double max_val, double min_val) -{ - return octave::get_save_type (max_val, min_val); -} - -OCTAVE_DEPRECATED (7, "use 'octave::get_save_type' instead") -inline save_type -get_save_type (float max_val, float min_val) -{ - return octave::get_save_type (max_val, min_val); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-fstrm.h --- a/libinterp/corefcn/oct-fstrm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-fstrm.h Tue Dec 06 15:17:16 2022 -0500 @@ -90,11 +90,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::fstream' instead") -typedef octave::fstream octave_fstream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-hdf5-types.h --- a/libinterp/corefcn/oct-hdf5-types.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-hdf5-types.h Tue Dec 06 15:17:16 2022 -0500 @@ -38,16 +38,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::check_hdf5_types' instead") -inline bool check_hdf5_types (bool warn = true) -{ - return octave::check_hdf5_types (warn); -} - -#endif - #endif // Available for C and C++. diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-iostrm.h --- a/libinterp/corefcn/oct-iostrm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-iostrm.h Tue Dec 06 15:17:16 2022 -0500 @@ -161,17 +161,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_iostream' instead") -typedef octave::base_iostream octave_base_iostream; - -OCTAVE_DEPRECATED (7, "use 'octave::istream' instead") -typedef octave::istream octave_istream; - -OCTAVE_DEPRECATED (7, "use 'octave::ostream' instead") -typedef octave::ostream octave_ostream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-prcstrm.h --- a/libinterp/corefcn/oct-prcstrm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-prcstrm.h Tue Dec 06 15:17:16 2022 -0500 @@ -98,14 +98,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::octave_iprocstream' instead") -typedef octave::octave_iprocstream octave_iprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::octave_oprocstream' instead") -typedef octave::octave_oprocstream octave_oprocstream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-procbuf.h --- a/libinterp/corefcn/oct-procbuf.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-procbuf.h Tue Dec 06 15:17:16 2022 -0500 @@ -83,11 +83,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use octave::procbuf' instead") -typedef octave::procbuf procbuf; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-stdstrm.h --- a/libinterp/corefcn/oct-stdstrm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-stdstrm.h Tue Dec 06 15:17:16 2022 -0500 @@ -199,14 +199,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::stdiostream' instead") -typedef octave::stdiostream octave_stdiostream; - -OCTAVE_DEPRECATED (7, "use 'octave::zstdiostream' instead") -typedef octave::zstdiostream octave_zstdiostream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-stream.cc --- a/libinterp/corefcn/oct-stream.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-stream.cc Tue Dec 06 15:17:16 2022 -0500 @@ -4288,6 +4288,9 @@ { T value = T (); + is >> std::ws; // skip through whitespace and advance stream pointer + std::streampos pos = is.tellg (); + switch (fmt.type) { case 'o': @@ -4301,11 +4304,7 @@ case 'i': { - int c1 = std::istream::traits_type::eof (); - - while (is && (c1 = is.get ()) != std::istream::traits_type::eof () - && isspace (c1)) - ; // skip whitespace + int c1 = is.get (); if (c1 != std::istream::traits_type::eof ()) { @@ -4354,18 +4353,33 @@ break; } - // If conversion produces an integer that overflows, failbit is set but - // value is non-zero. We want to treat this case as success, so clear - // failbit from the stream state to keep going. - // FIXME: Maybe set error state on octave stream as above? Matlab does - // *not* indicate an error message on overflow. - if ((is.rdstate () & std::ios::failbit) && value != T ()) - is.clear (is.rdstate () & ~std::ios::failbit); - - // Only copy the converted value if the stream is in a state where we - // want to continue reading. - if (! (is.rdstate () & std::ios::failbit)) - *valptr = value; + std::ios::iostate status = is.rdstate (); + if (! (status & std::ios::failbit)) + { + // Copy the converted value if the stream is in a good state + *valptr = value; + } + else + { + if (value != T ()) + { + // If conversion produces an integer that overflows, failbit is set + // but value is non-zero. We want to treat this case as success, + // so clear failbit from the stream state to keep going. + // FIXME: Maybe set error state on octave stream? Matlab does + // *not* indicate an error message on overflow. + is.clear (status & ~std::ios::failbit); + *valptr = value; + } + else + { + // True error. + // Reset stream to original position, clear eof bit, pass status on. + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } + } return is; } @@ -4433,17 +4447,20 @@ case 'E': case 'G': { - int c1 = std::istream::traits_type::eof (); - - while (is && (c1 = is.get ()) != std::istream::traits_type::eof () - && isspace (c1)) - ; // skip whitespace - - if (c1 != std::istream::traits_type::eof ()) + is >> std::ws; // skip through whitespace and advance stream pointer + if (is.good ()) { - is.putback (c1); + std::streampos pos = is.tellg (); ref = read_value (is); + + std::ios::iostate status = is.rdstate (); + if (status & std::ios::failbit) + { + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } } } break; @@ -4497,11 +4514,16 @@ { \ int c = std::istream::traits_type::eof (); \ \ + /* get all whitespace characters */ \ while (is && (c = is.get ()) != std::istream::traits_type::eof () \ && isspace (c)) \ { /* skip whitespace */ } \ \ - if (c != std::istream::traits_type::eof ()) \ + if (c == std::istream::traits_type::eof ()) \ + /* reset failbit at eof */ \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ + else \ + /* put back non-whitespace character */ \ is.putback (c); \ } \ while (0) @@ -4566,8 +4588,8 @@ && (c = is.get ()) != std::istream::traits_type::eof ()) \ tmp[n++] = static_cast (c); \ \ - if (n > 0 && c == std::istream::traits_type::eof ()) \ - is.clear (); \ + if (c == std::istream::traits_type::eof ()) \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ tmp.resize (n) @@ -4609,8 +4631,8 @@ tmp[n++] = static_cast (c); \ } \ \ - if (n > 0 && c == std::istream::traits_type::eof ()) \ - is.clear (); \ + if (c == std::istream::traits_type::eof ()) \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ tmp.resize (n); \ } \ @@ -4623,15 +4645,13 @@ // This format must match a nonempty sequence of characters. #define BEGIN_CHAR_CLASS_CONVERSION() \ - int width = elt->width; \ + int width = (elt->width ? elt->width \ + : std::numeric_limits::max ()); \ \ std::string tmp; \ \ do \ { \ - if (! width) \ - width = std::numeric_limits::max (); \ - \ std::ostringstream buf; \ \ std::string char_class = elt->char_class; \ @@ -4642,29 +4662,39 @@ { \ int chars_read = 0; \ while (is && chars_read++ < width \ - && (c = is.get ()) != std::istream::traits_type::eof () \ - && char_class.find (c) != std::string::npos) \ - buf << static_cast (c); \ + && (c = is.get ()) != std::istream::traits_type::eof ()) \ + { \ + if (char_class.find (c) != std::string::npos) \ + buf << static_cast (c); \ + else \ + { \ + is.putback (c); \ + break; \ + } \ + } \ } \ else \ { \ int chars_read = 0; \ while (is && chars_read++ < width \ - && (c = is.get ()) != std::istream::traits_type::eof () \ - && char_class.find (c) == std::string::npos) \ - buf << static_cast (c); \ + && (c = is.get ()) != std::istream::traits_type::eof ()) \ + { \ + if (char_class.find (c) == std::string::npos) \ + buf << static_cast (c); \ + else \ + { \ + is.putback (c); \ + break; \ + } \ + } \ } \ \ - if (width == std::numeric_limits::max () \ - && c != std::istream::traits_type::eof ()) \ - is.putback (c); \ - \ tmp = buf.str (); \ \ if (tmp.empty ()) \ is.setstate (std::ios::failbit); \ else if (c == std::istream::traits_type::eof ()) \ - is.clear (); \ + is.clear (is.rdstate () & (~std::ios::failbit)); \ \ } \ while (0) @@ -4676,7 +4706,7 @@ tmp = string::u8_from_encoding (who, tmp, encoding ()); \ width = tmp.length (); \ \ - if (is) \ + if (is && width > 0) \ { \ int i = 0; \ \ @@ -5048,10 +5078,10 @@ // If it looks like we have a matching failure, then // reset the failbit in the stream state. - if (! is.eof () && is.rdstate () & std::ios::failbit) + if (is.rdstate () & std::ios::failbit) { - error (who, "format failed to match"); is.clear (is.rdstate () & (~std::ios::failbit)); + error (who, "format failed to match"); } // FIXME: is this the right thing to do? diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/oct-strstrm.h --- a/libinterp/corefcn/oct-strstrm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/oct-strstrm.h Tue Dec 06 15:17:16 2022 -0500 @@ -194,17 +194,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::base_strstream' instead") -typedef octave::base_strstream octave_base_strstream; - -OCTAVE_DEPRECATED (7, "use 'octave::istrstream' instead") -typedef octave::istrstream octave_istrstream; - -OCTAVE_DEPRECATED (7, "use 'octave::ostrstream' instead") -typedef octave::ostrstream octave_ostrstream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/procstream.h --- a/libinterp/corefcn/procstream.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/procstream.h Tue Dec 06 15:17:16 2022 -0500 @@ -187,20 +187,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::procstreambase' instead") -typedef octave::procstreambase procstreambase; - -OCTAVE_DEPRECATED (7, "use 'octave::iprocstream' instead") -typedef octave::iprocstream iprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::oprocstream' instead") -typedef octave::oprocstream oprocstream; - -OCTAVE_DEPRECATED (7, "use 'octave::procstream' instead") -typedef octave::procstream procstream; - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/sparse-xdiv.h --- a/libinterp/corefcn/sparse-xdiv.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/sparse-xdiv.h Tue Dec 06 15:17:16 2022 -0500 @@ -104,207 +104,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const Matrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseMatrix -xdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseMatrix -xdiv (const SparseMatrix& a, const DiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const DiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline SparseComplexMatrix -xdiv (const SparseComplexMatrix& a, const ComplexDiagMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline Matrix -x_el_div (double a, const SparseMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (double a, const SparseComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex& a, const SparseMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex& a, const SparseComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const SparseMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseMatrix -xleftdiv (const SparseMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseMatrix -xleftdiv (const DiagMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const SparseMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const DiagMatrix& a, const SparseComplexMatrix& b, MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline SparseComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const SparseComplexMatrix& b, - MatrixType& typ) -{ - return octave::xleftdiv (a, b, typ); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/sparse-xpow.h --- a/libinterp/corefcn/sparse-xpow.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/sparse-xpow.h Tue Dec 06 15:17:16 2022 -0500 @@ -62,106 +62,4 @@ OCTAVE_END_NAMESPACE(octave) -#if (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const SparseMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const SparseComplexMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseMatrix& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const SparseMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const SparseComplexMatrix& a, const SparseComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/variables.h --- a/libinterp/corefcn/variables.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/variables.h Tue Dec 06 15:17:16 2022 -0500 @@ -107,91 +107,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::symbol_exist' instead") -inline int -symbol_exist (const std::string& name, const std::string& type = "any") -{ - return octave::symbol_exist (name, type); -} - -OCTAVE_DEPRECATED (7, "use 'octave::unique_symbol_name' instead") -inline std::string -unique_symbol_name (const std::string& basename) -{ - return octave::unique_symbol_name (basename); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (bool& var, const octave_value_list& args, int nargout, - const char *nm) -{ - return octave::set_internal_variable (var, args, nargout, nm); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (char& var, const octave_value_list& args, int nargout, - const char *nm) -{ - return octave::set_internal_variable (var, args, nargout, nm); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (int& var, const octave_value_list& args, int nargout, - const char *nm, - int minval = std::numeric_limits::min (), - int maxval = std::numeric_limits::max ()) -{ - return octave::set_internal_variable (var, args, nargout, nm, minval, maxval); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (double& var, const octave_value_list& args, int nargout, - const char *nm, - double minval = -octave::numeric_limits::Inf (), - double maxval = octave::numeric_limits::Inf ()) -{ - return octave::set_internal_variable (var, args, nargout, nm, minval, maxval); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (std::string& var, const octave_value_list& args, - int nargout, const char *nm, bool empty_ok = true) -{ - return octave::set_internal_variable (var, args, nargout, nm, empty_ok); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (std::string& var, const octave_value_list& args, - int nargout, const char *nm, const char **choices) -{ - return octave::set_internal_variable (var, args, nargout, nm, choices); -} - -OCTAVE_DEPRECATED (7, "use 'octave::set_internal_variable' instead") -inline octave_value -set_internal_variable (int& var, const octave_value_list& args, int nargout, - const char *nm, const char **choices) -{ - return octave::set_internal_variable (var, args, nargout, nm, choices); -} - -OCTAVE_DEPRECATED (7, "use 'octave::maybe_missing_function_hook' instead") -inline std::string -maybe_missing_function_hook (const std::string& name) -{ - return octave::maybe_missing_function_hook (name); -} - -#endif - // The following macros should also be considered obsolete. #define SET_INTERNAL_VARIABLE(NM) \ diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/xdiv.h --- a/libinterp/corefcn/xdiv.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/xdiv.h Tue Dec 06 15:17:16 2022 -0500 @@ -156,415 +156,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const Matrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const Matrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const ComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline Matrix -x_el_div (double a, const Matrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (double a, const ComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex a, const Matrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexMatrix -x_el_div (const Complex a, const ComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline NDArray -x_el_div (double a, const NDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (double a, const ComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (const Complex a, const NDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline ComplexNDArray -x_el_div (const Complex a, const ComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const Matrix& a, const Matrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const Matrix& a, const ComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexMatrix& a, const Matrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexMatrix& a, const ComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatMatrix -xdiv (const FloatMatrix& a, const FloatMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatMatrix& a, const FloatComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, MatrixType& typ) -{ - return octave::xdiv (a, b, typ); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatMatrix -x_el_div (float a, const FloatMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (float a, const FloatComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (const FloatComplex a, const FloatMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexMatrix -x_el_div (const FloatComplex a, const FloatComplexMatrix& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatNDArray -x_el_div (float a, const FloatNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (float a, const FloatComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (const FloatComplex a, const FloatNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xdiv' instead") -inline FloatComplexNDArray -x_el_div (const FloatComplex a, const FloatComplexNDArray& b) -{ - return octave::elem_xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatMatrix -xleftdiv (const FloatMatrix& a, const FloatMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatMatrix& a, const FloatComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexMatrix& a, const FloatMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexMatrix& a, const FloatComplexMatrix& b, - MatrixType& typ, blas_trans_type transt = blas_no_trans) -{ - return octave::xleftdiv (a, b, typ, transt); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline Matrix -xdiv (const Matrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexMatrix -xdiv (const ComplexMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline DiagMatrix -xdiv (const DiagMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexDiagMatrix -xdiv (const ComplexDiagMatrix& a, const DiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline ComplexDiagMatrix -xdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatMatrix -xdiv (const FloatMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexMatrix -xdiv (const FloatComplexMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatDiagMatrix -xdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexDiagMatrix -xdiv (const FloatComplexDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xdiv' instead") -inline FloatComplexDiagMatrix -xdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline Matrix -xleftdiv (const DiagMatrix& a, const Matrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const DiagMatrix& a, const ComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexMatrix -xleftdiv (const ComplexDiagMatrix& a, const ComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline DiagMatrix -xleftdiv (const DiagMatrix& a, const DiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexDiagMatrix -xleftdiv (const DiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline ComplexDiagMatrix -xleftdiv (const ComplexDiagMatrix& a, const ComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexMatrix -xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatDiagMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexDiagMatrix -xleftdiv (const FloatDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xleftdiv' instead") -inline FloatComplexDiagMatrix -xleftdiv (const FloatComplexDiagMatrix& a, const FloatComplexDiagMatrix& b) -{ - return octave::xleftdiv (a, b); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/xnorm.h --- a/libinterp/corefcn/xnorm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/xnorm.h Tue Dec 06 15:17:16 2022 -0500 @@ -48,36 +48,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline octave_value -xnorm (const octave_value& x, const octave_value& p) -{ - return octave::xnorm (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline octave_value -xcolnorms (const octave_value& x, const octave_value& p) -{ - return octave::xcolnorms (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline octave_value -xrownorms (const octave_value& x, const octave_value& p) -{ - return octave::xrownorms (x, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline octave_value -xfrobnorm (const octave_value& x) -{ - return octave::xfrobnorm (x); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/corefcn/xpow.h --- a/libinterp/corefcn/xpow.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/corefcn/xpow.h Tue Dec 06 15:17:16 2022 -0500 @@ -44,7 +44,6 @@ class ComplexNDArray; class FloatComplexNDArray; class octave_value; -class Range; OCTAVE_BEGIN_NAMESPACE(octave) @@ -209,589 +208,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const Matrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (double a, const ComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Matrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Matrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const DiagMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const DiagMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const PermMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const Matrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const Complex& a, const ComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexDiagMatrix& a, double b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const ComplexDiagMatrix& a, const Complex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const octave::range& r) -{ - return octave::elem_xpow (a, r); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Matrix& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const octave::range& r) -{ - return octave::elem_xpow (a, r); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const Matrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexMatrix& a, const ComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (double a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const NDArray& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const Complex& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, double b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const NDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const Complex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const ComplexNDArray& a, const ComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (float a, const FloatComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatDiagMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatDiagMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplex& a, const FloatComplexMatrix& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexDiagMatrix& a, float b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xpow' instead") -inline octave_value -xpow (const FloatComplexDiagMatrix& a, const FloatComplex& b) -{ - return octave::xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatMatrix& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexMatrix& a, const FloatComplexMatrix& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (float a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatNDArray& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplex& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, float b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatNDArray& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatComplex& b) -{ - return octave::elem_xpow (a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::elem_xpow' instead") -inline octave_value -elem_xpow (const FloatComplexNDArray& a, const FloatComplexNDArray& b) -{ - return octave::elem_xpow (a, b); -} - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/mk-builtins.pl --- a/libinterp/mk-builtins.pl Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/mk-builtins.pl Tue Dec 06 15:17:16 2022 -0500 @@ -150,23 +150,6 @@ print "\nOCTAVE_END_NAMESPACE(octave)\n"; - print "\n#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS)\n\n"; - - foreach $name (sort (@fcn_names)) - { - print "OCTAVE_DEPRECATED (7, \"use 'octave::$name' instead\") -inline octave_value_list -$name (const octave_value_list& args = octave_value_list (), int nargout = 0) -{ - return octave::$name (args, nargout); -} - -"; - } - - ## end OCTAVE_PROVIDE_DEPRECATED_SYMBOLS block - print "\n\n#endif\n"; - print "\n#endif\n"; } elsif ($make_source) diff -r 9089bd969b37 -r bd9da634f00d libinterp/module.mk --- a/libinterp/module.mk Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/module.mk Tue Dec 06 15:17:16 2022 -0500 @@ -176,11 +176,6 @@ LIBINTERP_DEFUN_FILES += \ $(BUILT_IN_DEFUN_FILES) -## FIXME: The following two variables are deprecated and should be removed -## in Octave version 3.12. -DLL_CDEFS = @OCTINTERP_DLL_DEFS@ -DLL_CXXDEFS = @OCTINTERP_DLL_DEFS@ - ## Rules to build test files LIBINTERP_TST_FILES_SRC := $(shell $(SHELL) $(srcdir)/build-aux/find-files-with-tests.sh "$(srcdir)" $(ULT_DIST_SRC) $(DLDFCN_SRC)) diff -r 9089bd969b37 -r bd9da634f00d libinterp/octave-value/ov-legacy-range.cc --- a/libinterp/octave-value/ov-legacy-range.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/octave-value/ov-legacy-range.cc Tue Dec 06 15:17:16 2022 -0500 @@ -31,6 +31,7 @@ #include #include +#include "Range.h" #include "lo-ieee.h" #include "lo-utils.h" @@ -49,23 +50,326 @@ #include "ls-hdf5.h" #include "ls-utils.h" -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif +class +Range +{ +public: + + Range (void) + : m_base (0), m_limit (0), m_inc (0), m_numel (0) + { } + + // Assume range is already properly constructed, so just copy internal + // values. However, we set LIMIT to the computed final value because + // that mimics the behavior of the other Range class constructors that + // reset limit to the computed final value. + + Range (const octave::range& r) + : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()), + m_numel (r.numel ()) + { } + + Range (const Range& r) = default; + + Range& operator = (const Range& r) = default; + + ~Range (void) = default; + + Range (double b, double l) + : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ()) + { + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); + } + + Range (double b, double l, double i) + : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ()) + { + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); + } + + // The range has a finite number of elements. + bool ok (void) const + { + return (octave::math::isfinite (m_limit) + && (m_numel >= 0 || m_numel == -2)); + } + + double base (void) const { return m_base; } + double limit (void) const { return m_limit; } + double increment (void) const { return m_inc; } + + octave_idx_type numel (void) const { return m_numel; } + + bool all_elements_are_ints (void) const; + + Matrix matrix_value (void) const; + + double min (void) const; + double max (void) const; + +private: + + double m_base; + double m_limit; + double m_inc; + + octave_idx_type m_numel; + + octave_idx_type numel_internal (void) const; + + double limit_internal (void) const; + + void init (void); +}; + +bool +Range::all_elements_are_ints (void) const +{ + // If the base and increment are ints, the final value in the range will also + // be an integer, even if the limit is not. If there is one or fewer + // elements only the base needs to be an integer. + + return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc)) + && (octave::math::nint_big (m_base) == m_base || m_numel < 1) + && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1)); +} + +Matrix +Range::matrix_value (void) const +{ + Matrix retval (1, m_numel); + + if (m_numel > 0) + { + // The first element must always be *exactly* the base. + // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). + retval(0) = m_base; + + double b = m_base; + double increment = m_inc; + for (octave_idx_type i = 1; i < m_numel - 1; i++) + retval.xelem (i) = b + i * increment; + + retval.xelem (m_numel - 1) = m_limit; + } + + return retval; +} + +// NOTE: max and min only return useful values if numel > 0. +// do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0. + +double +Range::min (void) const +{ + double retval = 0.0; + if (m_numel > 0) + { + if (m_inc > 0) + retval = m_base; + else + { + retval = m_base + (m_numel - 1) * m_inc; + + // Require '<=' test. See note in max (). + if (retval <= m_limit) + retval = m_limit; + } + + } + return retval; +} + +double +Range::max (void) const +{ + double retval = 0.0; + if (m_numel > 0) + { + if (m_inc > 0) + { + retval = m_base + (m_numel - 1) * m_inc; + + // On some machines (x86 with extended precision floating point + // arithmetic, for example) it is possible that we can overshoot the + // limit by approximately the machine precision even though we were + // very careful in our calculation of the number of elements. + // Therefore, we clip the result to the limit if it overshoots. + // The test also includes equality (>= m_limit) to have expressions + // such as -5:1:-0 result in a -0 endpoint. + if (retval >= m_limit) + retval = m_limit; + } + else + retval = m_base; + } + return retval; +} + +// C See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5. +// C +// C===Tolerant FLOOR function. +// C +// C X - is given as a Double Precision argument to be operated on. +// C It is assumed that X is represented with M mantissa bits. +// C CT - is given as a Comparison Tolerance such that +// C 0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between +// C X and A whole number is less than CT, then TFLOOR is +// C returned as this whole number. By treating the +// C floating-point numbers as a finite ordered set note that +// C the heuristic EPS=2.**(-(M-1)) and CT=3*EPS causes +// C arguments of TFLOOR/TCEIL to be treated as whole numbers +// C if they are exactly whole numbers or are immediately +// C adjacent to whole number representations. Since EPS, the +// C "distance" between floating-point numbers on the unit +// C interval, and M, the number of bits in X'S mantissa, exist +// C on every floating-point computer, TFLOOR/TCEIL are +// C consistently definable on every floating-point computer. +// C +// C For more information see the following references: +// C (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL QUOTE +// C QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5. +// C (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling", APL +// C QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through +// C FL5, the history of five years of evolutionary development of +// C FL5 - the seven lines of code below - by open collaboration +// C and corroboration of the mathematical-computing community. +// C +// C Penn State University Center for Academic Computing +// C H. D. Knoble - August, 1978. + +static inline double +tfloor (double x, double ct) +{ +// C---------FLOOR(X) is the largest integer algebraically less than +// C or equal to X; that is, the unfuzzy FLOOR function. + +// DINT (X) = X - DMOD (X, 1.0); +// FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); + +// C---------Hagerty's FL5 function follows... + + double q = 1.0; + + if (x < 0.0) + q = 1.0 - ct; + + double rmax = q / (2.0 - ct); + + double t1 = 1.0 + std::floor (x); + t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1); + t1 = (rmax < t1 ? rmax : t1); + t1 = (ct > t1 ? ct : t1); + t1 = std::floor (x + t1); + + if (x <= 0.0 || (t1 - x) < rmax) + return t1; + else + return t1 - 1.0; +} + +static inline bool +teq (double u, double v, + double ct = 3.0 * std::numeric_limits::epsilon ()) +{ + double tu = std::abs (u); + double tv = std::abs (v); + + return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); +} + +octave_idx_type +Range::numel_internal (void) const +{ + octave_idx_type retval = -1; + + if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc) + || octave::math::isnan (m_limit)) + retval = -2; + else if (octave::math::isinf (m_limit) + && ((m_inc > 0 && m_limit > 0) + || (m_inc < 0 && m_limit < 0))) + retval = std::numeric_limits::max () - 1; + else if (m_inc == 0 + || (m_limit > m_base && m_inc < 0) + || (m_limit < m_base && m_inc > 0)) + { + retval = 0; + } + else + { + double ct = 3.0 * std::numeric_limits::epsilon (); + + double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct); + + octave_idx_type n_elt = (tmp > 0.0 + ? static_cast (tmp) : 0); + + // If the final element that we would compute for the range is equal to + // the limit of the range, or is an adjacent floating point number, + // accept it. Otherwise, try a range with one fewer element. If that + // fails, try again with one more element. + // + // I'm not sure this is very good, but it seems to work better than just + // using tfloor as above. For example, without it, the expression + // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9]. + + if (! teq (m_base + (n_elt - 1) * m_inc, m_limit)) + { + if (teq (m_base + (n_elt - 2) * m_inc, m_limit)) + n_elt--; + else if (teq (m_base + n_elt * m_inc, m_limit)) + n_elt++; + } + + retval = ((n_elt < std::numeric_limits::max ()) + ? n_elt : -1); + } + + return retval; +} + +double +Range::limit_internal (void) const +{ + double new_limit = m_inc > 0 ? max () : min (); + + // If result must be an integer then force the new_limit to be one. + if (all_elements_are_ints ()) + new_limit = std::round (new_limit); + + return new_limit; +} + +void +Range::init (void) +{ + m_numel = numel_internal (); + + if (! octave::math::isinf (m_limit)) + m_limit = limit_internal (); +} DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_legacy_range, "range", "double"); octave_legacy_range::octave_legacy_range (void) - : octave_base_value (), range () { } + : octave_base_value (), m_range (new Range ()) { } octave_legacy_range::octave_legacy_range (const Range& r) - : octave_base_value (), range (r) + : octave_base_value (), m_range (new Range (r)) { - if (range.numel () < 0 && range.numel () != -2) + if (m_range->numel () < 0 && m_range->numel () != -2) error ("invalid range"); } +octave_legacy_range::octave_legacy_range (const octave_legacy_range& r) + : octave_base_value (r), m_range () +{ + m_range.reset (new Range (*(r.m_range))); +} + static octave_base_value * default_numeric_conversion_function (const octave_base_value& a) { @@ -78,7 +382,7 @@ octave_legacy_range::numeric_conversion_function (void) const { return octave_base_value::type_conv_info (default_numeric_conversion_function, - octave_matrix::static_type_id ()); + octave_matrix::static_type_id ()); } octave_base_value * @@ -86,10 +390,10 @@ { octave_base_value *retval = nullptr; - switch (range.numel ()) + switch (m_range->numel ()) { case 1: - retval = new octave_scalar (range.base ()); + retval = new octave_scalar (m_range->base ()); break; case 0: @@ -97,17 +401,17 @@ break; case -2: - retval = new octave_matrix (range.matrix_value ()); + retval = new octave_matrix (m_range->matrix_value ()); break; default: { - if (range.increment () == 0) - retval = new octave_matrix (range.matrix_value ()); + if (m_range->increment () == 0) + retval = new octave_matrix (m_range->matrix_value ()); else retval = new octave_range - (octave::range (range.base (), range.increment (), - range.limit (), range.numel ())); + (octave::range (m_range->base (), m_range->increment (), + m_range->limit (), m_range->numel ())); } break; } @@ -145,9 +449,9 @@ error ("load: failed to load range constant"); if (inc != 0) - range = Range (base, limit, inc); + m_range.reset (new Range (base, limit, inc)); else - range = Range (base, inc, static_cast (limit)); + m_range.reset (new Range (base, inc, static_cast (limit))); return true; } @@ -173,9 +477,9 @@ if (swap) swap_bytes<8> (&inc); if (inc != 0) - range = Range (bas, lim, inc); + m_range.reset (new Range (bas, lim, inc)); else - range = Range (bas, inc, static_cast (lim)); + m_range.reset (new Range (bas, inc, static_cast (lim))); return true; } @@ -245,14 +549,14 @@ octave_idx_type nel; if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX, "OCTAVE_RANGE_NELEM", &nel)) - range = Range (rangevals[0], rangevals[2], nel); + m_range.reset (new Range (rangevals[0], rangevals[2], nel)); else { if (rangevals[2] != 0) - range = Range (rangevals[0], rangevals[1], rangevals[2]); + m_range.reset (new Range (rangevals[0], rangevals[1], rangevals[2])); else - range = Range (rangevals[0], rangevals[2], - static_cast (rangevals[1])); + m_range.reset (new Range (rangevals[0], rangevals[2], + static_cast (rangevals[1]))); } } @@ -269,7 +573,3 @@ return retval; } - -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic pop -#endif diff -r 9089bd969b37 -r bd9da634f00d libinterp/octave-value/ov-legacy-range.h --- a/libinterp/octave-value/ov-legacy-range.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/octave-value/ov-legacy-range.h Tue Dec 06 15:17:16 2022 -0500 @@ -31,10 +31,9 @@ #include #include +#include #include -#include "Range.h" - #include "lo-mappers.h" #include "lo-utils.h" #include "mx-base.h" @@ -45,6 +44,8 @@ #include "ov-re-mat.h" #include "ov-typeinfo.h" +class Range; + class octave_value_list; // Legacy Range values. @@ -65,13 +66,13 @@ octave_legacy_range (const Range& r); - octave_legacy_range (const octave_legacy_range& r) = default; + octave_legacy_range (const octave_legacy_range& r); // No assignment. octave_legacy_range& operator = (const octave_legacy_range&) = delete; - ~octave_legacy_range (void) { } + ~octave_legacy_range (void) = default; octave_base_value * clone (void) const { @@ -102,7 +103,7 @@ private: - Range range; + std::unique_ptr m_range; DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA }; diff -r 9089bd969b37 -r bd9da634f00d libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/octave-value/ov.cc Tue Dec 06 15:17:16 2022 -0500 @@ -1073,36 +1073,6 @@ maybe_mutate (); } -// Remove when public constructor that uses this function is removed. -octave_base_value * -octave_value::make_range_rep_deprecated (double base, double inc, double limit) -{ -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - - return dynamic_cast - (new octave_legacy_range (Range (base, inc, limit))); - -#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC) -# pragma GCC diagnostic pop -#endif -} - -// Remove when public constructor that uses this function is removed. -octave_base_value * -octave_value::make_range_rep_deprecated (const Range& r, bool force_range) -{ - if (! force_range && ! r.ok ()) - error ("invalid range"); - - if ((force_range || Voptimize_range)) - return dynamic_cast (new octave_legacy_range (r)); - else - return dynamic_cast (new octave_matrix (r.matrix_value ())); -} - octave_value::octave_value (const octave::range& r, bool force_range) : m_rep (force_range || Voptimize_range ? dynamic_cast (new ov_range (r)) @@ -1201,8 +1171,8 @@ : m_rep (force_range || optimize_range ? dynamic_cast (new octave_char_range (r, type)) : dynamic_cast (type == '"' - ? new octave_char_matrix_dq_str (r.array_value ()) - : new octave_char_matrix_sq_str (r.array_value ()))) + ? new octave_char_matrix_dq_str (r.array_value ()) + : new octave_char_matrix_sq_str (r.array_value ()))) #else : m_rep (type == '"' ? new octave_char_matrix_dq_str (r.array_value ()) @@ -1891,10 +1861,10 @@ ComplexColumnVector octave_value::complex_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return ComplexColumnVector (complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } RowVector @@ -1910,7 +1880,7 @@ bool frc_vec_conv) const { return ComplexRowVector (complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } Array @@ -1920,8 +1890,8 @@ Array retval = array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "real vector")); + force_vector_conversion, + type_name (), "real vector")); } template @@ -1989,8 +1959,8 @@ } return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "integer vector")); + force_vector_conversion, + type_name (), "integer vector")); } template @@ -2008,8 +1978,8 @@ Array octave_value::octave_idx_type_vector_value (bool require_int, - bool force_string_conv, - bool force_vector_conversion) const + bool force_string_conv, + bool force_vector_conversion) const { Array retval; @@ -2059,8 +2029,8 @@ } return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "integer vector")); + force_vector_conversion, + type_name (), "integer vector")); } Array @@ -2070,25 +2040,25 @@ Array retval = complex_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "complex vector")); + force_vector_conversion, + type_name (), "complex vector")); } FloatColumnVector octave_value::float_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatColumnVector (float_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatComplexColumnVector octave_value::float_complex_column_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatComplexColumnVector (float_complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatRowVector @@ -2096,15 +2066,15 @@ bool frc_vec_conv) const { return FloatRowVector (float_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } FloatComplexRowVector octave_value::float_complex_row_vector_value (bool force_string_conv, - bool frc_vec_conv) const + bool frc_vec_conv) const { return FloatComplexRowVector (float_complex_vector_value (force_string_conv, - frc_vec_conv)); + frc_vec_conv)); } Array @@ -2114,19 +2084,19 @@ Array retval = float_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "real vector")); + force_vector_conversion, + type_name (), "real vector")); } Array octave_value::float_complex_vector_value (bool force_string_conv, - bool force_vector_conversion) const + bool force_vector_conversion) const { Array retval = float_complex_array_value (force_string_conv); return retval.reshape (make_vector_dims (retval.dims (), - force_vector_conversion, - type_name (), "complex vector")); + force_vector_conversion, + type_name (), "complex vector")); } // NAME can't always be "x ## FCN" because some of the original @@ -2214,8 +2184,7 @@ XVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value) XVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value) XVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value) -XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, - float_complex_diag_matrix_value) +XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value) XVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value) @@ -2273,16 +2242,13 @@ XVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value) XVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value) -XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, - float_complex_column_vector_value) +XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value) XVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value) -XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, - float_complex_row_vector_value) +XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value) XVALUE_EXTRACTOR (Array, xint_vector_value, int_vector_value) -XVALUE_EXTRACTOR (Array, xoctave_idx_type_vector_value, - octave_idx_type_vector_value) +XVALUE_EXTRACTOR (Array, xoctave_idx_type_vector_value, octave_idx_type_vector_value) XVALUE_EXTRACTOR (Array, xvector_value, vector_value) XVALUE_EXTRACTOR (Array, xcomplex_vector_value, complex_vector_value) @@ -2520,7 +2486,7 @@ if (! tmp) err_unary_op_conversion_failed - (octave_value::unary_op_as_string (op), type_name ()); + (octave_value::unary_op_as_string (op), type_name ()); octave_base_value *old_rep = m_rep; m_rep = tmp; @@ -2692,950 +2658,950 @@ OCTAVE_BEGIN_NAMESPACE(octave) -OCTAVE_NORETURN static void -err_binary_op (const std::string& on, const std::string& tn1, - const std::string& tn2) -{ - error ("binary operator '%s' not implemented for '%s' by '%s' operations", - on.c_str (), tn1.c_str (), tn2.c_str ()); -} - -OCTAVE_NORETURN static void -err_binary_op_conv (const std::string& on) -{ - error ("type conversion failed for binary operator '%s'", on.c_str ()); -} - -octave_value -binary_op (type_info& ti, octave_value::binary_op op, - const octave_value& v1, const octave_value& v2) -{ - octave_value retval; - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id () - || t1 == octave_classdef::static_type_id () - || t2 == octave_classdef::static_type_id ()) - { - type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); - - if (! f) - err_binary_op (octave_value::binary_op_as_string (op), - v1.class_name (), v2.class_name ()); - - retval = f (v1, v2); - } - else - { - // FIXME: we need to handle overloading operators for built-in - // classes (double, char, int8, etc.) - - type_info::binary_op_fcn f - = ti.lookup_binary_op (op, t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep ()); - else - { - octave_value tv1; - octave_base_value::type_conv_info cf1 - = v1.numeric_conversion_function (); - - octave_value tv2; - octave_base_value::type_conv_info cf2 - = v2.numeric_conversion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 - && ti.lookup_binary_op (op, t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 - && ti.lookup_binary_op (op, cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (v1.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - else - tv1 = v1; - - if (cf2) - { - octave_base_value *tmp = cf2 (v2.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - else - tv2 = v2; - - if (cf1 || cf2) - { - retval = binary_op (op, tv1, tv2); - } - else - { - //demote double -> single and try again - cf1 = tv1.numeric_demotion_function (); - - cf2 = tv2.numeric_demotion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 - && ti.lookup_binary_op (op, t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 - && ti.lookup_binary_op (op, cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (tv1.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - - if (cf2) - { - octave_base_value *tmp = cf2 (tv2.get_rep ()); - - if (! tmp) - err_binary_op_conv (octave_value::binary_op_as_string (op)); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - - if (! cf1 && ! cf2) - err_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - - f = ti.lookup_binary_op (op, t1, t2); - - if (! f) - err_binary_op (octave_value::binary_op_as_string (op), - v1.type_name (), v2.type_name ()); - - retval = f (tv1.get_rep (), tv2.get_rep ()); - } - } - } - - return retval; -} - -octave_value -binary_op (octave_value::binary_op op, const octave_value& v1, - const octave_value& v2) -{ - type_info& ti = __get_type_info__ (); - - return binary_op (ti, op, v1, v2); -} - -static octave_value -decompose_binary_op (type_info& ti, octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - switch (op) - { - case octave_value::op_trans_mul: - return binary_op (octave_value::op_mul, - unary_op (octave_value::op_transpose, v1), v2); - - case octave_value::op_mul_trans: - return binary_op (ti, octave_value::op_mul, - v1, unary_op (octave_value::op_transpose, v2)); - - case octave_value::op_herm_mul: - return binary_op (ti, octave_value::op_mul, - unary_op (octave_value::op_hermitian, v1), v2); - - case octave_value::op_mul_herm: - return binary_op (ti, octave_value::op_mul, - v1, unary_op (octave_value::op_hermitian, v2)); - - case octave_value::op_trans_ldiv: - return binary_op (ti, octave_value::op_ldiv, - unary_op (octave_value::op_transpose, v1), v2); - - case octave_value::op_herm_ldiv: - return binary_op (ti, octave_value::op_ldiv, - unary_op (octave_value::op_hermitian, v1), v2); - - case octave_value::op_el_not_and: - return binary_op (ti, octave_value::op_el_and, - unary_op (octave_value::op_not, v1), v2); - - case octave_value::op_el_not_or: - return binary_op (ti, octave_value::op_el_or, - unary_op (octave_value::op_not, v1), v2); - - case octave_value::op_el_and_not: - return binary_op (ti, octave_value::op_el_and, - v1, unary_op (octave_value::op_not, v2)); - - case octave_value::op_el_or_not: - return binary_op (ti, octave_value::op_el_or, - v1, unary_op (octave_value::op_not, v2)); - - default: - error ("invalid compound operator"); - } -} - -octave_value -binary_op (type_info& ti, octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - octave_value retval; - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - if (t1 == octave_class::static_type_id () - || t2 == octave_class::static_type_id () - || t1 == octave_classdef::static_type_id () - || t2 == octave_classdef::static_type_id ()) - { - type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); - - if (f) + OCTAVE_NORETURN static void + err_binary_op (const std::string& on, const std::string& tn1, + const std::string& tn2) + { + error ("binary operator '%s' not implemented for '%s' by '%s' operations", + on.c_str (), tn1.c_str (), tn2.c_str ()); + } + + OCTAVE_NORETURN static void + err_binary_op_conv (const std::string& on) + { + error ("type conversion failed for binary operator '%s'", on.c_str ()); + } + + octave_value + binary_op (type_info& ti, octave_value::binary_op op, + const octave_value& v1, const octave_value& v2) + { + octave_value retval; + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + if (t1 == octave_class::static_type_id () + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) + { + type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); + + if (! f) + err_binary_op (octave_value::binary_op_as_string (op), + v1.class_name (), v2.class_name ()); + retval = f (v1, v2); - else - retval = decompose_binary_op (ti, op, v1, v2); - } - else - { - type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep ()); - else - retval = decompose_binary_op (ti, op, v1, v2); - } - - return retval; -} - -octave_value -binary_op (octave_value::compound_binary_op op, - const octave_value& v1, const octave_value& v2) -{ - type_info& ti = __get_type_info__ (); - - return binary_op (ti, op, v1, v2); -} - -OCTAVE_NORETURN static void -err_cat_op (const std::string& tn1, const std::string& tn2) -{ - error ("concatenation operator not implemented for '%s' by '%s' operations", - tn1.c_str (), tn2.c_str ()); -} - -OCTAVE_NORETURN static void -err_cat_op_conv (void) -{ - error ("type conversion failed for concatenation operator"); -} - -octave_value -cat_op (type_info& ti, const octave_value& v1, - const octave_value& v2, const Array& ra_idx) -{ - octave_value retval; - - // Can't rapid return for concatenation with an empty object here as - // something like cat(1,[],single([]) must return the correct type. - - int t1 = v1.type_id (); - int t2 = v2.type_id (); - - type_info::cat_op_fcn f = ti.lookup_cat_op (t1, t2); - - if (f) - retval = f (v1.get_rep (), v2.get_rep (), ra_idx); - else - { - octave_value tv1; - octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); - - octave_value tv2; - octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); - - // Try biased (one-sided) conversions first. - if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ())) - cf1 = nullptr; - else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2)) - cf2 = nullptr; - - if (cf1) - { - octave_base_value *tmp = cf1 (v1.get_rep ()); - - if (! tmp) - err_cat_op_conv (); - - tv1 = octave_value (tmp); - t1 = tv1.type_id (); - } - else - tv1 = v1; - - if (cf2) - { - octave_base_value *tmp = cf2 (v2.get_rep ()); - - if (! tmp) - err_cat_op_conv (); - - tv2 = octave_value (tmp); - t2 = tv2.type_id (); - } - else - tv2 = v2; - - if (! cf1 && ! cf2) - err_cat_op (v1.type_name (), v2.type_name ()); - - retval = cat_op (ti, tv1, tv2, ra_idx); - } - - return retval; -} - -octave_value -cat_op (const octave_value& v1, const octave_value& v2, - const Array& ra_idx) -{ - type_info& ti = __get_type_info__ (); - - return cat_op (ti, v1, v2, ra_idx); -} - -// Unless the colon operator is used with a class or classdef object, -// then all arguments must be the same type or mixed with double -// values. - -static builtin_type_t -get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type) -{ - if (op1_type == op2_type) - return op1_type; - - if (op1_type == btyp_double) - return op2_type; - - if (op2_type == btyp_double) - return op1_type; - - return btyp_unknown; -} - -static builtin_type_t -get_colon_op_type (const octave_value& base, const octave_value& increment, + } + else + { + // FIXME: we need to handle overloading operators for built-in + // classes (double, char, int8, etc.) + + type_info::binary_op_fcn f + = ti.lookup_binary_op (op, t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep ()); + else + { + octave_value tv1; + octave_base_value::type_conv_info cf1 + = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 + = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && ti.lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 + && ti.lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (v1.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + else + tv1 = v1; + + if (cf2) + { + octave_base_value *tmp = cf2 (v2.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + else + tv2 = v2; + + if (cf1 || cf2) + { + retval = binary_op (op, tv1, tv2); + } + else + { + //demote double -> single and try again + cf1 = tv1.numeric_demotion_function (); + + cf2 = tv2.numeric_demotion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 + && ti.lookup_binary_op (op, t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 + && ti.lookup_binary_op (op, cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (tv1.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + + if (cf2) + { + octave_base_value *tmp = cf2 (tv2.get_rep ()); + + if (! tmp) + err_binary_op_conv (octave_value::binary_op_as_string (op)); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + + if (! cf1 && ! cf2) + err_binary_op (octave_value::binary_op_as_string (op), + v1.type_name (), v2.type_name ()); + + f = ti.lookup_binary_op (op, t1, t2); + + if (! f) + err_binary_op (octave_value::binary_op_as_string (op), + v1.type_name (), v2.type_name ()); + + retval = f (tv1.get_rep (), tv2.get_rep ()); + } + } + } + + return retval; + } + + octave_value + binary_op (octave_value::binary_op op, const octave_value& v1, + const octave_value& v2) + { + type_info& ti = __get_type_info__ (); + + return binary_op (ti, op, v1, v2); + } + + static octave_value + decompose_binary_op (type_info& ti, octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + switch (op) + { + case octave_value::op_trans_mul: + return binary_op (octave_value::op_mul, + unary_op (octave_value::op_transpose, v1), v2); + + case octave_value::op_mul_trans: + return binary_op (ti, octave_value::op_mul, + v1, unary_op (octave_value::op_transpose, v2)); + + case octave_value::op_herm_mul: + return binary_op (ti, octave_value::op_mul, + unary_op (octave_value::op_hermitian, v1), v2); + + case octave_value::op_mul_herm: + return binary_op (ti, octave_value::op_mul, + v1, unary_op (octave_value::op_hermitian, v2)); + + case octave_value::op_trans_ldiv: + return binary_op (ti, octave_value::op_ldiv, + unary_op (octave_value::op_transpose, v1), v2); + + case octave_value::op_herm_ldiv: + return binary_op (ti, octave_value::op_ldiv, + unary_op (octave_value::op_hermitian, v1), v2); + + case octave_value::op_el_not_and: + return binary_op (ti, octave_value::op_el_and, + unary_op (octave_value::op_not, v1), v2); + + case octave_value::op_el_not_or: + return binary_op (ti, octave_value::op_el_or, + unary_op (octave_value::op_not, v1), v2); + + case octave_value::op_el_and_not: + return binary_op (ti, octave_value::op_el_and, + v1, unary_op (octave_value::op_not, v2)); + + case octave_value::op_el_or_not: + return binary_op (ti, octave_value::op_el_or, + v1, unary_op (octave_value::op_not, v2)); + + default: + error ("invalid compound operator"); + } + } + + octave_value + binary_op (type_info& ti, octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + octave_value retval; + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + if (t1 == octave_class::static_type_id () + || t2 == octave_class::static_type_id () + || t1 == octave_classdef::static_type_id () + || t2 == octave_classdef::static_type_id ()) + { + type_info::binary_class_op_fcn f = ti.lookup_binary_class_op (op); + + if (f) + retval = f (v1, v2); + else + retval = decompose_binary_op (ti, op, v1, v2); + } + else + { + type_info::binary_op_fcn f = ti.lookup_binary_op (op, t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep ()); + else + retval = decompose_binary_op (ti, op, v1, v2); + } + + return retval; + } + + octave_value + binary_op (octave_value::compound_binary_op op, + const octave_value& v1, const octave_value& v2) + { + type_info& ti = __get_type_info__ (); + + return binary_op (ti, op, v1, v2); + } + + OCTAVE_NORETURN static void + err_cat_op (const std::string& tn1, const std::string& tn2) + { + error ("concatenation operator not implemented for '%s' by '%s' operations", + tn1.c_str (), tn2.c_str ()); + } + + OCTAVE_NORETURN static void + err_cat_op_conv (void) + { + error ("type conversion failed for concatenation operator"); + } + + octave_value + cat_op (type_info& ti, const octave_value& v1, + const octave_value& v2, const Array& ra_idx) + { + octave_value retval; + + // Can't rapid return for concatenation with an empty object here as + // something like cat(1,[],single([]) must return the correct type. + + int t1 = v1.type_id (); + int t2 = v2.type_id (); + + type_info::cat_op_fcn f = ti.lookup_cat_op (t1, t2); + + if (f) + retval = f (v1.get_rep (), v2.get_rep (), ra_idx); + else + { + octave_value tv1; + octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function (); + + octave_value tv2; + octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function (); + + // Try biased (one-sided) conversions first. + if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ())) + cf1 = nullptr; + else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2)) + cf2 = nullptr; + + if (cf1) + { + octave_base_value *tmp = cf1 (v1.get_rep ()); + + if (! tmp) + err_cat_op_conv (); + + tv1 = octave_value (tmp); + t1 = tv1.type_id (); + } + else + tv1 = v1; + + if (cf2) + { + octave_base_value *tmp = cf2 (v2.get_rep ()); + + if (! tmp) + err_cat_op_conv (); + + tv2 = octave_value (tmp); + t2 = tv2.type_id (); + } + else + tv2 = v2; + + if (! cf1 && ! cf2) + err_cat_op (v1.type_name (), v2.type_name ()); + + retval = cat_op (ti, tv1, tv2, ra_idx); + } + + return retval; + } + + octave_value + cat_op (const octave_value& v1, const octave_value& v2, + const Array& ra_idx) + { + type_info& ti = __get_type_info__ (); + + return cat_op (ti, v1, v2, ra_idx); + } + + // Unless the colon operator is used with a class or classdef object, + // then all arguments must be the same type or mixed with double + // values. + + static builtin_type_t + get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type) + { + if (op1_type == op2_type) + return op1_type; + + if (op1_type == btyp_double) + return op2_type; + + if (op2_type == btyp_double) + return op1_type; + + return btyp_unknown; + } + + static builtin_type_t + get_colon_op_type (const octave_value& base, const octave_value& increment, + const octave_value& limit) + { + builtin_type_t typ + = get_colon_op_type (base.builtin_type (), increment.builtin_type ()); + + if (typ == btyp_unknown) + return typ; + + return get_colon_op_type (typ, limit.builtin_type ()); + } + + // This check depends on the type of VAL either being the expected + // integer type or a double value. + + template + static void + check_colon_operand (const octave_value& val, const char *op_str) + { + if (! val.is_double_type ()) + return; + + double dval = val.double_value (); + double intpart; + static const double out_of_range_top + = static_cast (std::numeric_limits::max ()) + + 1.; + + if (dval >= out_of_range_top + || dval < std::numeric_limits::min () + || std::modf (dval, &intpart) != 0.0) + error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); + } + + // Return the difference between two unsigned integers as an unsigned + // integer of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + UT + integer_difference (UT a, UT b) + { + return a > b ? a - b : b - a; + } + + // Return the difference between two signed integers as an unsigned + // integer corresponding to the signed type. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_signed::value), + bool>::type = true> + UT + integer_difference (ST a, ST b) + { + // Map to unsigned. + // Idea from https://stackoverflow.com/questions/10589559 + + static const UT offset + = UT (0) - static_cast (std::numeric_limits::min ()); + + UT au = static_cast (a) + offset; + UT bu = static_cast (b) + offset; + + return integer_difference (au, bu); + } + + // Number of elements in an integer range taking care to avoid + // overflow. Base and limit are of the same type. If they are + // unsigned, then increment is also of the same type. If they are + // signed, then the type of increment is the unsigned type + // corresponding to T. Assumes that the base and limit values are + // consistent with the sign of the original increment (not an empty + // range) so we can calculate numel with the absolute value of the + // increment and the absolute difference between the base and limit + // values. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel_aux (T base, UT unsigned_increment, T limit) + { + // Adding one to DIFF/INCREMENT may overflow, so check whether it is + // out of range before adding. + + UT nel_m1 = integer_difference (limit, base) / unsigned_increment; + + // FIXME: fix error message. + if (nel_m1 > std::numeric_limits::max () - 1) + error ("too many elements for range!"); + + return static_cast (nel_m1) + 1; + } + + // Convert signed range increment to unsigned. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_signed::value), + bool>::type = true> + UT + range_increment (ST increment) + { + return (increment < 0 + ? UT (0) - static_cast (increment) + : static_cast (increment)); + } + + // "Convert" unsigned range increment to unsigned. A no-op, but + // needed to provide a consistent interface for other template + // functions. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_unsigned::value), + bool>::type = true> + UT + range_increment (UT increment) + { + return increment; + } + + // Convert double range increment to unsigned. Enable by return type. + + template ::type> + typename std::enable_if<(std::is_integral::value + && std::is_unsigned::value), UT>::type + range_increment (double increment) + { + double abs_increment = std::abs (increment); + + return static_cast (abs_increment); + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are of the same signed type. + + template ::value + && std::is_signed::value), + bool>::type = true> + octave_idx_type + range_numel (ST base, ST increment, ST limit) + { + typedef typename std::make_unsigned::type UT; + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + UT unsigned_increment = range_increment (increment); + + return range_numel_aux (base, unsigned_increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are unsigned and of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + octave_idx_type + range_numel (UT base, UT increment, UT limit) + { + // Unsigned, INCREMENT is always >= 0. + if (increment == 0 || base > limit) + return 0; + + return range_numel_aux (base, increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base + // and limit are of the same type and increment is a double value. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel (T base, double increment, T limit) + { + double intpart; + if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0) + error ("colon operator increment invalid (not an integer)"); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + static const double out_of_range_top + = static_cast (std::numeric_limits::max ()) + 1.; + + double abs_increment = std::abs (increment); + + // Technically, this condition should be + // `abs_increment > std::numeric_limits::max ()`. + // But intmax('uint64') is not representable exactly as floating point + // number. Instead, it "rounds" up by 1 to 2^64. To account for + // this, use the following expression which works for all unsigned + // integer types. + if (abs_increment >= out_of_range_top) + return 1; + + UT unsigned_increment = range_increment (increment); + + return range_numel_aux (base, unsigned_increment, limit); + } + + // Make a range from integer values. Increment may be integer or double. + + template ::value + && std::is_arithmetic::value), + bool>::type = true> + octave_value + make_int_range (T base, IT increment, T limit) + { + octave_idx_type nel = range_numel (base, increment, limit); + + // For now, we create arrays instead of range for all types + // except double. + + Array> result (dim_vector (1, nel)); + + if (nel > 0) + { + typedef typename std::make_unsigned::type UT; + + UT unsigned_increment = range_increment (increment); + + T val = base; + result.xelem (0) = val; + + if (limit > base) + { + for (octave_idx_type i = 1; i < nel; i++) + { + val += unsigned_increment; + result.xelem (i) = val; + } + } + else + { + for (octave_idx_type i = 1; i < nel; i++) + { + val -= unsigned_increment; + result.xelem (i) = val; + } + } + } + + return octave_value (result); + } + + // Make a range from floating point values. + + // FIXME: Try again to define memory efficient range classes for + // integer and floating point values? Maybe with the templates + // defined in this file we could do that in a reasonable way? + // Regardless of that, it might be good to provide special treatment + // of colon expressions in FOR loops so that we can eliminate the + // "is_for_cmd_expr / force_range" flag from the parser and the + // octave_value constructors for range objects. + + // NOTE: We define this function separately for float and double so + // that we can avoid having to instantiate ov_range. We DO + // instantiate range but only so we can take advantage of the + // range class to generate the corresponding array of float values + // and not have to duplicate that code here. + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r, is_for_cmd_expr); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r.array_value ()); + } + + template ::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value), + bool>::type = true> + octave_value + make_int_range (const octave_value& base, const octave_value& increment, + const octave_value& limit) + { + if (base.isempty () || increment.isempty () || limit.isempty ()) + return octave_value (Array (dim_vector (1, 0))); + + check_colon_operand (base, "lower bound"); + check_colon_operand (limit, "upper bound"); + + typename T::val_type base_val = octave_value_extract (base).value (); + typename T::val_type limit_val = octave_value_extract (limit).value (); + + if (increment.is_double_type ()) + { + double increment_val = increment.double_value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + check_colon_operand (increment, "increment"); + + typename T::val_type increment_val + = octave_value_extract (increment).value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (const octave_value& base, const octave_value& increment, + const octave_value& limit, bool is_for_cmd_expr) + { + if (base.isempty () || increment.isempty () || limit.isempty ()) + return octave_value (Array (dim_vector (1, 0))); + + T base_val = octave_value_extract (base); + T increment_val = octave_value_extract (increment); + T limit_val = octave_value_extract (limit); + + return make_float_range (base_val, increment_val, limit_val, + is_for_cmd_expr); + } + + + octave_value + make_char_range (const octave_value& base, const octave_value& increment, const octave_value& limit) -{ - builtin_type_t typ - = get_colon_op_type (base.builtin_type (), increment.builtin_type ()); - - if (typ == btyp_unknown) - return typ; - - return get_colon_op_type (typ, limit.builtin_type ()); -} - -// This check depends on the type of VAL either being the expected -// integer type or a double value. - -template -static void -check_colon_operand (const octave_value& val, const char *op_str) -{ - if (! val.is_double_type ()) - return; - - double dval = val.double_value (); - double intpart; - static const double out_of_range_top - = static_cast (std::numeric_limits::max ()) - + 1.; - - if (dval >= out_of_range_top - || dval < std::numeric_limits::min () - || std::modf (dval, &intpart) != 0.0) - error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); -} - -// Return the difference between two unsigned integers as an unsigned -// integer of the same type. - -template ::value - && std::is_unsigned::value), - bool>::type = true> -UT -integer_difference (UT a, UT b) -{ - return a > b ? a - b : b - a; -} - -// Return the difference between two signed integers as an unsigned -// integer corresponding to the signed type. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_signed::value), - bool>::type = true> -UT -integer_difference (ST a, ST b) -{ - // Map to unsigned. - // Idea from https://stackoverflow.com/questions/10589559 - - static const UT offset - = UT (0) - static_cast (std::numeric_limits::min ()); - - UT au = static_cast (a) + offset; - UT bu = static_cast (b) + offset; - - return integer_difference (au, bu); -} - -// Number of elements in an integer range taking care to avoid -// overflow. Base and limit are of the same type. If they are -// unsigned, then increment is also of the same type. If they are -// signed, then the type of increment is the unsigned type -// corresponding to T. Assumes that the base and limit values are -// consistent with the sign of the original increment (not an empty -// range) so we can calculate numel with the absolute value of the -// increment and the absolute difference between the base and limit -// values. - -template ::type, - typename std::enable_if::value, - bool>::type = true> -octave_idx_type -range_numel_aux (T base, UT unsigned_increment, T limit) -{ - // Adding one to DIFF/INCREMENT may overflow, so check whether it is - // out of range before adding. - - UT nel_m1 = integer_difference (limit, base) / unsigned_increment; - - // FIXME: fix error message. - if (nel_m1 > std::numeric_limits::max () - 1) - error ("too many elements for range!"); - - return static_cast (nel_m1) + 1; -} - -// Convert signed range increment to unsigned. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_signed::value), - bool>::type = true> -UT -range_increment (ST increment) -{ - return (increment < 0 - ? UT (0) - static_cast (increment) - : static_cast (increment)); -} - -// "Convert" unsigned range increment to unsigned. A no-op, but -// needed to provide a consistent interface for other template -// functions. - -template ::type, - typename std::enable_if<(std::is_integral::value - && std::is_unsigned::value), - bool>::type = true> -UT -range_increment (UT increment) -{ - return increment; -} - -// Convert double range increment to unsigned. Enable by return type. - -template ::type> -typename std::enable_if<(std::is_integral::value - && std::is_unsigned::value), UT>::type -range_increment (double increment) -{ - double abs_increment = std::abs (increment); - - return static_cast (abs_increment); -} - -// Number of elements in an integer range base:increment:limit. Base, -// increment, and limit are of the same signed type. - -template ::value - && std::is_signed::value), - bool>::type = true> -octave_idx_type -range_numel (ST base, ST increment, ST limit) -{ - typedef typename std::make_unsigned::type UT; - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return 0; - - UT unsigned_increment = range_increment (increment); - - return range_numel_aux (base, unsigned_increment, limit); -} - -// Number of elements in an integer range base:increment:limit. Base, -// increment, and limit are unsigned and of the same type. - -template ::value - && std::is_unsigned::value), - bool>::type = true> -octave_idx_type -range_numel (UT base, UT increment, UT limit) -{ - // Unsigned, INCREMENT is always >= 0. - if (increment == 0 || base > limit) - return 0; - - return range_numel_aux (base, increment, limit); -} - -// Number of elements in an integer range base:increment:limit. Base -// and limit are of the same type and increment is a double value. - -template ::type, - typename std::enable_if::value, - bool>::type = true> -octave_idx_type -range_numel (T base, double increment, T limit) -{ - double intpart; - if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0) - error ("colon operator increment invalid (not an integer)"); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return 0; - - static const double out_of_range_top - = static_cast (std::numeric_limits::max ()) + 1.; - - double abs_increment = std::abs (increment); - - // Technically, this condition should be - // `abs_increment > std::numeric_limits::max ()`. - // But intmax('uint64') is not representable exactly as floating point - // number. Instead, it "rounds" up by 1 to 2^64. To account for - // this, use the following expression which works for all unsigned - // integer types. - if (abs_increment >= out_of_range_top) - return 1; - - UT unsigned_increment = range_increment (increment); - - return range_numel_aux (base, unsigned_increment, limit); -} - -// Make a range from integer values. Increment may be integer or double. - -template ::value - && std::is_arithmetic::value), - bool>::type = true> -octave_value -make_int_range (T base, IT increment, T limit) -{ - octave_idx_type nel = range_numel (base, increment, limit); - - // For now, we create arrays instead of range for all types - // except double. - - Array> result (dim_vector (1, nel)); - - if (nel > 0) - { - typedef typename std::make_unsigned::type UT; - - UT unsigned_increment = range_increment (increment); - - T val = base; - result.xelem (0) = val; - - if (limit > base) - { - for (octave_idx_type i = 1; i < nel; i++) - { - val += unsigned_increment; - result.xelem (i) = val; - } - } - else - { - for (octave_idx_type i = 1; i < nel; i++) - { - val -= unsigned_increment; - result.xelem (i) = val; - } - } - } - - return octave_value (result); -} - -// Make a range from floating point values. - -// FIXME: Try again to define memory efficient range classes for -// integer and floating point values? Maybe with the templates -// defined in this file we could do that in a reasonable way? -// Regardless of that, it might be good to provide special treatment -// of colon expressions in FOR loops so that we can eliminate the -// "is_for_cmd_expr / force_range" flag from the parser and the -// octave_value constructors for range objects. - -// NOTE: We define this function separately for float and double so -// that we can avoid having to instantiate ov_range. We DO -// instantiate range but only so we can take advantage of the -// range class to generate the corresponding array of float values -// and not have to duplicate that code here. - -template ::value, - bool>::type = true> -octave_value -make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) -{ - if (math::isnan (base) - || math::isnan (increment) - || math::isnan (limit)) - return octave_value (numeric_limits::NaN ()); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return octave_value (Array (dim_vector (1, 0))); - - // At this point, we know that the base and limit values are - // consistent with the sign of the increment (not an empty range). - - range r (base, increment, limit); - - if (! is_for_cmd_expr && ! r.is_storable ()) - error ("range with infinite number of elements cannot be stored"); - - return octave_value (r, is_for_cmd_expr); -} - -template ::value, - bool>::type = true> -octave_value -make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) -{ - if (math::isnan (base) - || math::isnan (increment) - || math::isnan (limit)) - return octave_value (numeric_limits::NaN ()); - - if (increment == 0 - || (increment > 0 && base > limit) - || (increment < 0 && base < limit)) - return octave_value (Array (dim_vector (1, 0))); - - // At this point, we know that the base and limit values are - // consistent with the sign of the increment (not an empty range). - - range r (base, increment, limit); - - if (! is_for_cmd_expr && ! r.is_storable ()) - error ("range with infinite number of elements cannot be stored"); - - return octave_value (r.array_value ()); -} - -template ::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - || std::is_same::value), - bool>::type = true> -octave_value -make_int_range (const octave_value& base, const octave_value& increment, - const octave_value& limit) -{ - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (Array (dim_vector (1, 0))); - - check_colon_operand (base, "lower bound"); - check_colon_operand (limit, "upper bound"); - - typename T::val_type base_val = octave_value_extract (base).value (); - typename T::val_type limit_val = octave_value_extract (limit).value (); - - if (increment.is_double_type ()) - { - double increment_val = increment.double_value (); - - return make_int_range (base_val, increment_val, limit_val); - } - - check_colon_operand (increment, "increment"); - - typename T::val_type increment_val - = octave_value_extract (increment).value (); - - return make_int_range (base_val, increment_val, limit_val); -} - -template ::value, - bool>::type = true> -octave_value -make_float_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool is_for_cmd_expr) -{ - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (Array (dim_vector (1, 0))); - - T base_val = octave_value_extract (base); - T increment_val = octave_value_extract (increment); - T limit_val = octave_value_extract (limit); - - return make_float_range (base_val, increment_val, limit_val, - is_for_cmd_expr); -} - - -octave_value -make_char_range (const octave_value& base, const octave_value& increment, - const octave_value& limit) -{ - octave_value retval; - - bool dq_str = (base.is_dq_string () || increment.is_dq_string () - || limit.is_dq_string ()); - - char type = dq_str ? '"' : '\''; - - if (base.isempty () || increment.isempty () || limit.isempty ()) - retval = octave_value ("", type); - else - { - Matrix mtx_base = base.matrix_value (true); - Matrix mtx_increment = increment.matrix_value (true); - Matrix mtx_limit = limit.matrix_value (true); - - range tmp (mtx_base(0), mtx_increment(0), mtx_limit(0)); - - retval = octave_value (tmp); - } - - return retval.convert_to_str (false, true, type); -} - -octave_value -colon_op (const octave_value& base, const octave_value& increment_arg, - const octave_value& limit, bool is_for_cmd_expr) -{ - if (base.isobject () || increment_arg.isobject () || limit.isobject ()) - { - octave_value_list tmp1; - - if (increment_arg.is_defined ()) - { - tmp1(2) = limit; - tmp1(1) = increment_arg; - tmp1(0) = base; - } - else - { - tmp1(1) = limit; - tmp1(0) = base; - } - - interpreter& interp = __get_interpreter__ (); - - symbol_table& symtab = interp.get_symbol_table (); - - octave_value fcn = symtab.find_function ("colon", tmp1); - - if (fcn.is_defined ()) - { - octave_value_list tmp2 = interp.feval (fcn, tmp1, 1); - - return tmp2(0); - } - } - - octave_value increment - = increment_arg.is_defined () ? increment_arg : octave_value (1.0); - - if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1) - warning_with_id ("Octave:colon-nonscalar-argument", - "colon arguments should be scalars"); - - if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ()) - warning_with_id ("Octave:colon-complex-argument", - "imaginary part of complex colon arguments is ignored"); - - // FIXME: is there a better way to do this job, maybe using type traits? - - builtin_type_t type_id = get_colon_op_type (base, increment, limit); - - // For compatibility with Matlab, don't allow the range used in - // a FOR loop expression to be converted to a Matrix. - - // For now, these functions create arrays instead of range for - // all types except double. - - switch (type_id) - { - case btyp_double: - case btyp_complex: - return make_float_range (base, increment, limit, is_for_cmd_expr); - - case btyp_float: - case btyp_float_complex: - return make_float_range (base, increment, limit, is_for_cmd_expr); - - case btyp_int8: - return make_int_range (base, increment, limit); - - case btyp_int16: - return make_int_range (base, increment, limit); - - case btyp_int32: - return make_int_range (base, increment, limit); - - case btyp_int64: - return make_int_range (base, increment, limit); - - case btyp_uint8: - return make_int_range (base, increment, limit); - - case btyp_uint16: - return make_int_range (base, increment, limit); - - case btyp_uint32: - return make_int_range (base, increment, limit); - - case btyp_uint64: - return make_int_range (base, increment, limit); - - case btyp_char: - return make_char_range (base, increment, limit); - - case btyp_unknown: - error ("incompatible types found in range expression"); - - default: - error ("invalid types found in range expression"); - } - - return octave_value (); -} - -OCTAVE_NORETURN static void -err_unary_op_conv (const std::string& on) -{ - error ("type conversion failed for unary operator '%s'", on.c_str ()); -} - -octave_value -unary_op (type_info& ti, octave_value::unary_op op, - const octave_value& v) -{ - octave_value retval; - - int t = v.type_id (); - - if (t == octave_class::static_type_id () - || t == octave_classdef::static_type_id ()) - { - type_info::unary_class_op_fcn f = ti.lookup_unary_class_op (op); - - if (! f) - err_unary_op (octave_value::unary_op_as_string (op), v.class_name ()); - - retval = f (v); - } - else - { - // FIXME: we need to handle overloading operators for built-in - // classes (double, char, int8, etc.) - - type_info::unary_op_fcn f = ti.lookup_unary_op (op, t); - - if (f) - retval = f (v.get_rep ()); - else - { - octave_value tv; - octave_base_value::type_conv_fcn cf - = v.numeric_conversion_function (); - - if (! cf) - err_unary_op (octave_value::unary_op_as_string (op), - v.type_name ()); - - octave_base_value *tmp = cf (v.get_rep ()); - - if (! tmp) - err_unary_op_conv (octave_value::unary_op_as_string (op)); - - tv = octave_value (tmp); - retval = unary_op (op, tv); - } - } - - return retval; -} - -octave_value -unary_op (octave_value::unary_op op, const octave_value& v) -{ - type_info& ti = __get_type_info__ (); - - return unary_op (ti, op, v); -} + { + octave_value retval; + + bool dq_str = (base.is_dq_string () || increment.is_dq_string () + || limit.is_dq_string ()); + + char type = dq_str ? '"' : '\''; + + if (base.isempty () || increment.isempty () || limit.isempty ()) + retval = octave_value ("", type); + else + { + Matrix mtx_base = base.matrix_value (true); + Matrix mtx_increment = increment.matrix_value (true); + Matrix mtx_limit = limit.matrix_value (true); + + range tmp (mtx_base(0), mtx_increment(0), mtx_limit(0)); + + retval = octave_value (tmp); + } + + return retval.convert_to_str (false, true, type); + } + + octave_value + colon_op (const octave_value& base, const octave_value& increment_arg, + const octave_value& limit, bool is_for_cmd_expr) + { + if (base.isobject () || increment_arg.isobject () || limit.isobject ()) + { + octave_value_list tmp1; + + if (increment_arg.is_defined ()) + { + tmp1(2) = limit; + tmp1(1) = increment_arg; + tmp1(0) = base; + } + else + { + tmp1(1) = limit; + tmp1(0) = base; + } + + interpreter& interp = __get_interpreter__ (); + + symbol_table& symtab = interp.get_symbol_table (); + + octave_value fcn = symtab.find_function ("colon", tmp1); + + if (fcn.is_defined ()) + { + octave_value_list tmp2 = interp.feval (fcn, tmp1, 1); + + return tmp2(0); + } + } + + octave_value increment + = increment_arg.is_defined () ? increment_arg : octave_value (1.0); + + if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1) + warning_with_id ("Octave:colon-nonscalar-argument", + "colon arguments should be scalars"); + + if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ()) + warning_with_id ("Octave:colon-complex-argument", + "imaginary part of complex colon arguments is ignored"); + + // FIXME: is there a better way to do this job, maybe using type traits? + + builtin_type_t type_id = get_colon_op_type (base, increment, limit); + + // For compatibility with Matlab, don't allow the range used in + // a FOR loop expression to be converted to a Matrix. + + // For now, these functions create arrays instead of range for + // all types except double. + + switch (type_id) + { + case btyp_double: + case btyp_complex: + return make_float_range (base, increment, limit, is_for_cmd_expr); + + case btyp_float: + case btyp_float_complex: + return make_float_range (base, increment, limit, is_for_cmd_expr); + + case btyp_int8: + return make_int_range (base, increment, limit); + + case btyp_int16: + return make_int_range (base, increment, limit); + + case btyp_int32: + return make_int_range (base, increment, limit); + + case btyp_int64: + return make_int_range (base, increment, limit); + + case btyp_uint8: + return make_int_range (base, increment, limit); + + case btyp_uint16: + return make_int_range (base, increment, limit); + + case btyp_uint32: + return make_int_range (base, increment, limit); + + case btyp_uint64: + return make_int_range (base, increment, limit); + + case btyp_char: + return make_char_range (base, increment, limit); + + case btyp_unknown: + error ("incompatible types found in range expression"); + + default: + error ("invalid types found in range expression"); + } + + return octave_value (); + } + + OCTAVE_NORETURN static void + err_unary_op_conv (const std::string& on) + { + error ("type conversion failed for unary operator '%s'", on.c_str ()); + } + + octave_value + unary_op (type_info& ti, octave_value::unary_op op, + const octave_value& v) + { + octave_value retval; + + int t = v.type_id (); + + if (t == octave_class::static_type_id () + || t == octave_classdef::static_type_id ()) + { + type_info::unary_class_op_fcn f = ti.lookup_unary_class_op (op); + + if (! f) + err_unary_op (octave_value::unary_op_as_string (op), v.class_name ()); + + retval = f (v); + } + else + { + // FIXME: we need to handle overloading operators for built-in + // classes (double, char, int8, etc.) + + type_info::unary_op_fcn f = ti.lookup_unary_op (op, t); + + if (f) + retval = f (v.get_rep ()); + else + { + octave_value tv; + octave_base_value::type_conv_fcn cf + = v.numeric_conversion_function (); + + if (! cf) + err_unary_op (octave_value::unary_op_as_string (op), + v.type_name ()); + + octave_base_value *tmp = cf (v.get_rep ()); + + if (! tmp) + err_unary_op_conv (octave_value::unary_op_as_string (op)); + + tv = octave_value (tmp); + retval = unary_op (op, tv); + } + } + + return retval; + } + + octave_value + unary_op (octave_value::unary_op op, const octave_value& v) + { + type_info& ti = __get_type_info__ (); + + return unary_op (ti, op, v); + } OCTAVE_END_NAMESPACE(octave) @@ -3748,8 +3714,7 @@ std::string& type_string, std::list& idx) { - const octave_map m = - arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name); + const octave_map m = arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name); if (m.nfields () != 2 || ! m.contains ("type") || ! m.contains ("subs")) error ("%s: second argument must be a structure with fields 'type' and 'subs'", diff -r 9089bd969b37 -r bd9da634f00d libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/octave-value/ov.h Tue Dec 06 15:17:16 2022 -0500 @@ -36,7 +36,6 @@ #include #include -#include "Range.h" #include "data-conv.h" #include "idx-vector.h" #include "mach-info.h" @@ -288,34 +287,6 @@ OCTINTERP_API octave_value (const Array& cellstr); OCTINTERP_API octave_value (const octave::idx_vector& idx, bool lazy = true); -private: - - // Remove when public constructors that use this function are removed. - static OCTINTERP_API octave_base_value * - make_range_rep_deprecated (double base, double inc, double limit); - - // Remove when public constructors that use this function are removed. - static OCTINTERP_API octave_base_value * - make_range_rep_deprecated (const Range& r, bool force_range); - -public: - -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value (range&)' instead") - octave_value (double base, double limit, double inc) - : m_rep (make_range_rep_deprecated (base, inc, limit)) - { - maybe_mutate (); - } - - OCTAVE_DEPRECATED (7, "use 'octave_value (range&)' instead") - octave_value (const Range& r, bool force_range = false) - : m_rep (make_range_rep_deprecated (r, force_range)) - { - maybe_mutate (); - } -#endif - OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); @@ -552,15 +523,6 @@ return m_rep->do_index_op (idx, resize_ok); } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::index_op' instead") - octave_value do_index_op (const octave_value_list& idx, - bool resize_ok = false) - { - return index_op (idx, resize_ok); - } -#endif - OCTINTERP_API octave_value subsasgn (const std::string& type, const std::list& idx, const octave_value& rhs); @@ -1459,27 +1421,10 @@ OCTINTERP_API octave_value& non_const_unary_op (unary_op op); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead") - octave_value& do_non_const_unary_op (unary_op op) - { - return non_const_unary_op (op); - } -#endif - OCTINTERP_API octave_value& non_const_unary_op (unary_op op, const std::string& type, const std::list& idx); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_value::non_const_unary_op' instead") - octave_value& do_non_const_unary_op (unary_op op, const std::string& type, - const std::list& idx) - { - return non_const_unary_op (op, type, idx); - } -#endif - const octave_base_value& get_rep (void) const { return *m_rep; } bool is_copy_of (const octave_value& val) const { return m_rep == val.m_rep; } @@ -1736,87 +1681,6 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead") -inline octave_value -do_unary_op (octave::type_info& ti, octave_value::unary_op op, - const octave_value& a) -{ - return octave::unary_op (ti, op, a); -} - -OCTAVE_DEPRECATED (7, "use 'octave::unary_op' instead") -inline octave_value -do_unary_op (octave_value::unary_op op, const octave_value& a) -{ - return octave::unary_op (op, a); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave::type_info& ti, octave_value::binary_op op, - const octave_value& a, const octave_value& b) -{ - return octave::binary_op (ti, op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave::type_info& ti, octave_value::compound_binary_op op, - const octave_value& a, const octave_value& b) -{ - return octave::binary_op (ti, op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave_value::binary_op op, const octave_value& a, - const octave_value& b) -{ - return octave::binary_op (op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::binary_op' instead") -inline octave_value -do_binary_op (octave_value::compound_binary_op op, const octave_value& a, - const octave_value& b) -{ - return octave::binary_op (op, a, b); -} - -OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead") -inline octave_value -do_cat_op (octave::type_info& ti, const octave_value& a, - const octave_value& b, const Array& ra_idx) -{ - return octave::cat_op (ti, a, b, ra_idx); -} - -OCTAVE_DEPRECATED (7, "use 'octave::cat_op' instead") -inline octave_value -do_cat_op (const octave_value& a, const octave_value& b, - const Array& ra_idx) -{ - return octave::cat_op (a, b, ra_idx); -} - -OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead") -inline octave_value -do_colon_op (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool is_for_cmd_expr = false) -{ - return octave::colon_op (base, increment, limit, is_for_cmd_expr); -} - -OCTAVE_DEPRECATED (7, "use 'octave::colon_op' instead") -inline octave_value -do_colon_op (const octave_value& base, const octave_value& limit, - bool is_for_cmd_expr = false) -{ - return octave::colon_op (base, limit, is_for_cmd_expr); -} -#endif - #define OV_UNOP_FN(name) \ inline octave_value \ name (const octave_value& a) \ diff -r 9089bd969b37 -r bd9da634f00d libinterp/parse-tree/bp-table.h --- a/libinterp/parse-tree/bp-table.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/parse-tree/bp-table.h Tue Dec 06 15:17:16 2022 -0500 @@ -39,217 +39,172 @@ OCTAVE_BEGIN_NAMESPACE(octave) -class tree_evaluator; - -struct bp_type -{ -public: - bp_type (int l, const std::string& c) : line (l), cond (c) { } - - //-------- + class tree_evaluator; - int line; - std::string cond; -}; + struct bp_type + { + public: + bp_type (int l, const std::string& c) : line (l), cond (c) { } -// Interface to breakpoints. -class OCTINTERP_API bp_table -{ -public: + //-------- - bp_table (tree_evaluator& tw) - : m_evaluator (tw), m_bp_set (), m_errors_that_stop (), - m_caught_that_stop (), m_warnings_that_stop () - { } - - ~bp_table (void) = default; - - // Set of breakpoint lines. - typedef std::set bp_lines; + int line; + std::string cond; + }; - typedef bp_lines::const_iterator const_bp_lines_iterator; - typedef bp_lines::iterator bp_lines_iterator; - - typedef std::map fname_line_map; - - typedef fname_line_map::const_iterator const_fname_line_map_iterator; - typedef fname_line_map::iterator fname_line_map_iterator; - - typedef std::map > fname_bp_map; - typedef fname_bp_map::const_iterator const_fname_bp_map_iterator; - typedef fname_bp_map::iterator fname_bp_map_iterator; + // Interface to breakpoints. + class OCTINTERP_API bp_table + { + public: -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead") - int add_breakpoint (const std::string& fname = "", - const std::string& class_name = "", - int line = 1, - const std::string& condition = "") - { - return add_breakpoint_in_function (fname, class_name, line, condition); - } + bp_table (tree_evaluator& tw) + : m_evaluator (tw), m_bp_set (), m_errors_that_stop (), + m_caught_that_stop (), m_warnings_that_stop () + { } - OCTAVE_DEPRECATED (7, "use 'bp_table::add_breakpoints_in_function' instead") - bp_lines add_breakpoint (const std::string& fname = "", - const std::string& class_name = "", - const bp_lines& lines = bp_lines (), - const std::string& condition = "") - { - return add_breakpoints_in_function (fname, class_name, lines, condition); - } -#endif + ~bp_table (void) = default; + + // Set of breakpoint lines. + typedef std::set bp_lines; + + typedef bp_lines::const_iterator const_bp_lines_iterator; + typedef bp_lines::iterator bp_lines_iterator; - // Add a breakpoint at the nearest executable line in a function. - int add_breakpoint_in_function (const std::string& fname = "", - const std::string& class_name = "", - int line = 1, - const std::string& condition = ""); + typedef std::map fname_line_map; + + typedef fname_line_map::const_iterator const_fname_line_map_iterator; + typedef fname_line_map::iterator fname_line_map_iterator; - // Add a set of breakpoints at the nearest executable lines in a - // function. - bp_lines add_breakpoints_in_function (const std::string& fname = "", - const std::string& class_name = "", - const bp_lines& lines = bp_lines (), - const std::string& condition = ""); + typedef std::map > fname_bp_map; + typedef fname_bp_map::const_iterator const_fname_bp_map_iterator; + typedef fname_bp_map::iterator fname_bp_map_iterator; - // Add a breakpoint at the nearest executable line in a file. - int add_breakpoint_in_file (const std::string& file = "", - int line = 1, - const std::string& condition = ""); - - // Add a set of breakpoints at the nearest executable lines in a - // file. - bp_lines add_breakpoints_in_file (const std::string& file = "", - const bp_lines& lines = bp_lines (), + // Add a breakpoint at the nearest executable line in a function. + int add_breakpoint_in_function (const std::string& fname = "", + const std::string& class_name = "", + int line = 1, const std::string& condition = ""); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoint_from_function' instead") - int remove_breakpoint (const std::string& fname = "", - int line = 1) - { - return remove_breakpoint_from_function (fname, line); - } + // Add a set of breakpoints at the nearest executable lines in a + // function. + bp_lines add_breakpoints_in_function (const std::string& fname = "", + const std::string& class_name = "", + const bp_lines& lines = bp_lines (), + const std::string& condition = ""); - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_breakpoints_from_function' instead") - int remove_breakpoint (const std::string& fname = "", - const bp_lines& lines = bp_lines ()) - { - return remove_breakpoints_from_function (fname, lines); - } -#endif + // Add a breakpoint at the nearest executable line in a file. + int add_breakpoint_in_file (const std::string& file = "", + int line = 1, + const std::string& condition = ""); + + // Add a set of breakpoints at the nearest executable lines in a + // file. + bp_lines add_breakpoints_in_file (const std::string& file = "", + const bp_lines& lines = bp_lines (), + const std::string& condition = ""); - // Remove a breakpoint from the given line in file. - int remove_breakpoint_from_function (const std::string& fname = "", - int line = 1); + // Remove a breakpoint from the given line in file. + int remove_breakpoint_from_function (const std::string& fname = "", + int line = 1); - // Remove a set of breakpoints from the given lines in file. - int remove_breakpoints_from_function (const std::string& fname = "", - const bp_lines& lines = bp_lines ()); + // Remove a set of breakpoints from the given lines in file. + int remove_breakpoints_from_function (const std::string& fname = "", + const bp_lines& lines = bp_lines ()); - // Remove all the breakpoints in a specified function. - bp_lines remove_all_breakpoints_from_function (const std::string& fname, - bool silent = false); + // Remove all the breakpoints in a specified function. + bp_lines remove_all_breakpoints_from_function (const std::string& fname, + bool silent = false); - // Remove a breakpoint from the given line in file. - int remove_breakpoint_from_file (const std::string& file = "", - int line = 1); + // Remove a breakpoint from the given line in file. + int remove_breakpoint_from_file (const std::string& file = "", + int line = 1); - // Remove a set of breakpoints from the given lines in file. - int remove_breakpoints_from_file (const std::string& file = "", - const bp_lines& lines = bp_lines ()); + // Remove a set of breakpoints from the given lines in file. + int remove_breakpoints_from_file (const std::string& file = "", + const bp_lines& lines = bp_lines ()); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'bp_table::remove_all_breakpoints_from_function' instead") - bp_lines remove_all_breakpoints_in_file (const std::string& fname, - bool silent = false) - { - return remove_all_breakpoints_from_function (fname, silent); - } -#endif + // Remove all the breakpoints from a file. + bp_lines remove_all_breakpoints_from_file (const std::string& file, + bool silent = false); + + // Remove all the breakpoints registered with octave. + void remove_all_breakpoints (void); - // Remove all the breakpoints from a file. - bp_lines remove_all_breakpoints_from_file (const std::string& file, - bool silent = false); + // Return all breakpoints. Each element of the map is a vector + // containing the breakpoints corresponding to a given function name. + fname_bp_map get_breakpoint_list (const octave_value_list& fname_list); + + bool have_breakpoints (void) { return (! m_bp_set.empty ()); } - // Remove all the breakpoints registered with octave. - void remove_all_breakpoints (void); - - // Return all breakpoints. Each element of the map is a vector - // containing the breakpoints corresponding to a given function name. - fname_bp_map get_breakpoint_list (const octave_value_list& fname_list); - - bool have_breakpoints (void) { return (! m_bp_set.empty ()); } + // Should we enter debugging for this particular error identifier? + bool debug_on_err (const std::string& id) + { + return (m_errors_that_stop.empty () || m_errors_that_stop.count (id)); + } - // Should we enter debugging for this particular error identifier? - bool debug_on_err (const std::string& id) - { - return (m_errors_that_stop.empty () || m_errors_that_stop.count (id)); - } + // Should we enter debugging for this particular identifier in a try/catch? + bool debug_on_caught (const std::string& id) + { + return (m_caught_that_stop.empty () || m_caught_that_stop.count (id)); + } - // Should we enter debugging for this particular identifier in a try/catch? - bool debug_on_caught (const std::string& id) - { - return (m_caught_that_stop.empty () || m_caught_that_stop.count (id)); - } + // Should we enter debugging for this particular warning identifier? + bool debug_on_warn (const std::string& id) + { + return (m_warnings_that_stop.empty () || m_warnings_that_stop.count (id)); + } - // Should we enter debugging for this particular warning identifier? - bool debug_on_warn (const std::string& id) - { - return (m_warnings_that_stop.empty () || m_warnings_that_stop.count (id)); - } + octave_map stop_on_err_warn_status (bool to_screen); + + void dbstop_process_map_args (const octave_map& mv); - octave_map stop_on_err_warn_status (bool to_screen); + void dbclear_all_signals (void); - void dbstop_process_map_args (const octave_map& mv); + bool condition_valid (const std::string& cond); - void dbclear_all_signals (void); - - bool condition_valid (const std::string& cond); + void parse_dbfunction_params (const char *who, + const octave_value_list& args, + std::string& fcn_name, + std::string& class_name, + bp_table::bp_lines& lines, + std::string& cond); - void parse_dbfunction_params (const char *who, - const octave_value_list& args, - std::string& fcn_name, - std::string& class_name, - bp_table::bp_lines& lines, - std::string& cond); + private: + + typedef std::set::const_iterator const_bp_set_iterator; + typedef std::set::iterator bp_set_iterator; -private: - - typedef std::set::const_iterator const_bp_set_iterator; - typedef std::set::iterator bp_set_iterator; + tree_evaluator& m_evaluator; - tree_evaluator& m_evaluator; - - // Set of function (.m file) names containing at least one breakpoint. - std::set m_bp_set; + // Set of function (.m file) names containing at least one breakpoint. + std::set m_bp_set; - // Set of error and warning message IDs that cause us to stop - // *if* Vdebug_on_error / Vdebug_on_caught / Vdebug_on_warning is set. - // Empty means stop on any error / caught error / warning. - std::set m_errors_that_stop; - std::set m_caught_that_stop; - std::set m_warnings_that_stop; + // Set of error and warning message IDs that cause us to stop + // *if* Vdebug_on_error / Vdebug_on_caught / Vdebug_on_warning is set. + // Empty means stop on any error / caught error / warning. + std::set m_errors_that_stop; + std::set m_caught_that_stop; + std::set m_warnings_that_stop; - void set_stop_flag (const char *who, const std::string& condition, - bool on_off); + void set_stop_flag (const char *who, const std::string& condition, + bool on_off); - void process_id_list (const char *who, const std::string& condition, - const octave_value_list& args, - int nargin, int& pos, bool on_off, - std::set& id_list); + void process_id_list (const char *who, const std::string& condition, + const octave_value_list& args, + int nargin, int& pos, bool on_off, + std::set& id_list); - bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname, - const bp_lines& line, const std::string& condition, - bp_lines& retval); + bool add_breakpoint_1 (octave_user_code *fcn, const std::string& fname, + const bp_lines& line, const std::string& condition, + bp_lines& retval); - int remove_breakpoint_1 (octave_user_code *fcn, const std::string&, - const bp_lines& lines); + int remove_breakpoint_1 (octave_user_code *fcn, const std::string&, + const bp_lines& lines); - bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn, - const std::string& fname); -}; + bp_lines remove_all_breakpoints_in_file_1 (octave_user_code *fcn, + const std::string& fname); + }; OCTAVE_END_NAMESPACE(octave) diff -r 9089bd969b37 -r bd9da634f00d libinterp/parse-tree/lex.h --- a/libinterp/parse-tree/lex.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/parse-tree/lex.h Tue Dec 06 15:17:16 2022 -0500 @@ -691,10 +691,6 @@ void warn_deprecated_syntax (const std::string& msg); - void warn_deprecated_operator (const std::string& deprecated_op, - const std::string& recommended_op, - const std::string& version); - void push_token (token *); token * current_token (void); diff -r 9089bd969b37 -r bd9da634f00d libinterp/parse-tree/lex.ll --- a/libinterp/parse-tree/lex.ll Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/parse-tree/lex.ll Tue Dec 06 15:17:16 2022 -0500 @@ -183,28 +183,6 @@ } \ while (0) -#define CMD_OR_DEPRECATED_OP(PATTERN, REPLACEMENT, VERSION, TOK) \ - do \ - { \ - curr_lexer->lexer_debug (PATTERN); \ - \ - if (curr_lexer->looks_like_command_arg ()) \ - { \ - yyless (0); \ - curr_lexer->push_start_state (COMMAND_START); \ - } \ - else \ - { \ - curr_lexer->warn_deprecated_operator (PATTERN, REPLACEMENT, \ - #VERSION); \ - /* set COMPAT to true here to avoid warning about \ - compatibility since we've already warned about the \ - operator being deprecated. */ \ - return curr_lexer->handle_op (TOK, false, true); \ - } \ - } \ - while (0) - #define CMD_OR_UNARY_OP(PATTERN, TOK, COMPAT) \ do \ { \ @@ -1088,28 +1066,6 @@ curr_lexer->m_string_text += '\v'; } -(\.\.\.){S}*{NL} { - curr_lexer->lexer_debug ("(\\.\\.\\.){S}*{NL}"); - - /* FIXME: Remove support for '...' continuation in Octave 9 */ - static const char *msg = "'...' continuations in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave; please use '\\' instead"; - - curr_lexer->warn_deprecated_syntax (msg); - - HANDLE_STRING_CONTINUATION; - } - -\\{S}+{NL} { - curr_lexer->lexer_debug ("\\\\{S}+{NL}"); - - /* FIXME: Remove support for WS after line continuation in Octave 9 */ - static const char *msg = "whitespace after continuation markers in double-quoted character strings were deprecated in version 7 and will not be allowed in a future version of Octave"; - - curr_lexer->warn_deprecated_syntax (msg); - - HANDLE_STRING_CONTINUATION; - } - \\{NL} { curr_lexer->lexer_debug ("\\\\{NL}"); @@ -1302,17 +1258,6 @@ // Deprecated C preprocessor style continuation markers. %} -\\{S}*{NL} | -\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL} { - curr_lexer->lexer_debug ("\\\\{S}*{NL}|\\\\{S}*{CCHAR}{ANY_EXCEPT_NL}*{NL}"); - - /* FIXME: Remove support for '\\' line continuation in Octave 9 */ - static const char *msg = "using continuation marker \\ outside of double quoted strings was deprecated in version 7 and will be removed from a future version of Octave, use ... instead"; - - curr_lexer->warn_deprecated_syntax (msg); - - curr_lexer->handle_continuation (); - } %{ // End of file. @@ -1644,13 +1589,10 @@ %} ":" { CMD_OR_OP (":", ':', true); } -".+" { CMD_OR_DEPRECATED_OP (".+", "+", 7, '+'); } -".-" { CMD_OR_DEPRECATED_OP (".-", "-", 7, '-'); } ".*" { CMD_OR_OP (".*", EMUL, true); } "./" { CMD_OR_OP ("./", EDIV, true); } ".\\" { CMD_OR_OP (".\\", ELEFTDIV, true); } ".^" { CMD_OR_OP (".^", EPOW, true); } -".**" { CMD_OR_DEPRECATED_OP (".**", ".^", 7, EPOW); } "<=" { CMD_OR_OP ("<=", EXPR_LE, true); } "==" { CMD_OR_OP ("==", EXPR_EQ, true); } "!=" { CMD_OR_OP ("!=", EXPR_NE, false); } @@ -1680,7 +1622,6 @@ } "^" { CMD_OR_OP ("^", POW, true); } -"**" { CMD_OR_DEPRECATED_OP ("**", "^", 7, POW); } "&&" { CMD_OR_OP ("&&", EXPR_AND_AND, true); } "||" { CMD_OR_OP ("||", EXPR_OR_OR, true); } @@ -1817,15 +1758,11 @@ "*=" { CMD_OR_OP ("*=", MUL_EQ, false); } "/=" { CMD_OR_OP ("/=", DIV_EQ, false); } "\\=" { CMD_OR_OP ("\\=", LEFTDIV_EQ, false); } -".+=" { CMD_OR_DEPRECATED_OP (".+=", "+=", 7, ADD_EQ); } -".-=" { CMD_OR_DEPRECATED_OP (".-=", "-=", 7, SUB_EQ); } ".*=" { CMD_OR_OP (".*=", EMUL_EQ, false); } "./=" { CMD_OR_OP ("./=", EDIV_EQ, false); } ".\\=" { CMD_OR_OP (".\\=", ELEFTDIV_EQ, false); } "^=" { CMD_OR_OP ("^=", POW_EQ, false); } -"**=" { CMD_OR_DEPRECATED_OP ("**=", "^=", 7, POW_EQ); } ".^=" { CMD_OR_OP (".^=", EPOW_EQ, false); } -".**=" { CMD_OR_DEPRECATED_OP (".**=", ".^=", 7, EPOW_EQ); } "&=" { CMD_OR_OP ("&=", AND_EQ, false); } "|=" { CMD_OR_OP ("|=", OR_EQ, false); } @@ -3667,16 +3604,6 @@ } void - base_lexer::warn_deprecated_operator (const std::string& deprecated_op, - const std::string& recommended_op, - const std::string& version) - { - std::string msg = "the '" + deprecated_op + "' operator was deprecated in version " + version + " and will not be allowed in a future version of Octave; please use '" + recommended_op + "' instead"; - - warn_deprecated_syntax (msg); - } - - void base_lexer::push_token (token *tok) { YYSTYPE *lval = yyget_lval (m_scanner); diff -r 9089bd969b37 -r bd9da634f00d libinterp/parse-tree/oct-lvalue.h --- a/libinterp/parse-tree/oct-lvalue.h Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/parse-tree/oct-lvalue.h Tue Dec 06 15:17:16 2022 -0500 @@ -81,14 +81,6 @@ void unary_op (octave_value::unary_op op); -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "use 'octave_lvalue::unary_op' instead") - void do_unary_op (octave_value::unary_op op) - { - return unary_op (op); - } -#endif - octave_value value (void) const; private: diff -r 9089bd969b37 -r bd9da634f00d libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/libinterp/parse-tree/pt-eval.cc Tue Dec 06 15:17:16 2022 -0500 @@ -75,616 +75,855 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Normal evaluator. - -class quit_debug_exception -{ -public: - - quit_debug_exception (bool all = false) : m_all (all) { } - - quit_debug_exception (const quit_debug_exception&) = default; - - quit_debug_exception& operator = (const quit_debug_exception&) = default; - - ~quit_debug_exception (void) = default; - - bool all (void) const { return m_all; } - -private: - - bool m_all; -}; - -class debugger -{ -public: - - enum execution_mode - { - EX_NORMAL = 0, - EX_CONTINUE = 1, - EX_QUIT = 2, - EX_QUIT_ALL = 3 + // Normal evaluator. + + class quit_debug_exception + { + public: + + quit_debug_exception (bool all = false) : m_all (all) { } + + quit_debug_exception (const quit_debug_exception&) = default; + + quit_debug_exception& operator = (const quit_debug_exception&) = default; + + ~quit_debug_exception (void) = default; + + bool all (void) const { return m_all; } + + private: + + bool m_all; }; - debugger (interpreter& interp, std::size_t level) - : m_interpreter (interp), m_level (level), - m_execution_mode (EX_NORMAL), m_in_debug_repl (false) - { } - - int server_loop (void); - - void repl (const std::string& prompt = "debug> "); - - bool in_debug_repl (void) const { return m_in_debug_repl; } - - void dbcont (void) { m_execution_mode = EX_CONTINUE; } - - void dbquit (bool all = false) - { - if (all) - m_execution_mode = EX_QUIT_ALL; - else - m_execution_mode = EX_QUIT; - } - - bool quitting_debugger (void) const; - -private: - - interpreter& m_interpreter; - - std::size_t m_level; - execution_mode m_execution_mode; - bool m_in_debug_repl; -}; - -// FIXME: Could the debugger server_loop and repl functions be merged -// with the corresponding tree_evaluator functions or do they need to -// remain separate? They perform nearly the same functions. - -int debugger::server_loop (void) -{ - // Process events from the event queue. - - tree_evaluator& tw = m_interpreter.get_evaluator (); - - void (tree_evaluator::*server_mode_fptr) (bool) - = &tree_evaluator::server_mode; - unwind_action act (server_mode_fptr, &tw, true); - - int exit_status = 0; - - do - { - if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) - break; - - if (quitting_debugger ()) - break; - - try - { - // FIXME: Should we call octave_quit in the octave::sleep - // and/or command_editor::run_event_hooks functions? - - octave_quit (); - - // FIXME: Running the event queue should be decoupled from - // the command_editor. - - // FIXME: Is it OK to use command_editor::run_event_hooks - // here? It may run more than one queued function per call, - // and it seems that the checks at the top of the loop - // probably need to be done after each individual event - // function is executed. For now, maybe the simplest thing - // would be to pass a predicate function (lambda expression) - // to the command_editor::run_event_hooks and have it check - // that and break out of the eval loop(s) if the condition - // is met? - - // FIXME: We should also use a condition variable to manage - // the execution of entries in the queue and eliminate the - // need for the busy-wait loop. - - command_editor::run_event_hooks (); - - release_unreferenced_dynamic_libraries (); - - sleep (0.1); - } - catch (const interrupt_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& e) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: unhandled index exception: " - << e.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) - { - m_interpreter.recover_from_exception (); - } - else - { - // We should exit with a nonzero status. - exit_status = 1; - break; - } - } - catch (const quit_debug_exception& qde) - { - if (qde.all ()) - throw; - - // Continue in this debug level. - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (exit_status == 0); - - if (exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - exit_status = 0; - } - - return exit_status; -} - -void debugger::repl (const std::string& prompt_arg) -{ - unwind_protect frame; - - frame.protect_var (m_in_debug_repl); - frame.protect_var (m_execution_mode); - - m_in_debug_repl = true; - - tree_evaluator& tw = m_interpreter.get_evaluator (); - - bool silent = tw.quiet_breakpoint_flag (false); - - frame.add (&tree_evaluator::restore_frame, &tw, - tw.current_call_stack_frame_number ()); - - tw.goto_frame (tw.debug_frame ()); - - octave_user_code *caller = tw.current_user_code (); - std::string fcn_file_nm, fcn_nm; - - if (caller) - { - fcn_file_nm = caller->fcn_file_name (); - fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm; - } - - int curr_debug_line = tw.current_line (); - - std::ostringstream buf; - - input_system& input_sys = m_interpreter.get_input_system (); - - event_manager& evmgr = m_interpreter.get_event_manager (); - - if (! fcn_nm.empty ()) - { - if (input_sys.gud_mode ()) - { - static char ctrl_z = 'Z' & 0x1f; - - buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line; - } - else - { - // FIXME: we should come up with a clean way to detect - // that we are stopped on the no-op command that marks the - // end of a function or script. - - if (! silent) - { - std::shared_ptr frm = tw.current_user_frame (); - - frm->display_stopped_in_message (buf); - } - - evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line); - - evmgr.set_workspace (); - - frame.add (&event_manager::execute_in_debugger_event, &evmgr, - fcn_nm, curr_debug_line); - - if (! silent) - { - std::string line_buf; - - if (caller) - line_buf = caller->get_code_line (curr_debug_line); - - if (! line_buf.empty ()) - buf << curr_debug_line << ": " << line_buf; - } - } - } - - if (silent) - command_editor::erase_empty_line (true); - - std::string stopped_in_msg = buf.str (); - - if (m_interpreter.server_mode ()) - { - if (! stopped_in_msg.empty ()) - octave_stdout << stopped_in_msg << std::endl; - - evmgr.push_event_queue (); - - frame.add (&event_manager::pop_event_queue, &evmgr); - - frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ()); - - std::shared_ptr - debug_parser (new push_parser (m_interpreter)); - - tw.set_parser (debug_parser); - - server_loop (); - } - else + class debugger + { + public: + + enum execution_mode + { + EX_NORMAL = 0, + EX_CONTINUE = 1, + EX_QUIT = 2, + EX_QUIT_ALL = 3 + }; + + debugger (interpreter& interp, std::size_t level) + : m_interpreter (interp), m_level (level), + m_execution_mode (EX_NORMAL), m_in_debug_repl (false) + { } + + int server_loop (void); + + void repl (const std::string& prompt = "debug> "); + + bool in_debug_repl (void) const { return m_in_debug_repl; } + + void dbcont (void) { m_execution_mode = EX_CONTINUE; } + + void dbquit (bool all = false) { - if (! stopped_in_msg.empty ()) - std::cerr << stopped_in_msg << std::endl; - - std::string tmp_prompt = prompt_arg; - if (m_level > 0) - tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg; - - frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ()); - input_sys.PS1 (tmp_prompt); - - if (! m_interpreter.interactive ()) - { - void (interpreter::*interactive_fptr) (bool) - = &interpreter::interactive; - frame.add (interactive_fptr, &m_interpreter, - m_interpreter.interactive ()); - - m_interpreter.interactive (true); - - // FIXME: should debugging be possible in an embedded - // interpreter? - - application *app = application::app (); - - if (app) - { - void (application::*forced_interactive_fptr) (bool) - = &application::forced_interactive; - frame.add (forced_interactive_fptr, app, - app->forced_interactive ()); - - app->forced_interactive (true); - } - } - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - - input_reader reader (m_interpreter); - - push_parser debug_parser (m_interpreter); - -#else - - parser debug_parser (m_interpreter); - -#endif - - error_system& es = m_interpreter.get_error_system (); - - while (m_in_debug_repl) - { - if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) - break; - - if (quitting_debugger ()) - break; - - try - { - debug_parser.reset (); - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - - int retval = 0; - - std::string prompt - = command_editor::decode_prompt_string (tmp_prompt); - - do - { - bool eof = false; - std::string input_line = reader.get_input (prompt, eof); - - if (eof) - { - retval = EOF; - break; - } - - retval = debug_parser.run (input_line, false); - - prompt = command_editor::decode_prompt_string (input_sys.PS2 ()); - } - while (retval < 0); - -#else - - int retval = debug_parser.run (); - -#endif - if (command_editor::interrupt (false)) - { - // Break regardless of m_execution_mode value. - - quitting_debugger (); - - break; - } - else - { - if (retval == 0) - { - std::shared_ptr stmt_list - = debug_parser.statement_list (); - - if (stmt_list) - stmt_list->accept (tw); - - if (octave_completion_matches_called) - octave_completion_matches_called = false; - - // FIXME: the following statement is here because - // the last command may have been a dbup, dbdown, or - // dbstep command that changed the current debug - // frame. If so, we need to reset the current frame - // for the call stack. But is this right way to do - // this job? What if the statement list was - // something like "dbup; dbstack"? Will the call to - // dbstack use the right frame? If not, how can we - // fix this problem? - tw.goto_frame (tw.debug_frame ()); - } - - octave_quit (); - } - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - es.display_exception (ee); - - // Ignore errors when in debugging mode; - m_interpreter.recover_from_exception (); - } - catch (const quit_debug_exception& qde) - { - if (qde.all ()) - throw; - - // Continue in this debug level. - } - } - } -} - -bool debugger::quitting_debugger (void) const -{ - if (m_execution_mode == EX_QUIT) - { - // If there is no enclosing debug level or the top-level - // repl is not active, handle dbquit the same as dbcont. - - if (m_level > 0 || m_interpreter.server_mode () - || m_interpreter.in_top_level_repl ()) - throw quit_debug_exception (); + if (all) + m_execution_mode = EX_QUIT_ALL; else - return true; + m_execution_mode = EX_QUIT; } - if (m_execution_mode == EX_QUIT_ALL) - { - // If the top-level repl is not active, handle "dbquit all" - // the same as dbcont. - - if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ()) - throw quit_debug_exception (true); - else - return true; - } - - return false; -} - -bool tree_evaluator::at_top_level (void) const -{ - return m_call_stack.at_top_level (); -} - -std::string -tree_evaluator::mfilename (const std::string& opt) const -{ - std::string fname; - - octave_user_code *fcn = m_call_stack.current_user_code (); - - if (fcn) - { - fname = fcn->fcn_file_name (); - - if (fname.empty ()) - fname = fcn->name (); - } - - if (opt == "fullpathext") - return fname; - - std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ()); - std::size_t epos = fname.rfind ('.'); - - if (epos <= dpos+1) - epos = std::string::npos; - - if (epos != std::string::npos) - fname = fname.substr (0, epos); - - if (opt == "fullpath") - return fname; - - if (dpos != std::string::npos) - fname = fname.substr (dpos+1); - - return fname; -} - -void tree_evaluator::parse_and_execute (const std::string& input, - bool& incomplete_parse) -{ - incomplete_parse = false; - - unwind_protect_var upv (m_in_top_level_repl, true); - - if (at_top_level ()) - { - dbstep_flag (0); - reset_debug_state (); - } - - // FIXME: OK to do this job here, or should it be in the functions - // that do the actual prompting? - - // Update the time stamp for the "prompt" so that automatically - // finding modified files based on file modification times will - // work. In the future, we may do something completely different to - // check for changes to files but for now, we rely on the prompt - // time stamp to limit the checks for file modification times. - - Vlast_prompt_time.stamp (); - - bool eof = false; - - event_manager& evmgr = m_interpreter.get_event_manager (); - - if (command_history::add (input)) - evmgr.append_history (input); - - m_exit_status = m_parser->run (input, eof); - - if (m_exit_status == 0) - { - std::shared_ptr - stmt_list = m_parser->statement_list (); - - if (stmt_list) - { - command_editor::increment_current_command_number (); - - eval (stmt_list, m_interpreter.interactive ()); - - evmgr.set_workspace (); - } - else if (m_parser->at_end_of_input ()) - m_exit_status = EOF; - } - else - incomplete_parse = true; - - // FIXME: Should we be checking m_exit_status or incomplete_parse or - // both here? Could EOF have a value other than -1, and is there - // possible confusion between that state and the parser returning -1? - - if (m_exit_status == -1) - m_exit_status = 0; - else - m_parser->reset (); - - evmgr.pre_input_event (); -} - -void tree_evaluator::get_line_and_eval (void) -{ - std::mutex mtx; - std::unique_lock lock (mtx); - std::condition_variable cv; - bool incomplete_parse = false; - bool evaluation_pending = false; - bool exiting = false; - - input_system& input_sys = m_interpreter.get_input_system (); - event_manager& evmgr = m_interpreter.get_event_manager (); - - while (true) - { - // FIXME: Detect EOF? Use readline? If - // so, then we need to disable idle event loop hook function - // execution. - - std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); - - std::cout << command_editor::decode_prompt_string (ps); - - std::string input; - std::getline (std::cin, input); - - if (input.empty ()) - continue; - - incomplete_parse = false; - evaluation_pending = true; - exiting = false; - - evmgr.post_event - ([&] (interpreter& interp) + bool quitting_debugger (void) const; + + private: + + interpreter& m_interpreter; + + std::size_t m_level; + execution_mode m_execution_mode; + bool m_in_debug_repl; + }; + + // FIXME: Could the debugger server_loop and repl functions be merged + // with the corresponding tree_evaluator functions or do they need to + // remain separate? They perform nearly the same functions. + + int debugger::server_loop (void) + { + // Process events from the event queue. + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + void (tree_evaluator::*server_mode_fptr) (bool) + = &tree_evaluator::server_mode; + unwind_action act (server_mode_fptr, &tw, true); + + int exit_status = 0; + + do { - // INTERPRETER THREAD - - std::lock_guard local_lock (mtx); + if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) + break; + + if (quitting_debugger ()) + break; try { - interp.parse_and_execute (input, incomplete_parse); + // FIXME: Should we call octave_quit in the octave::sleep + // and/or command_editor::run_event_hooks functions? + + octave_quit (); + + // FIXME: Running the event queue should be decoupled from + // the command_editor. + + // FIXME: Is it OK to use command_editor::run_event_hooks + // here? It may run more than one queued function per call, + // and it seems that the checks at the top of the loop + // probably need to be done after each individual event + // function is executed. For now, maybe the simplest thing + // would be to pass a predicate function (lambda expression) + // to the command_editor::run_event_hooks and have it check + // that and break out of the eval loop(s) if the condition + // is met? + + // FIXME: We should also use a condition variable to manage + // the execution of entries in the queue and eliminate the + // need for the busy-wait loop. + + command_editor::run_event_hooks (); + + release_unreferenced_dynamic_libraries (); + + sleep (0.1); + } + catch (const interrupt_exception&) + { + octave_interrupt_state = 1; + m_interpreter.recover_from_exception (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& e) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: unhandled index exception: " + << e.message () << " -- trying to return to prompt" + << std::endl; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + { + m_interpreter.recover_from_exception (); + } + else + { + // We should exit with a nonzero status. + exit_status = 1; + break; + } + } + catch (const quit_debug_exception& qde) + { + if (qde.all ()) + throw; + + // Continue in this debug level. + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; } - catch (const exit_exception&) + } + while (exit_status == 0); + + if (exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + exit_status = 0; + } + + return exit_status; + } + + void debugger::repl (const std::string& prompt_arg) + { + unwind_protect frame; + + frame.protect_var (m_in_debug_repl); + frame.protect_var (m_execution_mode); + + m_in_debug_repl = true; + + tree_evaluator& tw = m_interpreter.get_evaluator (); + + bool silent = tw.quiet_breakpoint_flag (false); + + frame.add (&tree_evaluator::restore_frame, &tw, + tw.current_call_stack_frame_number ()); + + tw.goto_frame (tw.debug_frame ()); + + octave_user_code *caller = tw.current_user_code (); + std::string fcn_file_nm, fcn_nm; + + if (caller) + { + fcn_file_nm = caller->fcn_file_name (); + fcn_nm = fcn_file_nm.empty () ? caller->name () : fcn_file_nm; + } + + int curr_debug_line = tw.current_line (); + + std::ostringstream buf; + + input_system& input_sys = m_interpreter.get_input_system (); + + event_manager& evmgr = m_interpreter.get_event_manager (); + + if (! fcn_nm.empty ()) + { + if (input_sys.gud_mode ()) + { + static char ctrl_z = 'Z' & 0x1f; + + buf << ctrl_z << ctrl_z << fcn_nm << ':' << curr_debug_line; + } + else + { + // FIXME: we should come up with a clean way to detect + // that we are stopped on the no-op command that marks the + // end of a function or script. + + if (! silent) + { + std::shared_ptr frm = tw.current_user_frame (); + + frm->display_stopped_in_message (buf); + } + + evmgr.enter_debugger_event (fcn_nm, fcn_file_nm, curr_debug_line); + + evmgr.set_workspace (); + + frame.add (&event_manager::execute_in_debugger_event, &evmgr, + fcn_nm, curr_debug_line); + + if (! silent) + { + std::string line_buf; + + if (caller) + line_buf = caller->get_code_line (curr_debug_line); + + if (! line_buf.empty ()) + buf << curr_debug_line << ": " << line_buf; + } + } + } + + if (silent) + command_editor::erase_empty_line (true); + + std::string stopped_in_msg = buf.str (); + + if (m_interpreter.server_mode ()) + { + if (! stopped_in_msg.empty ()) + octave_stdout << stopped_in_msg << std::endl; + + evmgr.push_event_queue (); + + frame.add (&event_manager::pop_event_queue, &evmgr); + + frame.add (&tree_evaluator::set_parser, &tw, tw.get_parser ()); + + std::shared_ptr + debug_parser (new push_parser (m_interpreter)); + + tw.set_parser (debug_parser); + + server_loop (); + } + else + { + if (! stopped_in_msg.empty ()) + std::cerr << stopped_in_msg << std::endl; + + std::string tmp_prompt = prompt_arg; + if (m_level > 0) + tmp_prompt = "[" + std::to_string (m_level) + "]" + prompt_arg; + + frame.add (&input_system::set_PS1, &input_sys, input_sys.PS1 ()); + input_sys.PS1 (tmp_prompt); + + if (! m_interpreter.interactive ()) + { + void (interpreter::*interactive_fptr) (bool) + = &interpreter::interactive; + frame.add (interactive_fptr, &m_interpreter, + m_interpreter.interactive ()); + + m_interpreter.interactive (true); + + // FIXME: should debugging be possible in an embedded + // interpreter? + + application *app = application::app (); + + if (app) + { + void (application::*forced_interactive_fptr) (bool) + = &application::forced_interactive; + frame.add (forced_interactive_fptr, app, + app->forced_interactive ()); + + app->forced_interactive (true); + } + } + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + + input_reader reader (m_interpreter); + + push_parser debug_parser (m_interpreter); + +#else + + parser debug_parser (m_interpreter); + +#endif + + error_system& es = m_interpreter.get_error_system (); + + while (m_in_debug_repl) { - evaluation_pending = false; - exiting = true; - cv.notify_all (); - throw; + if (m_execution_mode == EX_CONTINUE || tw.dbstep_flag ()) + break; + + if (quitting_debugger ()) + break; + + try + { + debug_parser.reset (); + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + + int retval = 0; + + std::string prompt + = command_editor::decode_prompt_string (tmp_prompt); + + do + { + bool eof = false; + std::string input_line = reader.get_input (prompt, eof); + + if (eof) + { + retval = EOF; + break; + } + + retval = debug_parser.run (input_line, false); + + prompt = command_editor::decode_prompt_string (input_sys.PS2 ()); + } + while (retval < 0); + +#else + + int retval = debug_parser.run (); + +#endif + if (command_editor::interrupt (false)) + { + // Break regardless of m_execution_mode value. + + quitting_debugger (); + + break; + } + else + { + if (retval == 0) + { + std::shared_ptr stmt_list + = debug_parser.statement_list (); + + if (stmt_list) + stmt_list->accept (tw); + + if (octave_completion_matches_called) + octave_completion_matches_called = false; + + // FIXME: the following statement is here because + // the last command may have been a dbup, dbdown, or + // dbstep command that changed the current debug + // frame. If so, we need to reset the current frame + // for the call stack. But is this right way to do + // this job? What if the statement list was + // something like "dbup; dbstack"? Will the call to + // dbstack use the right frame? If not, how can we + // fix this problem? + tw.goto_frame (tw.debug_frame ()); + } + + octave_quit (); + } + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + es.display_exception (ee); + + // Ignore errors when in debugging mode; + m_interpreter.recover_from_exception (); + } + catch (const quit_debug_exception& qde) + { + if (qde.all ()) + throw; + + // Continue in this debug level. + } + } + } + } + + bool debugger::quitting_debugger (void) const + { + if (m_execution_mode == EX_QUIT) + { + // If there is no enclosing debug level or the top-level + // repl is not active, handle dbquit the same as dbcont. + + if (m_level > 0 || m_interpreter.server_mode () + || m_interpreter.in_top_level_repl ()) + throw quit_debug_exception (); + else + return true; + } + + if (m_execution_mode == EX_QUIT_ALL) + { + // If the top-level repl is not active, handle "dbquit all" + // the same as dbcont. + + if (m_interpreter.server_mode () || m_interpreter.in_top_level_repl ()) + throw quit_debug_exception (true); + else + return true; + } + + return false; + } + + bool tree_evaluator::at_top_level (void) const + { + return m_call_stack.at_top_level (); + } + + std::string + tree_evaluator::mfilename (const std::string& opt) const + { + std::string fname; + + octave_user_code *fcn = m_call_stack.current_user_code (); + + if (fcn) + { + fname = fcn->fcn_file_name (); + + if (fname.empty ()) + fname = fcn->name (); + } + + if (opt == "fullpathext") + return fname; + + std::size_t dpos = fname.rfind (sys::file_ops::dir_sep_char ()); + std::size_t epos = fname.rfind ('.'); + + if (epos <= dpos+1) + epos = std::string::npos; + + if (epos != std::string::npos) + fname = fname.substr (0, epos); + + if (opt == "fullpath") + return fname; + + if (dpos != std::string::npos) + fname = fname.substr (dpos+1); + + return fname; + } + + void tree_evaluator::parse_and_execute (const std::string& input, + bool& incomplete_parse) + { + incomplete_parse = false; + + unwind_protect_var upv (m_in_top_level_repl, true); + + if (at_top_level ()) + { + dbstep_flag (0); + reset_debug_state (); + } + + // FIXME: OK to do this job here, or should it be in the functions + // that do the actual prompting? + + // Update the time stamp for the "prompt" so that automatically + // finding modified files based on file modification times will + // work. In the future, we may do something completely different to + // check for changes to files but for now, we rely on the prompt + // time stamp to limit the checks for file modification times. + + Vlast_prompt_time.stamp (); + + bool eof = false; + + event_manager& evmgr = m_interpreter.get_event_manager (); + + if (command_history::add (input)) + evmgr.append_history (input); + + m_exit_status = m_parser->run (input, eof); + + if (m_exit_status == 0) + { + std::shared_ptr + stmt_list = m_parser->statement_list (); + + if (stmt_list) + { + command_editor::increment_current_command_number (); + + eval (stmt_list, m_interpreter.interactive ()); + + evmgr.set_workspace (); + } + else if (m_parser->at_end_of_input ()) + m_exit_status = EOF; + } + else + incomplete_parse = true; + + // FIXME: Should we be checking m_exit_status or incomplete_parse or + // both here? Could EOF have a value other than -1, and is there + // possible confusion between that state and the parser returning -1? + + if (m_exit_status == -1) + m_exit_status = 0; + else + m_parser->reset (); + + evmgr.pre_input_event (); + } + + void tree_evaluator::get_line_and_eval (void) + { + std::mutex mtx; + std::unique_lock lock (mtx); + std::condition_variable cv; + bool incomplete_parse = false; + bool evaluation_pending = false; + bool exiting = false; + + input_system& input_sys = m_interpreter.get_input_system (); + event_manager& evmgr = m_interpreter.get_event_manager (); + + while (true) + { + // FIXME: Detect EOF? Use readline? If + // so, then we need to disable idle event loop hook function + // execution. + + std::string ps = incomplete_parse ? input_sys.PS2 () : input_sys.PS1 (); + + std::cout << command_editor::decode_prompt_string (ps); + + std::string input; + std::getline (std::cin, input); + + if (input.empty ()) + continue; + + incomplete_parse = false; + evaluation_pending = true; + exiting = false; + + evmgr.post_event + ([&] (interpreter& interp) + { + // INTERPRETER THREAD + + std::lock_guard local_lock (mtx); + + try + { + interp.parse_and_execute (input, incomplete_parse); + } + catch (const exit_exception&) + { + evaluation_pending = false; + exiting = true; + cv.notify_all (); + throw; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + evaluation_pending = false; + cv.notify_all (); + } + else + { + evaluation_pending = false; + cv.notify_all (); + throw exit_exception (1); + } + } + catch (...) + { + evaluation_pending = false; + cv.notify_all (); + throw; + } + + evaluation_pending = false; + cv.notify_all (); + }); + + // Wait until evaluation is finished before prompting for input + // again. + + cv.wait (lock, [&] { return ! evaluation_pending; }); + + if (exiting) + break; + } + } + + int tree_evaluator::repl (void) + { + // The big loop. Read, Eval, Print, Loop. Normally user + // interaction at the command line in a terminal session, but we may + // also end up here when reading from a pipe or when stdin is + // connected to a file by the magic of input redirection. + + int exit_status = 0; + + // FIXME: should this choice be a command-line option? Note that we + // intend that the push parser interface only be used for + // interactive sessions. + +#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) + static bool use_command_line_push_parser = true; +#else + static bool use_command_line_push_parser = false; +#endif + + // The following logic is written as it is to allow easy transition + // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to + // simplify the logic of the main loop below by using the same + // base_parser::run interface for both push and pull parsers. + + std::shared_ptr repl_parser; + + if (m_interpreter.interactive ()) + { + if (use_command_line_push_parser) + { + push_parser *pp + = new push_parser (m_interpreter, + new input_reader (m_interpreter)); + + repl_parser = std::shared_ptr (pp); + } + else + { + parser *pp = new parser (new lexer (m_interpreter)); + repl_parser = std::shared_ptr (pp); + } + } + else + { + parser *pp = new parser (new lexer (stdin, m_interpreter)); + repl_parser = std::shared_ptr (pp); + } + + do + { + try + { + unwind_protect_var upv (m_in_top_level_repl, true); + + repl_parser->reset (); + + if (at_top_level ()) + { + dbstep_flag (0); + reset_debug_state (); + } + + exit_status = repl_parser->run (); + + if (exit_status == 0) + { + std::shared_ptr + stmt_list = repl_parser->statement_list (); + + if (stmt_list) + { + command_editor::increment_current_command_number (); + + eval (stmt_list, m_interpreter.interactive ()); + } + else if (repl_parser->at_end_of_input ()) + { + exit_status = EOF; + break; + } + } + } + catch (const interrupt_exception&) + { + m_interpreter.recover_from_exception (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& ie) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: unhandled index exception: " + << ie.message () << " -- trying to return to prompt" + << std::endl; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + es.display_exception (ee); + + if (m_interpreter.interactive ()) + m_interpreter.recover_from_exception (); + else + { + // We should exit with a nonzero status. + exit_status = 1; + break; + } + } + catch (const quit_debug_exception&) + { + m_interpreter.recover_from_exception (); + + // FIXME: Does anything else need to happen here? + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; + } + } + while (exit_status == 0); + + if (exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + exit_status = 0; + } + + return exit_status; + } + + int tree_evaluator::server_loop (void) + { + // Process events from the event queue. + + unwind_protect_var upv1 (m_server_mode, true); + + m_exit_status = 0; + + std::shared_ptr parser (new push_parser (m_interpreter)); + unwind_protect_var> upv2 (m_parser, parser); + + // FIXME: We are currently resetting the parser after every call to + // recover_from_exception. This action should probably be handled + // in a more consistent way, but resetting the parser in every call + // to interpreter::recover_from_exception appears to cause + // segfaults in the test suite. + + do + { + try + { + // FIXME: Should we call octave_quit in the octave::sleep + // and/or command_editor::run_event_hooks functions? + + octave_quit (); + + // FIXME: Running the event queue should be decoupled from + // the command_editor. We should also use a condition + // variable to manage the execution of entries in the queue + // and eliminate the need for the busy-wait loop. + + command_editor::run_event_hooks (); + + release_unreferenced_dynamic_libraries (); + + sleep (0.1); + } + catch (const interrupt_exception&) + { + octave_interrupt_state = 1; + m_interpreter.recover_from_exception (); + m_parser->reset (); + + // Required newline when the user does Ctrl+C at the prompt. + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + } + catch (const index_exception& e) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + + std::cerr << "error: unhandled index exception: " + << e.message () << " -- trying to return to prompt" + << std::endl; } catch (const execution_exception& ee) { @@ -697,1133 +936,874 @@ { m_interpreter.recover_from_exception (); m_parser->reset (); - evaluation_pending = false; - cv.notify_all (); } else { - evaluation_pending = false; - cv.notify_all (); - throw exit_exception (1); + // We should exit with a nonzero status. + m_exit_status = 1; + break; } } - catch (...) + catch (const quit_debug_exception&) { - evaluation_pending = false; - cv.notify_all (); - throw; - } - - evaluation_pending = false; - cv.notify_all (); - }); - - // Wait until evaluation is finished before prompting for input - // again. - - cv.wait (lock, [&] { return ! evaluation_pending; }); - - if (exiting) - break; - } -} - -int tree_evaluator::repl (void) -{ - // The big loop. Read, Eval, Print, Loop. Normally user - // interaction at the command line in a terminal session, but we may - // also end up here when reading from a pipe or when stdin is - // connected to a file by the magic of input redirection. - - int exit_status = 0; - - // FIXME: should this choice be a command-line option? Note that we - // intend that the push parser interface only be used for - // interactive sessions. - -#if defined (OCTAVE_ENABLE_COMMAND_LINE_PUSH_PARSER) - static bool use_command_line_push_parser = true; -#else - static bool use_command_line_push_parser = false; -#endif - - // The following logic is written as it is to allow easy transition - // to setting USE_COMMAND_LINE_PUSH_PARSER at run time and to - // simplify the logic of the main loop below by using the same - // base_parser::run interface for both push and pull parsers. - - std::shared_ptr repl_parser; - - if (m_interpreter.interactive ()) - { - if (use_command_line_push_parser) - { - push_parser *pp - = new push_parser (m_interpreter, - new input_reader (m_interpreter)); - - repl_parser = std::shared_ptr (pp); - } - else - { - parser *pp = new parser (new lexer (m_interpreter)); - repl_parser = std::shared_ptr (pp); - } - } - else - { - parser *pp = new parser (new lexer (stdin, m_interpreter)); - repl_parser = std::shared_ptr (pp); - } - - do - { - try - { - unwind_protect_var upv (m_in_top_level_repl, true); - - repl_parser->reset (); - - if (at_top_level ()) - { - dbstep_flag (0); - reset_debug_state (); - } - - exit_status = repl_parser->run (); - - if (exit_status == 0) - { - std::shared_ptr - stmt_list = repl_parser->statement_list (); - - if (stmt_list) - { - command_editor::increment_current_command_number (); - - eval (stmt_list, m_interpreter.interactive ()); - } - else if (repl_parser->at_end_of_input ()) - { - exit_status = EOF; - break; - } - } - } - catch (const interrupt_exception&) - { - m_interpreter.recover_from_exception (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& ie) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: unhandled index exception: " - << ie.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) + octave_interrupt_state = 1; m_interpreter.recover_from_exception (); - else - { - // We should exit with a nonzero status. - exit_status = 1; - break; - } - } - catch (const quit_debug_exception&) - { - m_interpreter.recover_from_exception (); - - // FIXME: Does anything else need to happen here? - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (exit_status == 0); - - if (exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - exit_status = 0; - } - - return exit_status; -} - -int tree_evaluator::server_loop (void) -{ - // Process events from the event queue. - - unwind_protect_var upv1 (m_server_mode, true); - - m_exit_status = 0; - - std::shared_ptr parser (new push_parser (m_interpreter)); - unwind_protect_var> upv2 (m_parser, parser); - - // FIXME: We are currently resetting the parser after every call to - // recover_from_exception. This action should probably be handled - // in a more consistent way, but resetting the parser in every call - // to interpreter::recover_from_exception appears to cause - // segfaults in the test suite. - - do - { - try - { - // FIXME: Should we call octave_quit in the octave::sleep - // and/or command_editor::run_event_hooks functions? - - octave_quit (); - - // FIXME: Running the event queue should be decoupled from - // the command_editor. We should also use a condition - // variable to manage the execution of entries in the queue - // and eliminate the need for the busy-wait loop. - - command_editor::run_event_hooks (); - - release_unreferenced_dynamic_libraries (); - - sleep (0.1); - } - catch (const interrupt_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - m_parser->reset (); - - // Required newline when the user does Ctrl+C at the prompt. - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - } - catch (const index_exception& e) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - - std::cerr << "error: unhandled index exception: " - << e.message () << " -- trying to return to prompt" - << std::endl; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - es.display_exception (ee); - - if (m_interpreter.interactive ()) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - } - else - { - // We should exit with a nonzero status. - m_exit_status = 1; - break; - } - } - catch (const quit_debug_exception&) - { - octave_interrupt_state = 1; - m_interpreter.recover_from_exception (); - m_parser->reset (); - } - catch (const exit_exception& xe) - { - m_exit_status = xe.exit_status (); - break; - } - catch (const std::bad_alloc&) - { - m_interpreter.recover_from_exception (); - m_parser->reset (); - - std::cerr << "error: out of memory -- trying to return to prompt" - << std::endl; - } - } - while (m_exit_status == 0); - - if (m_exit_status == EOF) - { - if (m_interpreter.interactive ()) - octave_stdout << "\n"; - - m_exit_status = 0; - } - - return m_exit_status; -} - -void tree_evaluator::eval (std::shared_ptr& stmt_list, - bool interactive) -{ - try - { - stmt_list->accept (*this); - - octave_quit (); - - if (! interactive) - { - bool quit = (m_returning || m_breaking); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - - if (quit) - return; - } - - if (octave_completion_matches_called) - octave_completion_matches_called = false; - } - catch (const quit_debug_exception&) - { - m_interpreter.recover_from_exception (); - } -} - -octave_value_list -tree_evaluator::eval_string (const std::string& eval_str, bool silent, - int& parse_status, int nargout) -{ - octave_value_list retval; - - parser eval_parser (eval_str, m_interpreter); - - do - { - eval_parser.reset (); - - // If we are looking at - // - // val = eval ("code"); - // - // then don't allow code to be parsed as a command. - - if (nargout > 0) - eval_parser.disallow_command_syntax (); - - parse_status = eval_parser.run (); - - if (parse_status == 0) - { - std::shared_ptr stmt_list - = eval_parser.statement_list (); - - if (stmt_list) - { - tree_statement *stmt = nullptr; - - if (stmt_list->length () == 1 - && (stmt = stmt_list->front ()) - && stmt->is_expression ()) - { - tree_expression *expr = stmt->expression (); - - if (silent) - expr->set_print_flag (false); - - retval = expr->evaluate_n (*this, nargout); - - bool do_bind_ans = false; - - if (expr->is_identifier ()) - do_bind_ans = ! is_variable (expr); - else - do_bind_ans = ! expr->is_assignment_expression (); - - if (do_bind_ans && ! retval.empty ()) - bind_ans (retval(0), expr->print_result ()); - - if (nargout == 0) - retval = octave_value_list (); - } - else if (nargout == 0) - stmt_list->accept (*this); - else - error ("eval: invalid use of statement list"); - - if (returning () || breaking () || continuing ()) - break; - } - else if (eval_parser.at_end_of_input ()) + m_parser->reset (); + } + catch (const exit_exception& xe) + { + m_exit_status = xe.exit_status (); break; - } - } - while (parse_status == 0); - - return retval; -} - -octave_value tree_evaluator::eval_string (const std::string& eval_str, - bool silent, int& parse_status) -{ - octave_value retval; - - octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1); - - if (! tmp.empty ()) - retval = tmp(0); - - return retval; -} - -octave_value_list tree_evaluator::eval_string (const octave_value& arg, - bool silent, int& parse_status, - int nargout) -{ - std::string s = arg.xstring_value ("eval: expecting string argument"); - - return eval_string (s, silent, parse_status, nargout); -} - -octave_value_list tree_evaluator::eval (const std::string& try_code, - int nargout) -{ - int parse_status = 0; - - return eval_string (try_code, nargout > 0, parse_status, nargout); -} - -octave_value_list tree_evaluator::eval (const std::string& try_code, - const std::string& catch_code, - int nargout) -{ - octave_value_list retval; - - error_system& es = m_interpreter.get_error_system (); - - int parse_status = 0; - - bool execution_error = false; - - octave_value_list tmp; - - try - { - tmp = eval_string (try_code, nargout > 0, parse_status, nargout); - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - execution_error = true; - } - - if (parse_status != 0 || execution_error) - { - tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); - - retval = (nargout > 0) ? tmp : octave_value_list (); - } - else - { - if (nargout > 0) - retval = tmp; - - // FIXME: we should really be rethrowing whatever - // exception occurred, not just throwing an - // execution exception. - if (execution_error) - throw execution_exception (); - } - - return retval; -} - -octave_value_list tree_evaluator::evalin (const std::string& context, - const std::string& try_code, - int nargout) -{ - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(evalin: CONTEXT must be "caller" or "base")"); - - int parse_status = 0; - - return eval_string (try_code, nargout > 0, parse_status, nargout); -} - -octave_value_list tree_evaluator::evalin (const std::string& context, - const std::string& try_code, - const std::string& catch_code, - int nargout) -{ - octave_value_list retval; - - unwind_action act1 ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(evalin: CONTEXT must be "caller" or "base")"); - - error_system& es = m_interpreter.get_error_system (); - - int parse_status = 0; - - bool execution_error = false; - - octave_value_list tmp; - - try - { - tmp = eval_string (try_code, nargout > 0, parse_status, nargout); - } - catch (const execution_exception& ee) - { - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - execution_error = true; - } - - if (parse_status != 0 || execution_error) - { - tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); - - retval = (nargout > 0) ? tmp : octave_value_list (); - } - else - { - if (nargout > 0) - retval = tmp; - - // FIXME: we should really be rethrowing whatever - // exception occurred, not just throwing an - // execution exception. - if (execution_error) - throw execution_exception (); - } - - return retval; -} - -void -tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_argument_list (tree_argument_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arguments_block (tree_arguments_block&) -{ - warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE"); -} - -void -tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_validation (tree_arg_validation&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_binary_expression (tree_binary_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_boolean_expression (tree_boolean_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_break_command (tree_break_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (m_in_loop_command) - m_breaking = 1; - else - error ("break must appear in a loop in the same file as loop command"); -} - -void -tree_evaluator::visit_colon_expression (tree_colon_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_continue_command (tree_continue_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (m_in_loop_command) - m_continuing = 1; -} - -bool -tree_evaluator::statement_printing_enabled (void) -{ - return ! (m_silent_functions && (m_statement_context == SC_FUNCTION - || m_statement_context == SC_SCRIPT)); -} - -void -tree_evaluator::reset_debug_state (void) -{ - m_debug_mode = (m_bp_table.have_breakpoints () - || m_dbstep_flag != 0 - || m_break_on_next_stmt - || in_debug_repl ()); -} - -void -tree_evaluator::reset_debug_state (bool mode) -{ - m_debug_mode = mode; -} - -void -tree_evaluator::enter_debugger (const std::string& prompt) -{ - unwind_protect frame; - - frame.add (command_history::ignore_entries, - command_history::ignoring_entries ()); - - command_history::ignore_entries (false); - - frame.add (&call_stack::restore_frame, &m_call_stack, - m_call_stack.current_frame ()); - - // Don't allow errors or warnings at the debug prompt to push us - // into deeper levels of debugging. - - error_system& es = m_interpreter.get_error_system (); - - frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ()); - - frame.add (&error_system::set_debug_on_warning, &es, - es.debug_on_warning ()); - - es.debug_on_error (false); - es.debug_on_warning (false); - - // Go up to the nearest user code frame. - - m_debug_frame = m_call_stack.dbupdown (0); - - // FIXME: probably we just want to print one line, not the - // entire statement, which might span many lines... - // - // tree_print_code tpc (octave_stdout); - // stmt.accept (tpc); - - debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ()); - - m_debugger_stack.push (dbgr); - - frame.add ([=] (void) - { - delete m_debugger_stack.top (); - m_debugger_stack.pop (); - reset_debug_state (); - }); - - dbgr->repl (prompt); -} - -void -tree_evaluator::keyboard (const std::string& prompt) -{ - enter_debugger (prompt); -} - -void -tree_evaluator::dbupdown (int n, bool verbose) -{ - m_debug_frame = m_call_stack.dbupdown (n, verbose); -} - -Matrix -tree_evaluator::ignored_fcn_outputs (void) const -{ - Matrix retval; - - const std::list *lvalues = m_lvalue_list; - - if (! lvalues) + } + catch (const std::bad_alloc&) + { + m_interpreter.recover_from_exception (); + m_parser->reset (); + + std::cerr << "error: out of memory -- trying to return to prompt" + << std::endl; + } + } + while (m_exit_status == 0); + + if (m_exit_status == EOF) + { + if (m_interpreter.interactive ()) + octave_stdout << "\n"; + + m_exit_status = 0; + } + + return m_exit_status; + } + + void tree_evaluator::eval (std::shared_ptr& stmt_list, + bool interactive) + { + try + { + stmt_list->accept (*this); + + octave_quit (); + + if (! interactive) + { + bool quit = (m_returning || m_breaking); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + + if (quit) + return; + } + + if (octave_completion_matches_called) + octave_completion_matches_called = false; + } + catch (const quit_debug_exception&) + { + m_interpreter.recover_from_exception (); + } + } + + octave_value_list + tree_evaluator::eval_string (const std::string& eval_str, bool silent, + int& parse_status, int nargout) + { + octave_value_list retval; + + parser eval_parser (eval_str, m_interpreter); + + do + { + eval_parser.reset (); + + // If we are looking at + // + // val = eval ("code"); + // + // then don't allow code to be parsed as a command. + + if (nargout > 0) + eval_parser.disallow_command_syntax (); + + parse_status = eval_parser.run (); + + if (parse_status == 0) + { + std::shared_ptr stmt_list + = eval_parser.statement_list (); + + if (stmt_list) + { + tree_statement *stmt = nullptr; + + if (stmt_list->length () == 1 + && (stmt = stmt_list->front ()) + && stmt->is_expression ()) + { + tree_expression *expr = stmt->expression (); + + if (silent) + expr->set_print_flag (false); + + retval = expr->evaluate_n (*this, nargout); + + bool do_bind_ans = false; + + if (expr->is_identifier ()) + do_bind_ans = ! is_variable (expr); + else + do_bind_ans = ! expr->is_assignment_expression (); + + if (do_bind_ans && ! retval.empty ()) + bind_ans (retval(0), expr->print_result ()); + + if (nargout == 0) + retval = octave_value_list (); + } + else if (nargout == 0) + stmt_list->accept (*this); + else + error ("eval: invalid use of statement list"); + + if (returning () || breaking () || continuing ()) + break; + } + else if (eval_parser.at_end_of_input ()) + break; + } + } + while (parse_status == 0); + + return retval; + } + + octave_value tree_evaluator::eval_string (const std::string& eval_str, + bool silent, int& parse_status) + { + octave_value retval; + + octave_value_list tmp = eval_string (eval_str, silent, parse_status, 1); + + if (! tmp.empty ()) + retval = tmp(0); + + return retval; + } + + octave_value_list tree_evaluator::eval_string (const octave_value& arg, + bool silent, int& parse_status, + int nargout) + { + std::string s = arg.xstring_value ("eval: expecting string argument"); + + return eval_string (s, silent, parse_status, nargout); + } + + octave_value_list tree_evaluator::eval (const std::string& try_code, + int nargout) + { + int parse_status = 0; + + return eval_string (try_code, nargout > 0, parse_status, nargout); + } + + octave_value_list tree_evaluator::eval (const std::string& try_code, + const std::string& catch_code, + int nargout) + { + octave_value_list retval; + + error_system& es = m_interpreter.get_error_system (); + + int parse_status = 0; + + bool execution_error = false; + + octave_value_list tmp; + + try + { + tmp = eval_string (try_code, nargout > 0, parse_status, nargout); + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + execution_error = true; + } + + if (parse_status != 0 || execution_error) + { + tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); + + retval = (nargout > 0) ? tmp : octave_value_list (); + } + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever + // exception occurred, not just throwing an + // execution exception. + if (execution_error) + throw execution_exception (); + } + + return retval; + } + + octave_value_list tree_evaluator::evalin (const std::string& context, + const std::string& try_code, + int nargout) + { + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(evalin: CONTEXT must be "caller" or "base")"); + + int parse_status = 0; + + return eval_string (try_code, nargout > 0, parse_status, nargout); + } + + octave_value_list tree_evaluator::evalin (const std::string& context, + const std::string& try_code, + const std::string& catch_code, + int nargout) + { + octave_value_list retval; + + unwind_action act1 ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(evalin: CONTEXT must be "caller" or "base")"); + + error_system& es = m_interpreter.get_error_system (); + + int parse_status = 0; + + bool execution_error = false; + + octave_value_list tmp; + + try + { + tmp = eval_string (try_code, nargout > 0, parse_status, nargout); + } + catch (const execution_exception& ee) + { + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + execution_error = true; + } + + if (parse_status != 0 || execution_error) + { + tmp = eval_string (catch_code, nargout > 0, parse_status, nargout); + + retval = (nargout > 0) ? tmp : octave_value_list (); + } + else + { + if (nargout > 0) + retval = tmp; + + // FIXME: we should really be rethrowing whatever + // exception occurred, not just throwing an + // execution exception. + if (execution_error) + throw execution_exception (); + } + return retval; - - octave_idx_type nbh = 0; - - for (const auto& lval : *lvalues) - nbh += lval.is_black_hole (); - - if (nbh > 0) - { - retval.resize (1, nbh); - - octave_idx_type k = 0; - octave_idx_type l = 0; - - for (const auto& lval : *lvalues) - { - if (lval.is_black_hole ()) - retval(l++) = k+1; - - k += lval.numel (); - } - } - - return retval; -} - -// If NAME is an operator (like "+", "-", ...), convert it to the -// corresponding function name ("plus", "minus", ...). - -static std::string -get_operator_function_name (const std::string& name) -{ - // Bow to the god of compatibility. - - // FIXME: it seems ugly to put this here, but there is no single - // function in the parser that converts from the operator name to - // the corresponding function name. At least try to do it without N - // string compares. - - // FIXME: .+, .-, **, and .** are deprecated but still need to be - // handled here until they are removed. - - std::size_t len = name.length (); - - if (len == 3 && name == ".**") - // deprecated - return "power"; - else if (len == 2) - { - if (name[0] == '.') - { - switch (name[1]) - { - case '\'': - return "transpose"; - - case '+': - // deprecated - return "plus"; - - case '-': - // deprecated - return "minus"; - - case '*': - return "times"; - - case '/': - return "rdivide"; - - case '^': - return "power"; - - case '\\': - return "ldivide"; - - default: - break; - } - } - else if (name[1] == '=') - { - switch (name[0]) - { - case '<': - return "le"; - - case '=': - return "eq"; - - case '>': - return "ge"; - - case '~': - case '!': - return "ne"; - - default: - break; - } - } - else if (name == "**") - // deprecated - return "mpower"; - } - else if (len == 1) - { - switch (name[0]) - { - case '~': - case '!': - return "not"; - - case '\'': - return "ctranspose"; - - case '+': - return "plus"; - - case '-': - return "minus"; - - case '*': - return "mtimes"; - - case '/': - return "mrdivide"; - - case '^': - return "mpower"; - - case '\\': - return "mldivide"; - - case '<': - return "lt"; - - case '>': - return "gt"; - - case '&': - return "and"; - - case '|': - return "or"; - - default: - break; - } - } - - return name; -} - -// Creates a function handle that takes into account the context, -// finding local, nested, private, or sub functions. - -octave_value -tree_evaluator::make_fcn_handle (const std::string& name) -{ - octave_value retval; - - // The str2func function can create a function handle with the name - // of an operator (for example, "+"). If so, it is converted to the - // name of the corresponding function ("+" -> "plus") and we create - // a simple function handle using that name. - - std::string fcn_name = get_operator_function_name (name); - - // If FCN_NAME is different from NAME, then NAME is an operator. As - // of version 2020a, Matlab apparently uses the function name - // corresponding to the operator to search for private and local - // functions in the current scope but not(!) nested functions. - - bool name_is_operator = fcn_name != name; - - std::size_t pos = fcn_name.find ('.'); - - if (pos != std::string::npos) - { - // Recognize (some of? which ones?) the following cases - // and create something other than a simple function handle? - // Should we just be checking for the last two when the first - // element of the dot-separated list is an object? If so, then - // should this syntax be limited to a dot-separated list with - // exactly two elements? - // - // object . method - // object . static-method - // - // Code to do that duplicates some of simple_fcn_handle::call. - - // Only accept expressions that contain one '.' separator. - - // FIXME: The logic here is a bit complicated. Is there a good - // way to simplify it? - - std::string meth_nm = fcn_name.substr (pos+1); - - if (meth_nm.find ('.') == std::string::npos) - { - std::string obj_nm = fcn_name.substr (0, pos); - - // If obj_nm is an object in the current scope with a - // method named meth_nm, create a classsimple handle. - - octave_value object = varval (obj_nm); - - if (object.is_defined () && object.is_classdef_object ()) - { - octave_classdef *cdef = object.classdef_object_value (); - - if (cdef) - { - std::string class_nm = cdef->class_name (); - - cdef_object cdef_obj = cdef->get_object (); - - cdef_class cls = cdef_obj.get_class (); - - cdef_method meth = cls.find_method (meth_nm); - - if (meth.ok ()) - { - // If the method we found is static, create a - // new function name from the class name and - // method name and create a simple function - // handle below. Otherwise, create a class - // simple function handle. - - if (meth.is_static ()) - fcn_name = class_nm + '.' + meth_nm; - else - { - octave_value meth_fcn = meth.get_function (); - - octave_fcn_handle *fh - = new octave_fcn_handle (object, meth_fcn, - class_nm, meth_nm); - - return octave_value (fh); - } - } - } - } - } - - // We didn't match anything above, so create handle to SIMPLE - // package function or static class method. Function resolution - // is performed when the handle is used. - - return octave_value (new octave_fcn_handle (fcn_name)); - } - - // If the function name refers to a sub/local/private function or a - // class method/constructor, create scoped function handle that is - // bound to that function. Use the same precedence list as - // fcn_info::find but limit search to the following types of - // functions: - // - // nested functions (and subfunctions) - // local functions in the current file - // private function - // class method - // - // For anything else we create a simple function handle that will be - // resolved dynamically in the scope where it is evaluated. - - symbol_scope curr_scope = get_current_scope (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - if (curr_scope) - { - octave_value ov_fcn - = symtab.find_scoped_function (fcn_name, curr_scope); - - // If name is operator, we are in Fstr2func, so skip the stack - // frame for that function. - - bool skip_first = name_is_operator; - octave_function *curr_fcn = current_function (skip_first); - - if (ov_fcn.is_defined ()) - { - octave_function *fcn = ov_fcn.function_value (); - - if (fcn->is_nested_function ()) - { - if (! name_is_operator) - { - // Get current stack frame and return handle to nested - // function. - - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - // If we are creating a handle to the current - // function or a handle to a sibling function (i.e., - // not a child of the current function), then use - // the calling stack frame as the context instead of - // the current stack frame. - - // FIXME: Do we need both checks here or is it - // sufficient to check that the parent of curr_fcn - // is the same as the parent of fcn? Is there any - // case where curr_fcn could be nullptr, or does - // that indicate an internal error of some kind? - - if (curr_fcn - && (fcn_name == curr_fcn->name () - || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ())) - frame = frame->access_link (); - - octave_fcn_handle *fh - = new octave_fcn_handle (ov_fcn, fcn_name, frame); - - return octave_value (fh); - } - } - else if (fcn->is_subfunction () - /* || fcn->is_localfunction () */ - || fcn->is_private_function ()) - { - // Create handle to SCOPED function (sub/local function - // or private function). - - std::list parentage = fcn->parent_fcn_names (); - - octave_fcn_handle *fh - = new octave_fcn_handle (ov_fcn, fcn_name, parentage); - - return octave_value (fh); - } - } - - if (curr_fcn && (curr_fcn->is_class_method () - || curr_fcn->is_class_constructor ())) - { - std::string dispatch_class = curr_fcn->dispatch_class (); - - octave_value ov_meth - = symtab.find_method (fcn_name, dispatch_class); - - if (ov_meth.is_defined ()) - { - octave_function *fcn = ov_meth.function_value (); - - // FIXME: do we need to check that it is a method of - // dispatch_class, or is it sufficient to just check - // that it is a method? - - if (fcn->is_class_method ()) - { - // Create CLASSSIMPLE handle to method but don't - // bind to the method. Lookup will be done later. - - octave_fcn_handle *fh - = new octave_fcn_handle (dispatch_class, fcn_name); - - return octave_value (fh); - } - } - } - } - - octave_value ov_fcn = symtab.find_user_function (fcn_name); - - // Create handle to SIMPLE function. If the function is not found - // now, then we will look for it again when the handle is used. - - return octave_value (new octave_fcn_handle (ov_fcn, fcn_name)); -} + } + + void + tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_argument_list (tree_argument_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arguments_block (tree_arguments_block&) + { + warning ("function arguments validation blocks are not supported; INCORRECT RESULTS ARE POSSIBLE"); + } + + void + tree_evaluator::visit_args_block_attribute_list (tree_args_block_attribute_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_args_block_validation_list (tree_args_block_validation_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation (tree_arg_validation&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_size_spec (tree_arg_size_spec&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_arg_validation_fcns (tree_arg_validation_fcns&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_binary_expression (tree_binary_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_boolean_expression (tree_boolean_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_compound_binary_expression (tree_compound_binary_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_break_command (tree_break_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (m_in_loop_command) + m_breaking = 1; + else + error ("break must appear in a loop in the same file as loop command"); + } + + void + tree_evaluator::visit_colon_expression (tree_colon_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_continue_command (tree_continue_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (m_in_loop_command) + m_continuing = 1; + } + + bool + tree_evaluator::statement_printing_enabled (void) + { + return ! (m_silent_functions && (m_statement_context == SC_FUNCTION + || m_statement_context == SC_SCRIPT)); + } + + void + tree_evaluator::reset_debug_state (void) + { + m_debug_mode = (m_bp_table.have_breakpoints () + || m_dbstep_flag != 0 + || m_break_on_next_stmt + || in_debug_repl ()); + } + + void + tree_evaluator::reset_debug_state (bool mode) + { + m_debug_mode = mode; + } + + void + tree_evaluator::enter_debugger (const std::string& prompt) + { + unwind_protect frame; + + frame.add (command_history::ignore_entries, + command_history::ignoring_entries ()); + + command_history::ignore_entries (false); + + frame.add (&call_stack::restore_frame, &m_call_stack, + m_call_stack.current_frame ()); + + // Don't allow errors or warnings at the debug prompt to push us + // into deeper levels of debugging. + + error_system& es = m_interpreter.get_error_system (); + + frame.add (&error_system::set_debug_on_error, &es, es.debug_on_error ()); + + frame.add (&error_system::set_debug_on_warning, &es, + es.debug_on_warning ()); + + es.debug_on_error (false); + es.debug_on_warning (false); + + // Go up to the nearest user code frame. + + m_debug_frame = m_call_stack.dbupdown (0); + + // FIXME: probably we just want to print one line, not the + // entire statement, which might span many lines... + // + // tree_print_code tpc (octave_stdout); + // stmt.accept (tpc); + + debugger *dbgr = new debugger (m_interpreter, m_debugger_stack.size ()); + + m_debugger_stack.push (dbgr); + + frame.add ([=] (void) + { + delete m_debugger_stack.top (); + m_debugger_stack.pop (); + reset_debug_state (); + }); + + dbgr->repl (prompt); + } + + void + tree_evaluator::keyboard (const std::string& prompt) + { + enter_debugger (prompt); + } + + void + tree_evaluator::dbupdown (int n, bool verbose) + { + m_debug_frame = m_call_stack.dbupdown (n, verbose); + } + + Matrix + tree_evaluator::ignored_fcn_outputs (void) const + { + Matrix retval; + + const std::list *lvalues = m_lvalue_list; + + if (! lvalues) + return retval; + + octave_idx_type nbh = 0; + + for (const auto& lval : *lvalues) + nbh += lval.is_black_hole (); + + if (nbh > 0) + { + retval.resize (1, nbh); + + octave_idx_type k = 0; + octave_idx_type l = 0; + + for (const auto& lval : *lvalues) + { + if (lval.is_black_hole ()) + retval(l++) = k+1; + + k += lval.numel (); + } + } + + return retval; + } + + // If NAME is an operator (like "+", "-", ...), convert it to the + // corresponding function name ("plus", "minus", ...). + + static std::string + get_operator_function_name (const std::string& name) + { + // Bow to the god of compatibility. + + // FIXME: it seems ugly to put this here, but there is no single + // function in the parser that converts from the operator name to + // the corresponding function name. At least try to do it without N + // string compares. + + std::size_t len = name.length (); + + if (len == 2) + { + if (name[0] == '.') + { + switch (name[1]) + { + case '\'': + return "transpose"; + + case '*': + return "times"; + + case '/': + return "rdivide"; + + case '^': + return "power"; + + case '\\': + return "ldivide"; + + default: + break; + } + } + else if (name[1] == '=') + { + switch (name[0]) + { + case '<': + return "le"; + + case '=': + return "eq"; + + case '>': + return "ge"; + + case '~': + case '!': + return "ne"; + + default: + break; + } + } + } + else if (len == 1) + { + switch (name[0]) + { + case '~': + case '!': + return "not"; + + case '\'': + return "ctranspose"; + + case '+': + return "plus"; + + case '-': + return "minus"; + + case '*': + return "mtimes"; + + case '/': + return "mrdivide"; + + case '^': + return "mpower"; + + case '\\': + return "mldivide"; + + case '<': + return "lt"; + + case '>': + return "gt"; + + case '&': + return "and"; + + case '|': + return "or"; + + default: + break; + } + } + + return name; + } + + // Creates a function handle that takes into account the context, + // finding local, nested, private, or sub functions. + + octave_value + tree_evaluator::make_fcn_handle (const std::string& name) + { + octave_value retval; + + // The str2func function can create a function handle with the name + // of an operator (for example, "+"). If so, it is converted to the + // name of the corresponding function ("+" -> "plus") and we create + // a simple function handle using that name. + + std::string fcn_name = get_operator_function_name (name); + + // If FCN_NAME is different from NAME, then NAME is an operator. As + // of version 2020a, Matlab apparently uses the function name + // corresponding to the operator to search for private and local + // functions in the current scope but not(!) nested functions. + + bool name_is_operator = fcn_name != name; + + std::size_t pos = fcn_name.find ('.'); + + if (pos != std::string::npos) + { + // Recognize (some of? which ones?) the following cases + // and create something other than a simple function handle? + // Should we just be checking for the last two when the first + // element of the dot-separated list is an object? If so, then + // should this syntax be limited to a dot-separated list with + // exactly two elements? + // + // object . method + // object . static-method + // + // Code to do that duplicates some of simple_fcn_handle::call. + + // Only accept expressions that contain one '.' separator. + + // FIXME: The logic here is a bit complicated. Is there a good + // way to simplify it? + + std::string meth_nm = fcn_name.substr (pos+1); + + if (meth_nm.find ('.') == std::string::npos) + { + std::string obj_nm = fcn_name.substr (0, pos); + + // If obj_nm is an object in the current scope with a + // method named meth_nm, create a classsimple handle. + + octave_value object = varval (obj_nm); + + if (object.is_defined () && object.is_classdef_object ()) + { + octave_classdef *cdef = object.classdef_object_value (); + + if (cdef) + { + std::string class_nm = cdef->class_name (); + + cdef_object cdef_obj = cdef->get_object (); + + cdef_class cls = cdef_obj.get_class (); + + cdef_method meth = cls.find_method (meth_nm); + + if (meth.ok ()) + { + // If the method we found is static, create a + // new function name from the class name and + // method name and create a simple function + // handle below. Otherwise, create a class + // simple function handle. + + if (meth.is_static ()) + fcn_name = class_nm + '.' + meth_nm; + else + { + octave_value meth_fcn = meth.get_function (); + + octave_fcn_handle *fh + = new octave_fcn_handle (object, meth_fcn, + class_nm, meth_nm); + + return octave_value (fh); + } + } + } + } + } + + // We didn't match anything above, so create handle to SIMPLE + // package function or static class method. Function resolution + // is performed when the handle is used. + + return octave_value (new octave_fcn_handle (fcn_name)); + } + + // If the function name refers to a sub/local/private function or a + // class method/constructor, create scoped function handle that is + // bound to that function. Use the same precedence list as + // fcn_info::find but limit search to the following types of + // functions: + // + // nested functions (and subfunctions) + // local functions in the current file + // private function + // class method + // + // For anything else we create a simple function handle that will be + // resolved dynamically in the scope where it is evaluated. + + symbol_scope curr_scope = get_current_scope (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + if (curr_scope) + { + octave_value ov_fcn + = symtab.find_scoped_function (fcn_name, curr_scope); + + // If name is operator, we are in Fstr2func, so skip the stack + // frame for that function. + + bool skip_first = name_is_operator; + octave_function *curr_fcn = current_function (skip_first); + + if (ov_fcn.is_defined ()) + { + octave_function *fcn = ov_fcn.function_value (); + + if (fcn->is_nested_function ()) + { + if (! name_is_operator) + { + // Get current stack frame and return handle to nested + // function. + + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + // If we are creating a handle to the current + // function or a handle to a sibling function (i.e., + // not a child of the current function), then use + // the calling stack frame as the context instead of + // the current stack frame. + + // FIXME: Do we need both checks here or is it + // sufficient to check that the parent of curr_fcn + // is the same as the parent of fcn? Is there any + // case where curr_fcn could be nullptr, or does + // that indicate an internal error of some kind? + + if (curr_fcn + && (fcn_name == curr_fcn->name () + || fcn->parent_fcn_name () == curr_fcn->parent_fcn_name ())) + frame = frame->access_link (); + + octave_fcn_handle *fh + = new octave_fcn_handle (ov_fcn, fcn_name, frame); + + return octave_value (fh); + } + } + else if (fcn->is_subfunction () + /* || fcn->is_localfunction () */ + || fcn->is_private_function ()) + { + // Create handle to SCOPED function (sub/local function + // or private function). + + std::list parentage = fcn->parent_fcn_names (); + + octave_fcn_handle *fh + = new octave_fcn_handle (ov_fcn, fcn_name, parentage); + + return octave_value (fh); + } + } + + if (curr_fcn && (curr_fcn->is_class_method () + || curr_fcn->is_class_constructor ())) + { + std::string dispatch_class = curr_fcn->dispatch_class (); + + octave_value ov_meth + = symtab.find_method (fcn_name, dispatch_class); + + if (ov_meth.is_defined ()) + { + octave_function *fcn = ov_meth.function_value (); + + // FIXME: do we need to check that it is a method of + // dispatch_class, or is it sufficient to just check + // that it is a method? + + if (fcn->is_class_method ()) + { + // Create CLASSSIMPLE handle to method but don't + // bind to the method. Lookup will be done later. + + octave_fcn_handle *fh + = new octave_fcn_handle (dispatch_class, fcn_name); + + return octave_value (fh); + } + } + } + } + + octave_value ov_fcn = symtab.find_user_function (fcn_name); + + // Create handle to SIMPLE function. If the function is not found + // now, then we will look for it again when the handle is used. + + return octave_value (new octave_fcn_handle (ov_fcn, fcn_name)); + } /* %!test -%! x = {".**", "power"; -%! ".'", "transpose"; -%! ".+", "plus"; -%! ".-", "minus"; +%! x = {".'", "transpose"; %! ".*", "times"; %! "./", "rdivide"; %! ".^", "power"; @@ -1833,7 +1813,6 @@ %! ">=", "ge"; %! "!=", "ne"; %! "~=", "ne"; -%! "**", "mpower"; %! "~", "not"; %! "!", "not"; %! "\'", "ctranspose"; @@ -1852,401 +1831,401 @@ %! endfor */ -octave_value -tree_evaluator::evaluate (tree_decl_elt *elt) -{ - // Do not allow functions to return null values. - - tree_identifier *id = elt->ident (); - - return id ? id->evaluate (*this).storable_value () : octave_value (); -} - -bool -tree_evaluator::is_variable (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_variable (name); -} - -bool -tree_evaluator::is_local_variable (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_local_variable (name); -} - -bool -tree_evaluator::is_variable (const tree_expression *expr) const -{ - if (expr->is_identifier ()) - { - const tree_identifier *id - = dynamic_cast (expr); - - if (id->is_black_hole ()) - return false; - - return is_variable (id->symbol ()); - } - - return false; -} - -bool -tree_evaluator::is_defined (const tree_expression *expr) const -{ - if (expr->is_identifier ()) - { - const tree_identifier *id - = dynamic_cast (expr); - - return is_defined (id->symbol ()); - } - - return false; -} - -bool -tree_evaluator::is_variable (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_variable (sym); -} - -bool -tree_evaluator::is_defined (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_defined (sym); -} - -bool tree_evaluator::is_global (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->is_global (name); -} - -octave_value -tree_evaluator::varval (const symbol_record& sym) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->varval (sym); -} - -octave_value -tree_evaluator::varval (const std::string& name) const -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->varval (name); -} - -void tree_evaluator::install_variable (const std::string& name, - const octave_value& value, - bool global) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - return frame->install_variable (name, value, global); -} - -octave_value -tree_evaluator::global_varval (const std::string& name) const -{ - return m_call_stack.global_varval (name); -} - -octave_value& -tree_evaluator::global_varref (const std::string& name) -{ - return m_call_stack.global_varref (name); -} - -void -tree_evaluator::global_assign (const std::string& name, - const octave_value& val) -{ - m_call_stack.global_varref (name) = val; -} - -octave_value -tree_evaluator::top_level_varval (const std::string& name) const -{ - return m_call_stack.get_top_level_value (name); -} - -void -tree_evaluator::top_level_assign (const std::string& name, - const octave_value& val) -{ - m_call_stack.set_top_level_value (name, val); -} - -void -tree_evaluator::assign (const std::string& name, const octave_value& val) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->assign (name, val); -} - -void -tree_evaluator::assignin (const std::string& context, - const std::string& name, const octave_value& val) -{ - // FIXME: Can this be done without an unwind-protect frame, simply - // by getting a reference to the caller or base stack frame and - // calling assign on that? - - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(assignin: CONTEXT must be "caller" or "base")"); - - if (valid_identifier (name)) - { - // Put the check here so that we don't slow down assignments - // generally. Any that go through Octave's parser should have - // already been checked. - - if (iskeyword (name)) - error ("assignin: invalid assignment to keyword '%s'", - name.c_str ()); - - assign (name, val); - } - else - error ("assignin: invalid variable name '%s'", name.c_str ()); -} - -void -tree_evaluator::source_file (const std::string& file_name, - const std::string& context, - bool verbose, bool require_file) -{ - // Map from absolute name of script file to recursion level. We - // use a map instead of simply placing a limit on recursion in the - // source_file function so that two mutually recursive scripts - // written as - // - // foo1.m: - // ------ - // foo2 - // - // foo2.m: - // ------ - // foo1 - // - // and called with - // - // foo1 - // - // (for example) will behave the same if they are written as - // - // foo1.m: - // ------ - // source ("foo2.m") - // - // foo2.m: - // ------ - // source ("foo1.m") - // - // and called with - // - // source ("foo1.m") - // - // (for example). - - static std::map source_call_depth; - - std::string file_full_name - = sys::file_ops::tilde_expand (file_name); - - std::size_t pos - = file_full_name.find_last_of (sys::file_ops::dir_sep_str ()); - - std::string dir_name = file_full_name.substr (0, pos); - - file_full_name = sys::env::make_absolute (file_full_name); - - unwind_protect frame; - - if (source_call_depth.find (file_full_name) == source_call_depth.end ()) - source_call_depth[file_full_name] = -1; - - frame.protect_var (source_call_depth[file_full_name]); - - source_call_depth[file_full_name]++; - - if (source_call_depth[file_full_name] >= max_recursion_depth ()) - error ("max_recursion_depth exceeded"); - - if (! context.empty ()) - { - frame.add (&call_stack::restore_frame, &m_call_stack, - m_call_stack.current_frame ()); - - if (context == "caller") - m_call_stack.goto_caller_frame (); - else if (context == "base") - m_call_stack.goto_base_frame (); - else - error (R"(source: CONTEXT must be "caller" or "base")"); - } - - // Find symbol name that would be in symbol_table, if it were loaded. - std::size_t dir_end - = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); - dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1; - - std::size_t extension = file_name.find_last_of ('.'); - if (extension == std::string::npos) - extension = file_name.length (); - - std::string symbol = file_name.substr (dir_end, extension - dir_end); - std::string full_name = sys::canonicalize_file_name (file_name); - - // Check if this file is already loaded (or in the path) - symbol_table& symtab = m_interpreter.get_symbol_table (); - octave_value ov_code = symtab.fcn_table_find (symbol); - - // For compatibility with Matlab, accept both scripts and - // functions. - - if (ov_code.is_user_code ()) - { - octave_user_code *code = ov_code.user_code_value (); - - if (! code - || (sys::canonicalize_file_name (code->fcn_file_name ()) - != full_name)) - { - // Wrong file, so load it below. - ov_code = octave_value (); - } - } - else - { - // Not a script, so load it below. - ov_code = octave_value (); - } - - // If no symbol of this name, or the symbol is for a different - // file, load. - - if (ov_code.is_undefined ()) - { - try - { - ov_code = parse_fcn_file (m_interpreter, file_full_name, - file_name, dir_name, "", "", - require_file, true, false, false); - } - catch (execution_exception& ee) - { - error (ee, "source: error sourcing file '%s'", - file_full_name.c_str ()); - } - } - - // Return or error if we don't have a valid script or function. - - if (ov_code.is_undefined ()) - return; - - if (! ov_code.is_user_code ()) - error ("source: %s is not a script", full_name.c_str ()); - - if (verbose) - { - octave_stdout << "executing commands from " << full_name << " ... "; - octave_stdout.flush (); - } - - octave_user_code *code = ov_code.user_code_value (); - - code->call (*this, 0, octave_value_list ()); - - if (verbose) - octave_stdout << "done." << std::endl; -} - -void -tree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt, - const octave_value& val) -{ - m_call_stack.set_auto_fcn_var (avt, val); -} - -octave_value -tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const -{ - return m_call_stack.get_auto_fcn_var (avt); -} - -void -tree_evaluator::define_parameter_list_from_arg_vector -(tree_parameter_list *param_list, const octave_value_list& args) -{ - if (! param_list || param_list->varargs_only ()) - return; - - int i = -1; - - for (tree_decl_elt *elt : *param_list) - { - i++; - - octave_lvalue ref = elt->lvalue (*this); - - if (i < args.length ()) - { - if (args(i).is_defined () && args(i).is_magic_colon ()) - { - if (! eval_decl_elt (elt)) - error ("no default value for argument %d", i+1); - } - else - ref.define (args(i)); - } - else - eval_decl_elt (elt); - } -} - -void -tree_evaluator::undefine_parameter_list (tree_parameter_list *param_list) -{ - for (tree_decl_elt *elt : *param_list) - { - octave_lvalue ref = elt->lvalue (*this); - - ref.assign (octave_value::op_asn_eq, octave_value ()); - } -} + octave_value + tree_evaluator::evaluate (tree_decl_elt *elt) + { + // Do not allow functions to return null values. + + tree_identifier *id = elt->ident (); + + return id ? id->evaluate (*this).storable_value () : octave_value (); + } + + bool + tree_evaluator::is_variable (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (name); + } + + bool + tree_evaluator::is_local_variable (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_local_variable (name); + } + + bool + tree_evaluator::is_variable (const tree_expression *expr) const + { + if (expr->is_identifier ()) + { + const tree_identifier *id + = dynamic_cast (expr); + + if (id->is_black_hole ()) + return false; + + return is_variable (id->symbol ()); + } + + return false; + } + + bool + tree_evaluator::is_defined (const tree_expression *expr) const + { + if (expr->is_identifier ()) + { + const tree_identifier *id + = dynamic_cast (expr); + + return is_defined (id->symbol ()); + } + + return false; + } + + bool + tree_evaluator::is_variable (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_variable (sym); + } + + bool + tree_evaluator::is_defined (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_defined (sym); + } + + bool tree_evaluator::is_global (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->is_global (name); + } + + octave_value + tree_evaluator::varval (const symbol_record& sym) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (sym); + } + + octave_value + tree_evaluator::varval (const std::string& name) const + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->varval (name); + } + + void tree_evaluator::install_variable (const std::string& name, + const octave_value& value, + bool global) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + return frame->install_variable (name, value, global); + } + + octave_value + tree_evaluator::global_varval (const std::string& name) const + { + return m_call_stack.global_varval (name); + } + + octave_value& + tree_evaluator::global_varref (const std::string& name) + { + return m_call_stack.global_varref (name); + } + + void + tree_evaluator::global_assign (const std::string& name, + const octave_value& val) + { + m_call_stack.global_varref (name) = val; + } + + octave_value + tree_evaluator::top_level_varval (const std::string& name) const + { + return m_call_stack.get_top_level_value (name); + } + + void + tree_evaluator::top_level_assign (const std::string& name, + const octave_value& val) + { + m_call_stack.set_top_level_value (name, val); + } + + void + tree_evaluator::assign (const std::string& name, const octave_value& val) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->assign (name, val); + } + + void + tree_evaluator::assignin (const std::string& context, + const std::string& name, const octave_value& val) + { + // FIXME: Can this be done without an unwind-protect frame, simply + // by getting a reference to the caller or base stack frame and + // calling assign on that? + + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(assignin: CONTEXT must be "caller" or "base")"); + + if (valid_identifier (name)) + { + // Put the check here so that we don't slow down assignments + // generally. Any that go through Octave's parser should have + // already been checked. + + if (iskeyword (name)) + error ("assignin: invalid assignment to keyword '%s'", + name.c_str ()); + + assign (name, val); + } + else + error ("assignin: invalid variable name '%s'", name.c_str ()); + } + + void + tree_evaluator::source_file (const std::string& file_name, + const std::string& context, + bool verbose, bool require_file) + { + // Map from absolute name of script file to recursion level. We + // use a map instead of simply placing a limit on recursion in the + // source_file function so that two mutually recursive scripts + // written as + // + // foo1.m: + // ------ + // foo2 + // + // foo2.m: + // ------ + // foo1 + // + // and called with + // + // foo1 + // + // (for example) will behave the same if they are written as + // + // foo1.m: + // ------ + // source ("foo2.m") + // + // foo2.m: + // ------ + // source ("foo1.m") + // + // and called with + // + // source ("foo1.m") + // + // (for example). + + static std::map source_call_depth; + + std::string file_full_name + = sys::file_ops::tilde_expand (file_name); + + std::size_t pos + = file_full_name.find_last_of (sys::file_ops::dir_sep_str ()); + + std::string dir_name = file_full_name.substr (0, pos); + + file_full_name = sys::env::make_absolute (file_full_name); + + unwind_protect frame; + + if (source_call_depth.find (file_full_name) == source_call_depth.end ()) + source_call_depth[file_full_name] = -1; + + frame.protect_var (source_call_depth[file_full_name]); + + source_call_depth[file_full_name]++; + + if (source_call_depth[file_full_name] >= max_recursion_depth ()) + error ("max_recursion_depth exceeded"); + + if (! context.empty ()) + { + frame.add (&call_stack::restore_frame, &m_call_stack, + m_call_stack.current_frame ()); + + if (context == "caller") + m_call_stack.goto_caller_frame (); + else if (context == "base") + m_call_stack.goto_base_frame (); + else + error (R"(source: CONTEXT must be "caller" or "base")"); + } + + // Find symbol name that would be in symbol_table, if it were loaded. + std::size_t dir_end + = file_name.find_last_of (sys::file_ops::dir_sep_chars ()); + dir_end = (dir_end == std::string::npos) ? 0 : dir_end + 1; + + std::size_t extension = file_name.find_last_of ('.'); + if (extension == std::string::npos) + extension = file_name.length (); + + std::string symbol = file_name.substr (dir_end, extension - dir_end); + std::string full_name = sys::canonicalize_file_name (file_name); + + // Check if this file is already loaded (or in the path) + symbol_table& symtab = m_interpreter.get_symbol_table (); + octave_value ov_code = symtab.fcn_table_find (symbol); + + // For compatibility with Matlab, accept both scripts and + // functions. + + if (ov_code.is_user_code ()) + { + octave_user_code *code = ov_code.user_code_value (); + + if (! code + || (sys::canonicalize_file_name (code->fcn_file_name ()) + != full_name)) + { + // Wrong file, so load it below. + ov_code = octave_value (); + } + } + else + { + // Not a script, so load it below. + ov_code = octave_value (); + } + + // If no symbol of this name, or the symbol is for a different + // file, load. + + if (ov_code.is_undefined ()) + { + try + { + ov_code = parse_fcn_file (m_interpreter, file_full_name, + file_name, dir_name, "", "", + require_file, true, false, false); + } + catch (execution_exception& ee) + { + error (ee, "source: error sourcing file '%s'", + file_full_name.c_str ()); + } + } + + // Return or error if we don't have a valid script or function. + + if (ov_code.is_undefined ()) + return; + + if (! ov_code.is_user_code ()) + error ("source: %s is not a script", full_name.c_str ()); + + if (verbose) + { + octave_stdout << "executing commands from " << full_name << " ... "; + octave_stdout.flush (); + } + + octave_user_code *code = ov_code.user_code_value (); + + code->call (*this, 0, octave_value_list ()); + + if (verbose) + octave_stdout << "done." << std::endl; + } + + void + tree_evaluator::set_auto_fcn_var (stack_frame::auto_var_type avt, + const octave_value& val) + { + m_call_stack.set_auto_fcn_var (avt, val); + } + + octave_value + tree_evaluator::get_auto_fcn_var (stack_frame::auto_var_type avt) const + { + return m_call_stack.get_auto_fcn_var (avt); + } + + void + tree_evaluator::define_parameter_list_from_arg_vector + (tree_parameter_list *param_list, const octave_value_list& args) + { + if (! param_list || param_list->varargs_only ()) + return; + + int i = -1; + + for (tree_decl_elt *elt : *param_list) + { + i++; + + octave_lvalue ref = elt->lvalue (*this); + + if (i < args.length ()) + { + if (args(i).is_defined () && args(i).is_magic_colon ()) + { + if (! eval_decl_elt (elt)) + error ("no default value for argument %d", i+1); + } + else + ref.define (args(i)); + } + else + eval_decl_elt (elt); + } + } + + void + tree_evaluator::undefine_parameter_list (tree_parameter_list *param_list) + { + for (tree_decl_elt *elt : *param_list) + { + octave_lvalue ref = elt->lvalue (*this); + + ref.assign (octave_value::op_asn_eq, octave_value ()); + } + } // END is documented in op-kw-docs. DEFMETHOD (end, interp, args, , @@ -2292,2989 +2271,2988 @@ %! assert (x(minus (minus (end, 1), 1)), 8); */ -octave_value_list -tree_evaluator::convert_to_const_vector (tree_argument_list *args) -{ - std::list arg_vals; - - for (auto elt : *args) - { - // FIXME: is it possible for elt to be invalid? - - if (! elt) + octave_value_list + tree_evaluator::convert_to_const_vector (tree_argument_list *args) + { + std::list arg_vals; + + for (auto elt : *args) + { + // FIXME: is it possible for elt to be invalid? + + if (! elt) + break; + + octave_value tmp = elt->evaluate (*this); + + if (tmp.is_cs_list ()) + { + octave_value_list tmp_ovl = tmp.list_value (); + + for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) + arg_vals.push_back (tmp_ovl(i)); + } + else if (tmp.is_defined ()) + arg_vals.push_back (tmp); + } + + return octave_value_list (arg_vals); + } + + octave_value_list + tree_evaluator::convert_return_list_to_const_vector + (tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs, + const Cell& varargout) + { + octave_idx_type vlen = varargout.numel (); + int len = ret_list->length (); + + // Special case. Will do a shallow copy. + if (len == 0) + return varargout; + else + { + int i = 0; + int k = 0; + int num_ignored = ignored_outputs.numel (); + int ignored = num_ignored > 0 ? ignored_outputs(k) - 1 : -1; + + if (nargout <= len) + { + int nout = nargout > 0 ? nargout : 1; + octave_value_list retval (nout); + + for (tree_decl_elt *elt : *ret_list) + { + if (nargout == 0 && ! is_defined (elt->ident ())) + break; + + if (ignored >= 0 && i == ignored) + { + i++; + k++; + ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + } + else + retval(i++) = evaluate (elt); + + if (i == nout) + break; + } + + return retval; + } + else + { + octave_value_list retval (len + vlen); + + for (tree_decl_elt *elt : *ret_list) + { + if (ignored >= 0 && i == ignored) + { + i++; + k++; + ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + } + else + retval(i++) = evaluate (elt); + } + + for (octave_idx_type j = 0; j < vlen; j++) + retval(i++) = varargout(j); + + return retval; + } + } + } + + bool + tree_evaluator::eval_decl_elt (tree_decl_elt *elt) + { + bool retval = false; + + tree_identifier *id = elt->ident (); + tree_expression *expr = elt->expression (); + + if (id && expr) + { + octave_lvalue ult = id->lvalue (*this); + + octave_value init_val = expr->evaluate (*this); + + ult.assign (octave_value::op_asn_eq, init_val); + + retval = true; + } + + return retval; + } + + bool + tree_evaluator::switch_case_label_matches (tree_switch_case *expr, + const octave_value& val) + { + tree_expression *label = expr->case_label (); + + octave_value label_value = label->evaluate (*this); + + if (label_value.is_defined ()) + { + if (label_value.iscell ()) + { + Cell cell (label_value.cell_value ()); + + for (octave_idx_type i = 0; i < cell.rows (); i++) + { + for (octave_idx_type j = 0; j < cell.columns (); j++) + { + bool match = val.is_equal (cell(i,j)); + + if (match) + return true; + } + } + } + else + return val.is_equal (label_value); + } + + return false; + } + + void tree_evaluator::push_stack_frame (const symbol_scope& scope) + { + m_call_stack.push (scope); + } + + void tree_evaluator::push_stack_frame (octave_user_function *fcn, + const std::shared_ptr& closure_frames) + { + m_call_stack.push (fcn, closure_frames); + } + + void tree_evaluator::push_stack_frame (octave_user_function *fcn, + const stack_frame::local_vars_map& local_vars, + const std::shared_ptr& closure_frames) + { + m_call_stack.push (fcn, local_vars, closure_frames); + } + + void tree_evaluator::push_stack_frame (octave_user_script *script) + { + m_call_stack.push (script); + } + + void tree_evaluator::push_stack_frame (octave_function *fcn) + { + m_call_stack.push (fcn); + } + + void tree_evaluator::pop_stack_frame (void) + { + m_call_stack.pop (); + } + + int tree_evaluator::current_line (void) const + { + return m_call_stack.current_line (); + } + + int tree_evaluator::current_column (void) const + { + return m_call_stack.current_column (); + } + + int tree_evaluator::debug_user_code_line (void) const + { + return m_call_stack.debug_user_code_line (); + } + + int tree_evaluator::debug_user_code_column (void) const + { + return m_call_stack.debug_user_code_column (); + } + + void tree_evaluator::debug_where (std::ostream& os) const + { + std::shared_ptr frm = m_call_stack.current_user_frame (); + + frm->display_stopped_in_message (os); + } + + octave_user_code * tree_evaluator::current_user_code (void) const + { + return m_call_stack.current_user_code (); + } + + unwind_protect * tree_evaluator::curr_fcn_unwind_protect_frame (void) + { + return m_call_stack.curr_fcn_unwind_protect_frame (); + } + + octave_user_code * tree_evaluator::debug_user_code (void) const + { + return m_call_stack.debug_user_code (); + } + + octave_function * tree_evaluator::current_function (bool skip_first) const + { + return m_call_stack.current_function (skip_first); + } + + octave_function * tree_evaluator::caller_function (void) const + { + return m_call_stack.current_function (true); + } + + bool tree_evaluator::goto_frame (std::size_t n, bool verbose) + { + return m_call_stack.goto_frame (n, verbose); + } + + void tree_evaluator::goto_caller_frame (void) + { + m_call_stack.goto_caller_frame (); + } + + void tree_evaluator::goto_base_frame (void) + { + m_call_stack.goto_base_frame (); + } + + void tree_evaluator::restore_frame (std::size_t n) + { + return m_call_stack.restore_frame (n); + } + + std::string tree_evaluator::get_dispatch_class (void) const + { + return m_call_stack.get_dispatch_class (); + } + + void tree_evaluator::set_dispatch_class (const std::string& class_name) + { + m_call_stack.set_dispatch_class (class_name); + } + + bool + tree_evaluator::is_class_method_executing (std::string& dclass) const + { + return m_call_stack.is_class_method_executing (dclass); + } + + bool + tree_evaluator::is_class_constructor_executing (std::string& dclass) const + { + return m_call_stack.is_class_constructor_executing (dclass); + } + + std::list> + tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const + { + return m_call_stack.backtrace_frames (curr_user_frame); + } + + std::list> + tree_evaluator::backtrace_frames (void) const + { + return m_call_stack.backtrace_frames (); + } + + std::list + tree_evaluator::backtrace_info (octave_idx_type& curr_user_frame, + bool print_subfn) const + { + return m_call_stack.backtrace_info (curr_user_frame, print_subfn); + } + + std::list tree_evaluator::backtrace_info (void) const + { + return m_call_stack.backtrace_info (); + } + + octave_map + tree_evaluator::backtrace (octave_idx_type& curr_user_frame, + bool print_subfn) const + { + return m_call_stack.backtrace (curr_user_frame, print_subfn); + } + + octave_map tree_evaluator::backtrace (void) const + { + return m_call_stack.backtrace (); + } + + octave_map tree_evaluator::empty_backtrace (void) const + { + return m_call_stack.empty_backtrace (); + } + + std::string tree_evaluator::backtrace_message (void) const + { + std::list frames = backtrace_info (); + + std::ostringstream buf; + + for (const auto& frm : frames) + { + buf << " " << frm.fcn_name (); + + int line = frm.line (); + + if (line > 0) + { + buf << " at line " << line; + + int column = frm.column (); + + if (column > 0) + buf << " column " << column; + + buf << "\n"; + } + } + + return buf.str (); + } + + void tree_evaluator::push_dummy_scope (const std::string& name) + { + symbol_scope dummy_scope (name + "$dummy"); + + m_call_stack.push (dummy_scope); + } + + void tree_evaluator::pop_scope (void) + { + m_call_stack.pop (); + } + + symbol_scope tree_evaluator::get_top_scope (void) const + { + return m_call_stack.top_scope (); + } + + symbol_scope tree_evaluator::get_current_scope (void) const + { + return m_call_stack.current_scope (); + } + + void tree_evaluator::mlock (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("mlock: locking built-in function has no effect"); + return; + } + + fcn->lock (); + } + + void tree_evaluator::munlock (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("munlock: invalid use outside a function"); + + if (fcn->is_builtin_function ()) + { + warning ("munlock: unlocking built-in function has no effect"); + return; + } + + fcn->unlock (); + } + + bool tree_evaluator::mislocked (bool skip_first) const + { + octave_function *fcn = m_call_stack.current_function (skip_first); + + if (! fcn) + error ("mislocked: invalid use outside a function"); + + return fcn->islocked (); + } + + octave_value + tree_evaluator::max_stack_depth (const octave_value_list& args, int nargout) + { + return m_call_stack.max_stack_depth (args, nargout); + } + + void tree_evaluator::display_call_stack (void) const + { + m_call_stack.display (); + } + + octave_value tree_evaluator::find (const std::string& name) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + octave_value val = frame->varval (name); + + if (val.is_defined ()) + return val; + + // Subfunction. I think it only makes sense to check for + // subfunctions if we are currently executing a function defined + // from a .m file. + + octave_value fcn = frame->find_subfunction (name); + + if (fcn.is_defined ()) + return fcn; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + return symtab.fcn_table_find (name, ovl ()); + } + + void tree_evaluator::clear_objects (void) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_objects (); + } + + void tree_evaluator::clear_variable (const std::string& name) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable (name); + } + + void tree_evaluator::clear_variable_pattern (const std::string& pattern) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_pattern (pattern); + } + + void tree_evaluator::clear_variable_regexp (const std::string& pattern) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variable_regexp (pattern); + } + + void tree_evaluator::clear_variables (void) + { + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + frame->clear_variables (); + } + + void tree_evaluator::clear_global_variable (const std::string& name) + { + m_call_stack.clear_global_variable (name); + } + + void + tree_evaluator::clear_global_variable_pattern (const std::string& pattern) + { + m_call_stack.clear_global_variable_pattern (pattern); + } + + void tree_evaluator::clear_global_variable_regexp(const std::string& pattern) + { + m_call_stack.clear_global_variable_regexp (pattern); + } + + void tree_evaluator::clear_global_variables (void) + { + m_call_stack.clear_global_variables (); + } + + void tree_evaluator::clear_all (bool force) + { + // FIXME: should this also clear objects? + + clear_variables (); + clear_global_variables (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_functions (force); + } + + void tree_evaluator::clear_symbol (const std::string& name) + { + // FIXME: are we supposed to do both here? + + clear_variable (name); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function (name); + } + + void tree_evaluator::clear_symbol_pattern (const std::string& pattern) + { + // FIXME: are we supposed to do both here? + + clear_variable_pattern (pattern); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function_pattern (pattern); + } + + void tree_evaluator::clear_symbol_regexp (const std::string& pattern) + { + // FIXME: are we supposed to do both here? + + clear_variable_regexp (pattern); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_function_regexp (pattern); + } + + std::list tree_evaluator::global_variable_names (void) const + { + return m_call_stack.global_variable_names (); + } + + std::list tree_evaluator::top_level_variable_names (void) const + { + return m_call_stack.top_level_variable_names (); + } + + std::list tree_evaluator::variable_names (void) const + { + return m_call_stack.variable_names (); + } + + // Return a pointer to the user-defined function FNAME. If FNAME is empty, + // search backward for the first user-defined function in the + // current call stack. + + octave_user_code * + tree_evaluator::get_user_code (const std::string& fname, + const std::string& class_name) + { + octave_user_code *user_code = nullptr; + + if (fname.empty ()) + user_code = m_call_stack.debug_user_code (); + else + { + std::string name = fname; + + if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') + { + auto beg = name.begin () + 2; // never have @/method + auto end = name.end () - 1; // never have trailing '/' + std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); + } + + std::size_t name_len = name.length (); + + if (name_len > 2 && name.substr (name_len-2) == ".m") + name = name.substr (0, name_len-2); + + if (name.empty ()) + return nullptr; + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn; + std::size_t p2 = std::string::npos; + + if (name[0] == '@') + { + std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1); + + if (p1 == std::string::npos) + return nullptr; + + std::string dispatch_type = name.substr (1, p1-1); + + p2 = name.find ('>', p1); + + std::string method = name.substr (p1+1, p2-1); + + fcn = symtab.find_method (method, dispatch_type); + } + else if (! class_name.empty ()) + { + cdef_manager& cdm = m_interpreter.get_cdef_manager (); + + fcn = cdm.find_method (class_name, name); + + // If there is no classdef method, then try legacy classes. + if (fcn.is_undefined ()) + fcn = symtab.find_method (name, class_name); + } + else + { + p2 = name.find ('>'); + + std::string main_fcn = name.substr (0, p2); + + fcn = symtab.find_function (main_fcn); + } + + // List of function names sub1>sub2>... + std::string subfuns; + + if (p2 != std::string::npos) + subfuns = name.substr (p2+1); + + if (fcn.is_defined () && fcn.is_user_code ()) + user_code = fcn.user_code_value (); + + if (! user_code || subfuns.empty ()) + return user_code; + + fcn = user_code->find_subfunction (subfuns); + + if (fcn.is_undefined ()) + return nullptr; + + user_code = fcn.user_code_value (); + } + + return user_code; + } + + std::string + tree_evaluator::current_function_name (bool skip_first) const + { + octave_function *curfcn = m_call_stack.current_function (skip_first); + + if (curfcn) + return curfcn->name (); + + return ""; + } + + bool + tree_evaluator::in_user_code (void) const + { + return m_call_stack.current_user_code () != nullptr; + } + + void + tree_evaluator::visit_decl_command (tree_decl_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // FIXME: tree_decl_init_list is not derived from tree, so should it + // really have an accept method? + + tree_decl_init_list *init_list = cmd.initializer_list (); + + if (init_list) + init_list->accept (*this); + } + + void + tree_evaluator::visit_decl_elt (tree_decl_elt& elt) + { + tree_identifier *id = elt.ident (); + + if (id) + { + if (elt.is_global ()) + m_call_stack.make_global (id->symbol ()); + else if (elt.is_persistent ()) + m_call_stack.make_persistent (id->symbol ()); + else + error ("declaration list element not global or persistent"); + + octave_lvalue ult = id->lvalue (*this); + + if (ult.is_undefined ()) + { + tree_expression *expr = elt.expression (); + + octave_value init_val; + + if (expr) + init_val = expr->evaluate (*this); + else + init_val = Matrix (); + + ult.assign (octave_value::op_asn_eq, init_val); + } + } + } + + template + void + tree_evaluator::execute_range_loop (const range& rng, int line, + octave_lvalue& ult, + tree_statement_list *loop_body) + { + octave_idx_type steps = rng.numel (); + + if (math::isinf (rng.limit ())) + warning_with_id ("Octave:infinite-loop", + "FOR loop limit is infinite, will stop after %" + OCTAVE_IDX_TYPE_FORMAT " steps", steps); + + for (octave_idx_type i = 0; i < steps; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + octave_value val (rng.elem (i)); + + ult.assign (octave_value::op_asn_eq, val); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + + void + tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // FIXME: need to handle PARFOR loops here using cmd.in_parallel () + // and cmd.maxproc_expr (); + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.control_expr (); + + octave_value rhs = expr->evaluate (*this); + + if (rhs.is_undefined ()) + return; + + tree_expression *lhs = cmd.left_hand_side (); + + octave_lvalue ult = lhs->lvalue (*this); + + tree_statement_list *loop_body = cmd.body (); + + if (rhs.is_range ()) + { + // FIXME: is there a better way to dispatch here? + + if (rhs.is_double_type ()) + { + execute_range_loop (rhs.range_value (), line, ult, loop_body); + return; + } + + // For now, disable all but range. + +#if 0 + if (rhs.is_int64_type ()) + { + execute_range_loop (rhs.int64_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint64_type ()) + { + execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int32_type ()) + { + execute_range_loop (rhs.int32_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint32_type ()) + { + execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int16_type ()) + { + execute_range_loop (rhs.int16_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint16_type ()) + { + execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_int8_type ()) + { + execute_range_loop (rhs.int8_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_uint8_type ()) + { + execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body); + return; + } + + if (rhs.is_single_type ()) + { + execute_range_loop (rhs.float_range_value (), line, ult, loop_body); + return; + } +#endif + } + + if (rhs.is_scalar_type ()) + { + if (m_echo_state) + m_echo_file_pos = line; + + ult.assign (octave_value::op_asn_eq, rhs); + + if (loop_body) + loop_body->accept (*this); + + // Maybe decrement break and continue states. + quit_loop_now (); + + return; + } + + // Also handle any range types not explicitly handled above, though + // not as efficiently as the specialized code above. + + if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell () + || rhs.is_string () || rhs.isstruct ()) + { + // A matrix or cell is reshaped to 2 dimensions and iterated by + // columns. + + dim_vector dv = rhs.dims ().redim (2); + + octave_idx_type nrows = dv(0); + octave_idx_type steps = dv(1); + + octave_value arg = rhs; + if (rhs.ndims () > 2) + arg = arg.reshape (dv); + + if (nrows > 0 && steps > 0) + { + octave_value_list idx; + octave_idx_type iidx; + + // for row vectors, use single index to speed things up. + if (nrows == 1) + { + idx.resize (1); + iidx = 0; + } + else + { + idx.resize (2); + idx(0) = octave_value::magic_colon_t; + iidx = 1; + } + + for (octave_idx_type i = 1; i <= steps; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + // index_op expects one-based indices. + idx(iidx) = i; + octave_value val = arg.index_op (idx); + + ult.assign (octave_value::op_asn_eq, val); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + else + { + // Handle empty cases, while still assigning to loop var. + ult.assign (octave_value::op_asn_eq, arg); + } + + return; + } + + error ("invalid type in for loop expression near line %d, column %d", + cmd.line (), cmd.column ()); + } + + void + tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.control_expr (); + + octave_value rhs = expr->evaluate (*this); + + if (rhs.is_undefined ()) + return; + + if (! rhs.isstruct ()) + error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); + + // Cycle through structure elements. First element of id_list + // is set to value and the second is set to the name of the + // structure element. + + tree_argument_list *lhs = cmd.left_hand_side (); + + auto p = lhs->begin (); + + tree_expression *elt = *p++; + + octave_lvalue val_ref = elt->lvalue (*this); + + elt = *p; + + octave_lvalue key_ref = elt->lvalue (*this); + + const octave_map tmp_val = rhs.map_value (); + + tree_statement_list *loop_body = cmd.body (); + + string_vector keys = tmp_val.keys (); + + octave_idx_type nel = keys.numel (); + + for (octave_idx_type i = 0; i < nel; i++) + { + if (m_echo_state) + m_echo_file_pos = line; + + std::string key = keys[i]; + + const Cell val_lst = tmp_val.contents (key); + + octave_idx_type n = val_lst.numel (); + + octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); + + val_ref.assign (octave_value::op_asn_eq, val); + key_ref.assign (octave_value::op_asn_eq, key); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + } + + void tree_evaluator::visit_spmd_command (tree_spmd_command& cmd) + { + // For now, we just execute the commands serially. + + tree_statement_list *body = cmd.body (); + + if (body) + body->accept (*this); + } + + octave_value + tree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh) + { + // FIXME: should CMD_LIST be limited to a single expression? + // I think that is what Matlab does. + + symbol_scope new_scope; + symbol_scope scope = afh.scope (); + if (scope) + new_scope = scope.dup (); + + tree_parameter_list *param_list = afh.parameter_list (); + tree_parameter_list *param_list_dup + = param_list ? param_list->dup (new_scope) : nullptr; + + tree_parameter_list *ret_list = nullptr; + + tree_statement_list *stmt_list = nullptr; + + symbol_scope parent_scope = get_current_scope (); + + new_scope.set_parent (parent_scope); + new_scope.set_primary_parent (parent_scope); + + tree_expression *expr = afh.expression (); + if (expr) + { + tree_expression *expr_dup = expr->dup (new_scope); + tree_statement *stmt = new tree_statement (expr_dup, nullptr); + stmt_list = new tree_statement_list (stmt); + } + + tree_anon_scopes anon_fcn_ctx (afh); + + std::set free_vars = anon_fcn_ctx.free_variables (); + + stack_frame::local_vars_map local_vars; + + std::shared_ptr frame + = m_call_stack.get_current_stack_frame (); + + for (auto& name : free_vars) + { + octave_value val = frame->varval (name); + + if (val.is_defined ()) + local_vars[name] = val; + } + + octave_user_function *af + = new octave_user_function (new_scope, param_list_dup, ret_list, + stmt_list); + + octave_function *curr_fcn = m_call_stack.current_function (); + + bool is_nested = false; + + if (curr_fcn) + { + // FIXME: maybe it would be better to just stash curr_fcn + // instead of individual bits of info about it? + + // An anonymous function defined inside another nested function + // or parent of a nested function also behaves like a nested + // function. + + if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ()) + { + is_nested = true; + af->mark_as_nested_function (); + new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1); + } + + af->stash_dir_name (curr_fcn->dir_name ()); + + new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ()); + new_scope.cache_dir_name (curr_fcn->dir_name ()); + + // The following is needed so that class method dispatch works + // properly for anonymous functions that wrap class methods. + + if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ()) + af->stash_dispatch_class (curr_fcn->dispatch_class ()); + + af->stash_fcn_file_name (curr_fcn->fcn_file_name ()); + } + + af->mark_as_anonymous_function (); + + octave_value ov_fcn (af); + + return (is_nested + ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame)) + : octave_value (new octave_fcn_handle (ov_fcn, local_vars))); + } + + octave_value_list + tree_evaluator::execute_builtin_function (octave_builtin& builtin_function, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + if (args.has_magic_colon ()) + error ("invalid use of colon in function argument list"); + + profiler::enter block (m_profiler, builtin_function); + + octave_builtin::fcn fcn = builtin_function.function (); + + if (fcn) + retval = (*fcn) (args, nargout); + else + { + octave_builtin::meth meth = builtin_function.method (); + + retval = (*meth) (m_interpreter, args, nargout); + } + + // Do not allow null values to be returned from functions. + // FIXME: perhaps true builtins should be allowed? + + retval.make_storable_values (); + + // Fix the case of a single undefined value. + // This happens when a compiled function uses + // + // octave_value retval; + // + // instead of + // + // octave_value_list retval; + // + // the idiom is very common, so we solve that here. + + if (retval.length () == 1 && retval.xelem (0).is_undefined ()) + retval.clear (); + + return retval; + } + + octave_value_list + tree_evaluator::execute_mex_function (octave_mex_function& mex_function, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + if (args.has_magic_colon ()) + error ("invalid use of colon in function argument list"); + + profiler::enter block (m_profiler, mex_function); + + retval = call_mex (mex_function, args, nargout); + + return retval; + } + + octave_value_list + tree_evaluator::execute_user_script (octave_user_script& user_script, + int nargout, + const octave_value_list& args) + { + octave_value_list retval; + + std::string file_name = user_script.fcn_file_name (); + + if (args.length () != 0 || nargout != 0) + error ("invalid call to script %s", file_name.c_str ()); + + tree_statement_list *cmd_list = user_script.body (); + + if (! cmd_list) + return retval; + + // FIXME: Maybe this check belongs in the places where we push a new + // stack frame? Or in the call_stack push method itself? + + if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) + error ("max_recursion_depth exceeded"); + + unwind_protect_var upv (m_statement_context, SC_SCRIPT); + + profiler::enter block (m_profiler, user_script); + + if (echo ()) + push_echo_state (tree_evaluator::ECHO_SCRIPTS, file_name); + + // FIXME: Should we be using tree_evaluator::eval here? + + cmd_list->accept (*this); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + + return retval; + } + + void + tree_evaluator::visit_octave_user_script (octave_user_script&) + { + // ?? + panic_impossible (); + } + + octave_value_list + tree_evaluator::execute_user_function (octave_user_function& user_function, + int nargout, + const octave_value_list& xargs) + { + octave_value_list retval; + + // If this function is a classdef constructor, extract the first input + // argument, which must be the partially constructed object instance. + + octave_value_list args (xargs); + octave_value_list ret_args; + + int nargin = args.length (); + + if (user_function.is_classdef_constructor ()) + { + if (nargin > 0) + { + ret_args = args.slice (0, 1, true); + --nargin; + args = args.slice (1, nargin, true); + } + else + panic_impossible (); + } + + // FIXME: this probably shouldn't be a double-precision matrix. + Matrix ignored_outputs = ignored_fcn_outputs (); + + tree_parameter_list *param_list = user_function.parameter_list (); + + bool takes_varargs = false; + int max_inputs = 0; + + if (param_list) + { + takes_varargs = param_list->takes_varargs (); + max_inputs = param_list->length (); + } + + if (! takes_varargs && nargin > max_inputs) + { + std::string name = user_function.name (); + + if (name.empty ()) + name = "@"; + + error_with_id ("Octave:invalid-fun-call", + "%s: function called with too many inputs", + name.c_str ()); + } + + define_parameter_list_from_arg_vector (param_list, args); + + tree_parameter_list *ret_list = user_function.return_list (); + + if (ret_list && ! ret_list->takes_varargs ()) + { + int max_outputs = ret_list->length (); + + if (nargout > max_outputs) + { + std::string name = user_function.name (); + + error_with_id ("Octave:invalid-fun-call", + "%s: function called with too many outputs", + name.c_str ()); + } + } + + bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin, + nargout, user_function.takes_varargs (), + user_function.all_va_args (args)); + + // For classdef constructor, pre-populate the output arguments + // with the pre-initialized object instance, extracted above. + + if (user_function.is_classdef_constructor ()) + { + if (! ret_list) + error ("%s: invalid classdef constructor, no output argument defined", + user_function.dispatch_class ().c_str ()); + + define_parameter_list_from_arg_vector (ret_list, ret_args); + } + + // FIXME: Maybe this check belongs in the places where we push a + // new stack frame? Or in the call_stack push method itself? + + if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) + error ("max_recursion_depth exceeded"); + + unwind_action act2 ([&user_function] () { + user_function.restore_warning_states (); + }); + + // Evaluate the commands that make up the function. + + unwind_protect_var upv (m_statement_context, SC_FUNCTION); + + tree_statement_list *cmd_list = user_function.body (); + + if (cmd_list) + { + profiler::enter + block (m_profiler, user_function); + + if (echo ()) + push_echo_state (tree_evaluator::ECHO_FUNCTIONS, + user_function.fcn_file_name ()); + + if (user_function.is_special_expr ()) + { + panic_if (cmd_list->length () != 1); + + tree_statement *stmt = cmd_list->front (); + + tree_expression *expr = stmt->expression (); + + if (expr) + { + m_call_stack.set_location (stmt->line (), stmt->column ()); + + retval = expr->evaluate_n (*this, nargout); + } + } + else + cmd_list->accept (*this); + + if (m_returning) + m_returning = 0; + + if (m_breaking) + m_breaking--; + } + + // Copy return values out. + + if (ret_list && ! user_function.is_special_expr ()) + { + Cell varargout; + + if (ret_list->takes_varargs ()) + { + octave_value varargout_varval = varval ("varargout"); + + if (varargout_varval.is_defined ()) + varargout = varargout_varval.xcell_value ("varargout must be a cell array object"); + } + + retval = convert_return_list_to_const_vector (ret_list, nargout, + ignored_outputs, + varargout); + } + + return retval; + } + + void + tree_evaluator::visit_octave_user_function (octave_user_function&) + { + // ?? + panic_impossible (); + } + + void + tree_evaluator::visit_octave_user_function_header (octave_user_function&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_function_def (tree_function_def& cmd) + { + octave_value fcn = cmd.function (); + + octave_function *f = fcn.function_value (); + + if (f) + { + std::string nm = f->name (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.install_cmdline_function (nm, fcn); + + // Make sure that any variable with the same name as the new + // function is cleared. + + assign (nm); + } + } + + void + tree_evaluator::visit_identifier (tree_identifier&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_if_clause (tree_if_clause&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_if_command (tree_if_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + // FIXME: tree_if_command_list is not derived from tree, so should it + // really have an accept method? + + tree_if_command_list *lst = cmd.cmd_list (); + + if (lst) + lst->accept (*this); + } + + void + tree_evaluator::visit_if_command_list (tree_if_command_list& lst) + { + for (tree_if_clause *tic : lst) + { + tree_expression *expr = tic->condition (); + + if (! (in_debug_repl () + && m_call_stack.current_frame () == m_debug_frame)) + m_call_stack.set_location (tic->line (), tic->column ()); + + if (m_debug_mode && ! tic->is_else_clause ()) + do_breakpoint (tic->is_active_breakpoint (*this)); + + if (tic->is_else_clause () || is_logically_true (expr, "if")) + { + tree_statement_list *stmt_lst = tic->commands (); + + if (stmt_lst) + stmt_lst->accept (*this); + + break; + } + } + } + + void + tree_evaluator::visit_index_expression (tree_index_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_matrix (tree_matrix&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_cell (tree_cell&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_multi_assignment (tree_multi_assignment&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode && cmd.is_end_of_fcn_or_script ()) + do_breakpoint (cmd.is_active_breakpoint (*this), true); + } + + void + tree_evaluator::visit_constant (tree_constant&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_fcn_handle (tree_fcn_handle&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_parameter_list (tree_parameter_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_postfix_expression (tree_postfix_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_prefix_expression (tree_prefix_expression&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_return_command (tree_return_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + // Act like dbcont. + + if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame) + dbcont (); + else if (m_statement_context == SC_FUNCTION + || m_statement_context == SC_SCRIPT + || m_in_loop_command) + m_returning = 1; + } + + void + tree_evaluator::visit_simple_assignment (tree_simple_assignment&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_statement (tree_statement& stmt) + { + tree_command *cmd = stmt.command (); + tree_expression *expr = stmt.expression (); + + if (cmd || expr) + { + if (! (in_debug_repl () + && m_call_stack.current_frame () == m_debug_frame)) + m_call_stack.set_location (stmt.line (), stmt.column ()); + + try + { + if (cmd) + { + unwind_protect_var *> + upv (m_lvalue_list, nullptr); + + cmd->accept (*this); + } + else + { + if (m_echo_state) + { + int line = stmt.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (expr->is_active_breakpoint (*this)); + + // FIXME: maybe all of this should be packaged in + // one virtual function that returns a flag saying whether + // or not the expression will take care of binding ans and + // printing the result. + + // FIXME: it seems that we should just have to + // evaluate the expression and that should take care of + // everything, binding ans as necessary? + + octave_value tmp_result = expr->evaluate (*this, 0); + + if (tmp_result.is_defined ()) + { + bool do_bind_ans = false; + + if (expr->is_identifier ()) + do_bind_ans = ! is_variable (expr); + else + do_bind_ans = ! expr->is_assignment_expression (); + + if (do_bind_ans) + bind_ans (tmp_result, expr->print_result () + && statement_printing_enabled ()); + } + } + } + catch (const std::bad_alloc&) + { + // FIXME: We want to use error_with_id here so that give users + // control over this error message but error_with_id will + // require some memory allocations. Is there anything we can + // do to make those more likely to succeed? + + error_with_id ("Octave:bad-alloc", + "out of memory or dimension too large for Octave's index type"); + } + catch (const interrupt_exception&) + { + // If we are debugging, then continue with next statement. + // Otherwise, jump out of here. + + if (m_debug_mode) + m_interpreter.recover_from_exception (); + else + throw; + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + if ((m_interpreter.interactive () + || application::forced_interactive ()) + && ((es.debug_on_error () + && m_bp_table.debug_on_err (es.last_error_id ())) + || (es.debug_on_caught () + && m_bp_table.debug_on_caught (es.last_error_id ()))) + && in_user_code ()) + { + es.save_exception (ee); + es.display_exception (ee); + + enter_debugger (); + + // It doesn't make sense to continue execution after an + // error occurs so force the debugger to quit all debug + // levels and return the the top prompt. + + throw quit_debug_exception (true); + } + else + throw; + } + } + } + + void + tree_evaluator::visit_statement_list (tree_statement_list& lst) + { + // FIXME: commented out along with else clause below. + // static octave_value_list empty_list; + + auto p = lst.begin (); + + if (p != lst.end ()) + { + while (true) + { + tree_statement *elt = *p++; + + if (! elt) + error ("invalid statement found in statement list!"); + + octave_quit (); + + elt->accept (*this); + + if (m_breaking || m_continuing) + break; + + if (m_returning) + break; + + if (p == lst.end ()) + break; + else + { + // Clear previous values before next statement is + // evaluated so that we aren't holding an extra + // reference to a value that may be used next. For + // example, in code like this: + // + // X = rand (N); # refcount for X should be 1 + // # after this statement + // + // X(idx) = val; # no extra copy of X should be + // # needed, but we will be faked + // # out if retval is not cleared + // # between statements here + + // result_values = empty_list; + } + } + } + } + + void + tree_evaluator::visit_switch_case (tree_switch_case&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_switch_case_list (tree_switch_case_list&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_switch_command (tree_switch_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + tree_expression *expr = cmd.switch_value (); + + if (! expr) + error ("missing value in switch command near line %d, column %d", + cmd.line (), cmd.column ()); + + octave_value val = expr->evaluate (*this); + + tree_switch_case_list *lst = cmd.case_list (); + + if (lst) + { + for (tree_switch_case *t : *lst) + { + if (t->is_default_case () || switch_case_label_matches (t, val)) + { + tree_statement_list *stmt_lst = t->commands (); + + if (stmt_lst) + stmt_lst->accept (*this); + + break; + } + } + } + } + + void + tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + bool execution_error = false; + octave_scalar_map err_map; + + tree_statement_list *try_code = cmd.body (); + + if (try_code) + { + // unwind frame before catch block + + unwind_protect frame; + + interpreter_try (frame); + + // The catch code is *not* added to unwind_protect stack; it + // doesn't need to be run on interrupts. + + try + { + try_code->accept (*this); + } + catch (const execution_exception& ee) + { + execution_error = true; + + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + + err_map.assign ("message", es.last_error_message ()); + err_map.assign ("identifier", es.last_error_id ()); + err_map.assign ("stack", es.last_error_stack ()); + + m_interpreter.recover_from_exception (); + } + + // Actions attached to unwind_protect frame will run here, prior + // to executing the catch block. + } + + if (execution_error) + { + tree_statement_list *catch_code = cmd.cleanup (); + + if (catch_code) + { + tree_identifier *expr_id = cmd.identifier (); + + if (expr_id) + { + octave_lvalue ult = expr_id->lvalue (*this); + + ult.assign (octave_value::op_asn_eq, err_map); + } + + // perform actual "catch" block + catch_code->accept (*this); + } + } + } + + void + tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) + { + unwind_protect frame; + + frame.protect_var (octave_interrupt_state); + octave_interrupt_state = 0; + + // We want to preserve the last location info for possible + // backtracking. + + frame.add (&call_stack::set_line, &m_call_stack, + m_call_stack.current_line ()); + + frame.add (&call_stack::set_column, &m_call_stack, + m_call_stack.current_column ()); + + // Similarly, if we have seen a return or break statement, allow all + // the cleanup code to run before returning or handling the break. + // We don't have to worry about continue statements because they can + // only occur in loops. + + frame.protect_var (m_returning); + m_returning = 0; + + frame.protect_var (m_breaking); + m_breaking = 0; + + try + { + if (list) + list->accept (*this); + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + if (m_breaking || m_returning) + frame.discard (2); + else + frame.run (2); + + frame.discard (2); + + throw; + } + + // The unwind_protects are popped off the stack in the reverse of + // the order they are pushed on. + + // FIXME: these statements say that if we see a break or + // return statement in the cleanup block, that we want to use the + // new value of the breaking or returning flag instead of restoring + // the previous value. Is that the right thing to do? I think so. + // Consider the case of + // + // function foo () + // unwind_protect + // fprintf (stderr, "1: this should always be executed\n"); + // break; + // fprintf (stderr, "1: this should never be executed\n"); + // unwind_protect_cleanup + // fprintf (stderr, "2: this should always be executed\n"); + // return; + // fprintf (stderr, "2: this should never be executed\n"); + // end_unwind_protect + // endfunction + // + // If we reset the value of the breaking flag, both the returning + // flag and the breaking flag will be set, and we shouldn't have + // both. So, use the most recent one. If there is no return or + // break in the cleanup block, the values should be reset to + // whatever they were when the cleanup block was entered. + + if (m_breaking || m_returning) + frame.discard (2); + else + frame.run (2); + } + + void + tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) + { + if (m_echo_state) + { + int line = cmd.line (); + if (line < 0) + line = 1; + echo_code (line); + m_echo_file_pos = line + 1; + } + + tree_statement_list *cleanup_code = cmd.cleanup (); + + tree_statement_list *unwind_protect_code = cmd.body (); + + if (unwind_protect_code) + { + try + { + unwind_protect_code->accept (*this); + } + catch (const execution_exception& ee) + { + error_system& es = m_interpreter.get_error_system (); + + // FIXME: Maybe we should be able to temporarily set the + // interpreter's exception handling state to something "safe" + // while the cleanup block runs instead of just resetting it + // here? + es.save_exception (ee); + m_interpreter.recover_from_exception (); + + // Run the cleanup code on exceptions, so that it is run even + // in case of interrupt or out-of-memory. + do_unwind_protect_cleanup_code (cleanup_code); + + // If an error occurs inside the cleanup code, a new + // exception will be thrown instead of the original. + throw; + } + catch (const interrupt_exception&) + { + // The comments above apply here as well. + m_interpreter.recover_from_exception (); + do_unwind_protect_cleanup_code (cleanup_code); + throw; + } + + // Also execute the unwind_protect_cleanump code if the + // unwind_protect block runs without error. + do_unwind_protect_cleanup_code (cleanup_code); + } + } + + void + tree_evaluator::visit_while_command (tree_while_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.condition (); + + if (! expr) + panic_impossible (); + + for (;;) + { + if (m_echo_state) + m_echo_file_pos = line; + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (is_logically_true (expr, "while")) + { + tree_statement_list *loop_body = cmd.body (); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + } + else + break; + } + } + + void + tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) + { + int line = cmd.line (); + if (line < 0) + line = 1; + + if (m_echo_state) + { + echo_code (line); + line++; + } + + unwind_protect_var upv (m_in_loop_command, true); + + tree_expression *expr = cmd.condition (); + + if (! expr) + panic_impossible (); + + for (;;) + { + if (m_echo_state) + m_echo_file_pos = line; + + tree_statement_list *loop_body = cmd.body (); + + if (loop_body) + loop_body->accept (*this); + + if (quit_loop_now ()) + break; + + if (m_debug_mode) + do_breakpoint (cmd.is_active_breakpoint (*this)); + + if (is_logically_true (expr, "do-until")) + break; + } + } + + void + tree_evaluator::visit_superclass_ref (tree_superclass_ref&) + { + panic_impossible (); + } + + void + tree_evaluator::visit_metaclass_query (tree_metaclass_query&) + { + panic_impossible (); + } + + void tree_evaluator::bind_ans (const octave_value& val, bool print) + { + static std::string ans = "ans"; + + if (val.is_defined ()) + { + if (val.is_cs_list ()) + { + octave_value_list lst = val.list_value (); + + for (octave_idx_type i = 0; i < lst.length (); i++) + bind_ans (lst(i), print); + } + else + { + // FIXME: Maybe assign could also return the assigned value, + // just for convenience? + + assign (ans, val); + + if (print) + { + // Use varval instead of displaying VAL directly so that + // we get the right type and value for things like + // magic_int values that may mutate when stored. + + octave_value_list args = ovl (varval (ans)); + args.stash_name_tags (string_vector (ans)); + feval ("display", args); + } + } + } + } + + void + tree_evaluator::do_breakpoint (tree_statement& stmt) + { + do_breakpoint (stmt.is_active_breakpoint (*this), + stmt.is_end_of_fcn_or_script ()); + } + + void + tree_evaluator::do_breakpoint (bool is_breakpoint, + bool is_end_of_fcn_or_script) + { + bool break_on_this_statement = false; + + if (is_breakpoint) + break_on_this_statement = true; + else if (m_dbstep_flag > 0) + { + if (m_call_stack.current_frame () == m_debug_frame) + { + if (m_dbstep_flag == 1 || is_end_of_fcn_or_script) + { + // We get here if we are doing a "dbstep" or a "dbstep N" and + // the count has reached 1 so that we must stop and return to + // debug prompt. Alternatively, "dbstep N" has been used but + // the end of the frame has been reached so we stop at the last + // line and return to prompt. + + break_on_this_statement = true; + } + else + { + // Executing "dbstep N". Decrease N by one and continue. + + m_dbstep_flag--; + } + + } + else if (m_dbstep_flag == 1 + && m_call_stack.current_frame () < m_debug_frame) + { + // We stepped out from the end of a function. + + m_debug_frame = m_call_stack.current_frame (); + + break_on_this_statement = true; + } + } + else if (m_dbstep_flag == -1) + { + // We get here if we are doing a "dbstep in". + + break_on_this_statement = true; + + m_debug_frame = m_call_stack.current_frame (); + } + else if (m_dbstep_flag == -2) + { + // We get here if we are doing a "dbstep out". Check for end of + // function and whether the current frame is the same as the + // cached value because we want to step out from the frame where + // "dbstep out" was evaluated, not from any functions called from + // that frame. + + if (is_end_of_fcn_or_script + && m_call_stack.current_frame () == m_debug_frame) + m_dbstep_flag = -1; + } + + if (! break_on_this_statement) + break_on_this_statement = m_break_on_next_stmt; + + m_break_on_next_stmt = false; + + if (break_on_this_statement) + { + m_dbstep_flag = 0; + + enter_debugger (); + } + } + + bool + tree_evaluator::is_logically_true (tree_expression *expr, + const char *warn_for) + { + bool expr_value = false; + + m_call_stack.set_location (expr->line (), expr->column ()); + + octave_value t1 = expr->evaluate (*this); + + if (t1.is_defined ()) + return t1.is_true (); + else + error ("%s: undefined value used in conditional expression", warn_for); + + return expr_value; + } + + octave_value + tree_evaluator::max_recursion_depth (const octave_value_list& args, + int nargout) + { + return set_internal_variable (m_max_recursion_depth, args, nargout, + "max_recursion_depth", 0); + } + + symbol_info_list + tree_evaluator::glob_symbol_info (const std::string& pattern) const + { + return m_call_stack.glob_symbol_info (pattern); + } + + symbol_info_list + tree_evaluator::regexp_symbol_info (const std::string& pattern) const + { + return m_call_stack.regexp_symbol_info (pattern); + } + + symbol_info_list + tree_evaluator::get_symbol_info (void) + { + return m_call_stack.get_symbol_info (); + } + + symbol_info_list + tree_evaluator::top_scope_symbol_info (void) const + { + return m_call_stack.top_scope_symbol_info (); + } + + octave_map tree_evaluator::get_autoload_map (void) const + { + Cell fcn_names (dim_vector (m_autoload_map.size (), 1)); + Cell file_names (dim_vector (m_autoload_map.size (), 1)); + + octave_idx_type i = 0; + for (const auto& fcn_fname : m_autoload_map) + { + fcn_names(i) = fcn_fname.first; + file_names(i) = fcn_fname.second; + + i++; + } + + octave_map m; + + m.assign ("function", fcn_names); + m.assign ("file", file_names); + + return m; + } + + std::string tree_evaluator::lookup_autoload (const std::string& nm) const + { + std::string retval; + + auto p = m_autoload_map.find (nm); + + if (p != m_autoload_map.end ()) + { + load_path& lp = m_interpreter.get_load_path (); + + retval = lp.find_file (p->second); + } + + return retval; + } + + std::list tree_evaluator::autoloaded_functions (void) const + { + std::list names; + + for (const auto& fcn_fname : m_autoload_map) + names.push_back (fcn_fname.first); + + return names; + } + + std::list + tree_evaluator::reverse_lookup_autoload (const std::string& nm) const + { + std::list names; + + for (const auto& fcn_fname : m_autoload_map) + if (nm == fcn_fname.second) + names.push_back (fcn_fname.first); + + return names; + } + + void tree_evaluator::add_autoload (const std::string& fcn, + const std::string& nm) + { + std::string file_name = check_autoload_file (nm); + + m_autoload_map[fcn] = file_name; + } + + void tree_evaluator::remove_autoload (const std::string& fcn, + const std::string& nm) + { + check_autoload_file (nm); + + // Remove function from symbol table and autoload map. + symbol_table& symtab = m_interpreter.get_symbol_table (); + + symtab.clear_dld_function (fcn); + + m_autoload_map.erase (fcn); + } + + octave_value + tree_evaluator::whos_line_format (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_whos_line_format, args, nargout, + "whos_line_format"); + } + + octave_value + tree_evaluator::silent_functions (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_silent_functions, args, nargout, + "silent_functions"); + } + + octave_value + tree_evaluator::string_fill_char (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_string_fill_char, args, nargout, + "string_fill_char"); + } + + // Final step of processing an indexing error. Add the name of the + // variable being indexed, if any, then issue an error. (Will this also + // be needed by pt-lvalue, which calls subsref?) + + void tree_evaluator::final_index_error (index_exception& ie, + const tree_expression *expr) + { + std::string extra_message; + + if (is_variable (expr)) + { + std::string var = expr->name (); + + ie.set_var (var); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value fcn = symtab.find_function (var); + + if (fcn.is_function ()) + { + octave_function *fp = fcn.function_value (); + + if (fp && fp->name () == var) + extra_message + = " (note: variable '" + var + "' shadows function)"; + } + } + + std::string msg = ie.message () + extra_message; + + error_with_id (ie.err_id (), "%s", msg.c_str ()); + } + + octave_value + tree_evaluator::do_who (int argc, const string_vector& argv, + bool return_list, bool verbose) + { + return m_call_stack.do_who (argc, argv, return_list, verbose); + } + + octave_value_list + tree_evaluator::make_value_list (tree_argument_list *args, + const string_vector& arg_nm) + { + octave_value_list retval; + + if (args) + { + unwind_protect_var *> + upv (m_lvalue_list, nullptr); + + int len = args->length (); + + unwind_protect_var upv2 (m_index_position); + unwind_protect_var upv3 (m_num_indices); + + m_num_indices = len; + + std::list arg_vals; + + int k = 0; + + for (auto elt : *args) + { + // FIXME: is it possible for elt to be invalid? + + if (! elt) + break; + + m_index_position = k++; + + octave_value tmp = elt->evaluate (*this); + + if (tmp.is_cs_list ()) + { + octave_value_list tmp_ovl = tmp.list_value (); + + for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) + arg_vals.push_back (tmp_ovl(i)); + } + else if (tmp.is_defined ()) + arg_vals.push_back (tmp); + } + + retval = octave_value_list (arg_vals); + } + + octave_idx_type n = retval.length (); + + if (n > 0) + retval.stash_name_tags (arg_nm); + + return retval; + } + + std::list + tree_evaluator::make_lvalue_list (tree_argument_list *lhs) + { + std::list retval; + + for (tree_expression *elt : *lhs) + retval.push_back (elt->lvalue (*this)); + + return retval; + } + + void + tree_evaluator::push_echo_state (int type, const std::string& file_name, + int pos) + { + unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); + + if (frame) + { + push_echo_state_cleanup (*frame); + + set_echo_state (type, file_name, pos); + } + } + + void + tree_evaluator::set_echo_state (int type, const std::string& file_name, + int pos) + { + m_echo_state = echo_this_file (file_name, type); + m_echo_file_name = file_name; + m_echo_file_pos = pos; + } + + void + tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name, + int pos) + { + m_echo_state = state; + m_echo_file_name = file_name; + m_echo_file_pos = pos; + } + + void + tree_evaluator::maybe_set_echo_state (void) + { + octave_function *caller = caller_function (); + + if (caller && caller->is_user_code ()) + { + octave_user_code *fcn = dynamic_cast (caller); + + int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS; + + std::string file_name = fcn->fcn_file_name (); + + // We want the line where "echo" was called, not the line number + // stored in the stack frame that was created for the echo + // function (that will always be -1). + + int pos = m_call_stack.current_user_code_line (); + + if (pos < 0) + pos = 1; + + set_echo_state (type, file_name, pos); + } + } + + void + tree_evaluator::push_echo_state_cleanup (unwind_protect& frame) + { + frame.add (&tree_evaluator::uwp_set_echo_state, this, + m_echo_state, m_echo_file_name, m_echo_file_pos); + } + + bool tree_evaluator::maybe_push_echo_state_cleanup (void) + { + // This function is expected to be called from ECHO, which would be + // the top of the call stack. If the caller of ECHO is a + // user-defined function or script, then set up unwind-protect + // elements to restore echo state. + + unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); + + if (frame) + { + push_echo_state_cleanup (*frame); + return true; + } + + return false; + } + + + octave_value + tree_evaluator::echo (const octave_value_list& args, int) + { + bool cleanup_pushed = maybe_push_echo_state_cleanup (); + + string_vector argv = args.make_argv (); + + switch (args.length ()) + { + case 0: + if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS)) + { + m_echo = ECHO_OFF; + m_echo_files.clear (); + } + else + m_echo = ECHO_SCRIPTS; break; - octave_value tmp = elt->evaluate (*this); - - if (tmp.is_cs_list ()) + case 1: { - octave_value_list tmp_ovl = tmp.list_value (); - - for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) - arg_vals.push_back (tmp_ovl(i)); - } - else if (tmp.is_defined ()) - arg_vals.push_back (tmp); - } - - return octave_value_list (arg_vals); -} - -octave_value_list -tree_evaluator::convert_return_list_to_const_vector -(tree_parameter_list *ret_list, int nargout, const Matrix& ignored_outputs, - const Cell& varargout) -{ - octave_idx_type vlen = varargout.numel (); - int len = ret_list->length (); - - // Special case. Will do a shallow copy. - if (len == 0) - return varargout; - else - { - int i = 0; - int k = 0; - int num_ignored = ignored_outputs.numel (); - int ignored = num_ignored > 0 ? ignored_outputs(k) - 1 : -1; - - if (nargout <= len) - { - int nout = nargout > 0 ? nargout : 1; - octave_value_list retval (nout); - - for (tree_decl_elt *elt : *ret_list) + std::string arg0 = argv[0]; + + if (arg0 == "on") + m_echo = ECHO_SCRIPTS; + else if (arg0 == "off") + m_echo = ECHO_OFF; + else { - if (nargout == 0 && ! is_defined (elt->ident ())) - break; - - if (ignored >= 0 && i == ignored) + std::string file = fcn_file_in_path (arg0); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg0.c_str ()); + + if (m_echo & ECHO_ALL) { - i++; - k++; - ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; + // Echo is enabled for all functions, so turn it off + // for this one. + + m_echo_files[file] = false; } else - retval(i++) = evaluate (elt); - - if (i == nout) - break; - } - - return retval; - } - else - { - octave_value_list retval (len + vlen); - - for (tree_decl_elt *elt : *ret_list) - { - if (ignored >= 0 && i == ignored) { - i++; - k++; - ignored = k < num_ignored ? ignored_outputs(k) - 1 : -1; - } - else - retval(i++) = evaluate (elt); - } - - for (octave_idx_type j = 0; j < vlen; j++) - retval(i++) = varargout(j); - - return retval; - } - } -} - -bool -tree_evaluator::eval_decl_elt (tree_decl_elt *elt) -{ - bool retval = false; - - tree_identifier *id = elt->ident (); - tree_expression *expr = elt->expression (); - - if (id && expr) - { - octave_lvalue ult = id->lvalue (*this); - - octave_value init_val = expr->evaluate (*this); - - ult.assign (octave_value::op_asn_eq, init_val); - - retval = true; - } - - return retval; -} - -bool -tree_evaluator::switch_case_label_matches (tree_switch_case *expr, - const octave_value& val) -{ - tree_expression *label = expr->case_label (); - - octave_value label_value = label->evaluate (*this); - - if (label_value.is_defined ()) - { - if (label_value.iscell ()) - { - Cell cell (label_value.cell_value ()); - - for (octave_idx_type i = 0; i < cell.rows (); i++) - { - for (octave_idx_type j = 0; j < cell.columns (); j++) - { - bool match = val.is_equal (cell(i, j)); - - if (match) - return true; + // Echo may be enabled for specific functions. + + auto p = m_echo_files.find (file); + + if (p == m_echo_files.end ()) + { + // Not this one, so enable it. + + m_echo |= ECHO_FUNCTIONS; + m_echo_files[file] = true; + } + else + { + // This one is already in the list. Flip the + // status for it. + + p->second = ! p->second; + } } } } - else - return val.is_equal (label_value); - } - - return false; -} - -void tree_evaluator::push_stack_frame (const symbol_scope& scope) -{ - m_call_stack.push (scope); -} - -void tree_evaluator::push_stack_frame (octave_user_function *fcn, - const std::shared_ptr& closure_frames) -{ - m_call_stack.push (fcn, closure_frames); -} - -void tree_evaluator::push_stack_frame (octave_user_function *fcn, - const stack_frame::local_vars_map& local_vars, - const std::shared_ptr& closure_frames) -{ - m_call_stack.push (fcn, local_vars, closure_frames); -} - -void tree_evaluator::push_stack_frame (octave_user_script *script) -{ - m_call_stack.push (script); -} - -void tree_evaluator::push_stack_frame (octave_function *fcn) -{ - m_call_stack.push (fcn); -} - -void tree_evaluator::pop_stack_frame (void) -{ - m_call_stack.pop (); -} - -int tree_evaluator::current_line (void) const -{ - return m_call_stack.current_line (); -} - -int tree_evaluator::current_column (void) const -{ - return m_call_stack.current_column (); -} - -int tree_evaluator::debug_user_code_line (void) const -{ - return m_call_stack.debug_user_code_line (); -} - -int tree_evaluator::debug_user_code_column (void) const -{ - return m_call_stack.debug_user_code_column (); -} - -void tree_evaluator::debug_where (std::ostream& os) const -{ - std::shared_ptr frm = m_call_stack.current_user_frame (); - - frm->display_stopped_in_message (os); -} - -octave_user_code *tree_evaluator::current_user_code (void) const -{ - return m_call_stack.current_user_code (); -} - -unwind_protect *tree_evaluator::curr_fcn_unwind_protect_frame (void) -{ - return m_call_stack.curr_fcn_unwind_protect_frame (); -} - -octave_user_code *tree_evaluator::debug_user_code (void) const -{ - return m_call_stack.debug_user_code (); -} - -octave_function *tree_evaluator::current_function (bool skip_first) const -{ - return m_call_stack.current_function (skip_first); -} - -octave_function *tree_evaluator::caller_function (void) const -{ - return m_call_stack.current_function (true); -} - -bool tree_evaluator::goto_frame (std::size_t n, bool verbose) -{ - return m_call_stack.goto_frame (n, verbose); -} - -void tree_evaluator::goto_caller_frame (void) -{ - m_call_stack.goto_caller_frame (); -} - -void tree_evaluator::goto_base_frame (void) -{ - m_call_stack.goto_base_frame (); -} - -void tree_evaluator::restore_frame (std::size_t n) -{ - return m_call_stack.restore_frame (n); -} - -std::string tree_evaluator::get_dispatch_class (void) const -{ - return m_call_stack.get_dispatch_class (); -} - -void tree_evaluator::set_dispatch_class (const std::string& class_name) -{ - m_call_stack.set_dispatch_class (class_name); -} - -bool -tree_evaluator::is_class_method_executing (std::string& dclass) const -{ - return m_call_stack.is_class_method_executing (dclass); -} - -bool -tree_evaluator::is_class_constructor_executing (std::string& dclass) const -{ - return m_call_stack.is_class_constructor_executing (dclass); -} - -std::list> - tree_evaluator::backtrace_frames (octave_idx_type& curr_user_frame) const -{ - return m_call_stack.backtrace_frames (curr_user_frame); -} - -std::list> - tree_evaluator::backtrace_frames (void) const -{ - return m_call_stack.backtrace_frames (); -} - -std::list -tree_evaluator::backtrace_info (octave_idx_type& curr_user_frame, - bool print_subfn) const -{ - return m_call_stack.backtrace_info (curr_user_frame, print_subfn); -} - -std::list tree_evaluator::backtrace_info (void) const -{ - return m_call_stack.backtrace_info (); -} - -octave_map -tree_evaluator::backtrace (octave_idx_type& curr_user_frame, - bool print_subfn) const -{ - return m_call_stack.backtrace (curr_user_frame, print_subfn); -} - -octave_map tree_evaluator::backtrace (void) const -{ - return m_call_stack.backtrace (); -} - -octave_map tree_evaluator::empty_backtrace (void) const -{ - return m_call_stack.empty_backtrace (); -} - -std::string tree_evaluator::backtrace_message (void) const -{ - std::list frames = backtrace_info (); - - std::ostringstream buf; - - for (const auto& frm : frames) - { - buf << " " << frm.fcn_name (); - - int line = frm.line (); - - if (line > 0) + break; + + case 2: { - buf << " at line " << line; - - int column = frm.column (); - - if (column > 0) - buf << " column " << column; - - buf << "\n"; - } - } - - return buf.str (); -} - -void tree_evaluator::push_dummy_scope (const std::string& name) -{ - symbol_scope dummy_scope (name + "$dummy"); - - m_call_stack.push (dummy_scope); -} - -void tree_evaluator::pop_scope (void) -{ - m_call_stack.pop (); -} - -symbol_scope tree_evaluator::get_top_scope (void) const -{ - return m_call_stack.top_scope (); -} - -symbol_scope tree_evaluator::get_current_scope (void) const -{ - return m_call_stack.current_scope (); -} - -void tree_evaluator::mlock (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("mlock: invalid use outside a function"); - - if (fcn->is_builtin_function ()) - { - warning ("mlock: locking built-in function has no effect"); - return; - } - - fcn->lock (); -} - -void tree_evaluator::munlock (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("munlock: invalid use outside a function"); - - if (fcn->is_builtin_function ()) - { - warning ("munlock: unlocking built-in function has no effect"); - return; - } - - fcn->unlock (); -} - -bool tree_evaluator::mislocked (bool skip_first) const -{ - octave_function *fcn = m_call_stack.current_function (skip_first); - - if (! fcn) - error ("mislocked: invalid use outside a function"); - - return fcn->islocked (); -} - -octave_value -tree_evaluator::max_stack_depth (const octave_value_list& args, int nargout) -{ - return m_call_stack.max_stack_depth (args, nargout); -} - -void tree_evaluator::display_call_stack (void) const -{ - m_call_stack.display (); -} - -octave_value tree_evaluator::find (const std::string& name) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - octave_value val = frame->varval (name); - - if (val.is_defined ()) - return val; - - // Subfunction. I think it only makes sense to check for - // subfunctions if we are currently executing a function defined - // from a .m file. - - octave_value fcn = frame->find_subfunction (name); - - if (fcn.is_defined ()) - return fcn; - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - return symtab.fcn_table_find (name, ovl ()); -} - -void tree_evaluator::clear_objects (void) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_objects (); -} - -void tree_evaluator::clear_variable (const std::string& name) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable (name); -} - -void tree_evaluator::clear_variable_pattern (const std::string& pattern) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable_pattern (pattern); -} - -void tree_evaluator::clear_variable_regexp (const std::string& pattern) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variable_regexp (pattern); -} - -void tree_evaluator::clear_variables (void) -{ - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - frame->clear_variables (); -} - -void tree_evaluator::clear_global_variable (const std::string& name) -{ - m_call_stack.clear_global_variable (name); -} - -void -tree_evaluator::clear_global_variable_pattern (const std::string& pattern) -{ - m_call_stack.clear_global_variable_pattern (pattern); -} - -void tree_evaluator::clear_global_variable_regexp(const std::string& pattern) -{ - m_call_stack.clear_global_variable_regexp (pattern); -} - -void tree_evaluator::clear_global_variables (void) -{ - m_call_stack.clear_global_variables (); -} - -void tree_evaluator::clear_all (bool force) -{ - // FIXME: should this also clear objects? - - clear_variables (); - clear_global_variables (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_functions (force); -} - -void tree_evaluator::clear_symbol (const std::string& name) -{ - // FIXME: are we supposed to do both here? - - clear_variable (name); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function (name); -} - -void tree_evaluator::clear_symbol_pattern (const std::string& pattern) -{ - // FIXME: are we supposed to do both here? - - clear_variable_pattern (pattern); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function_pattern (pattern); -} - -void tree_evaluator::clear_symbol_regexp (const std::string& pattern) -{ - // FIXME: are we supposed to do both here? - - clear_variable_regexp (pattern); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_function_regexp (pattern); -} - -std::list tree_evaluator::global_variable_names (void) const -{ - return m_call_stack.global_variable_names (); -} - -std::list tree_evaluator::top_level_variable_names (void) const -{ - return m_call_stack.top_level_variable_names (); -} - -std::list tree_evaluator::variable_names (void) const -{ - return m_call_stack.variable_names (); -} - -// Return a pointer to the user-defined function FNAME. If FNAME is empty, -// search backward for the first user-defined function in the -// current call stack. - -octave_user_code * -tree_evaluator::get_user_code (const std::string& fname, - const std::string& class_name) -{ - octave_user_code *user_code = nullptr; - - if (fname.empty ()) - user_code = m_call_stack.debug_user_code (); - else - { - std::string name = fname; - - if (sys::file_ops::dir_sep_char () != '/' && name[0] == '@') - { - auto beg = name.begin () + 2; // never have @/method - auto end = name.end () - 1; // never have trailing '/' - std::replace (beg, end, '/', sys::file_ops::dir_sep_char ()); - } - - std::size_t name_len = name.length (); - - if (name_len > 2 && name.substr (name_len-2) == ".m") - name = name.substr (0, name_len-2); - - if (name.empty ()) - return nullptr; - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value fcn; - std::size_t p2 = std::string::npos; - - if (name[0] == '@') - { - std::size_t p1 = name.find (sys::file_ops::dir_sep_char (), 1); - - if (p1 == std::string::npos) - return nullptr; - - std::string dispatch_type = name.substr (1, p1-1); - - p2 = name.find ('>', p1); - - std::string method = name.substr (p1+1, p2-1); - - fcn = symtab.find_method (method, dispatch_type); - } - else if (! class_name.empty ()) - { - cdef_manager& cdm = m_interpreter.get_cdef_manager (); - - fcn = cdm.find_method (class_name, name); - - // If there is no classdef method, then try legacy classes. - if (fcn.is_undefined ()) - fcn = symtab.find_method (name, class_name); - } - else - { - p2 = name.find ('>'); - - std::string main_fcn = name.substr (0, p2); - - fcn = symtab.find_function (main_fcn); - } - - // List of function names sub1>sub2>... - std::string subfuns; - - if (p2 != std::string::npos) - subfuns = name.substr (p2+1); - - if (fcn.is_defined () && fcn.is_user_code ()) - user_code = fcn.user_code_value (); - - if (! user_code || subfuns.empty ()) - return user_code; - - fcn = user_code->find_subfunction (subfuns); - - if (fcn.is_undefined ()) - return nullptr; - - user_code = fcn.user_code_value (); - } - - return user_code; -} - -std::string -tree_evaluator::current_function_name (bool skip_first) const -{ - octave_function *curfcn = m_call_stack.current_function (skip_first); - - if (curfcn) - return curfcn->name (); - - return ""; -} - -bool -tree_evaluator::in_user_code (void) const -{ - return m_call_stack.current_user_code () != nullptr; -} - -void -tree_evaluator::visit_decl_command (tree_decl_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // FIXME: tree_decl_init_list is not derived from tree, so should it - // really have an accept method? - - tree_decl_init_list *init_list = cmd.initializer_list (); - - if (init_list) - init_list->accept (*this); -} - -void -tree_evaluator::visit_decl_elt (tree_decl_elt& elt) -{ - tree_identifier *id = elt.ident (); - - if (id) - { - if (elt.is_global ()) - m_call_stack.make_global (id->symbol ()); - else if (elt.is_persistent ()) - m_call_stack.make_persistent (id->symbol ()); - else - error ("declaration list element not global or persistent"); - - octave_lvalue ult = id->lvalue (*this); - - if (ult.is_undefined ()) - { - tree_expression *expr = elt.expression (); - - octave_value init_val; - - if (expr) - init_val = expr->evaluate (*this); - else - init_val = Matrix (); - - ult.assign (octave_value::op_asn_eq, init_val); - } - } -} - -template -void -tree_evaluator::execute_range_loop (const range& rng, int line, - octave_lvalue& ult, - tree_statement_list *loop_body) -{ - octave_idx_type steps = rng.numel (); - - if (math::isinf (rng.limit ())) - warning_with_id ("Octave:infinite-loop", - "FOR loop limit is infinite, will stop after %" - OCTAVE_IDX_TYPE_FORMAT " steps", steps); - - for (octave_idx_type i = 0; i < steps; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - octave_value val (rng.elem (i)); - - ult.assign (octave_value::op_asn_eq, val); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } -} - -void -tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // FIXME: need to handle PARFOR loops here using cmd.in_parallel () - // and cmd.maxproc_expr (); - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.control_expr (); - - octave_value rhs = expr->evaluate (*this); - - if (rhs.is_undefined ()) - return; - - tree_expression *lhs = cmd.left_hand_side (); - - octave_lvalue ult = lhs->lvalue (*this); - - tree_statement_list *loop_body = cmd.body (); - - if (rhs.is_range ()) - { - // FIXME: is there a better way to dispatch here? - - if (rhs.is_double_type ()) - { - execute_range_loop (rhs.range_value (), line, ult, loop_body); - return; - } - - // For now, disable all but range. - -#if 0 - if (rhs.is_int64_type ()) - { - execute_range_loop (rhs.int64_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint64_type ()) - { - execute_range_loop (rhs.uint64_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int32_type ()) - { - execute_range_loop (rhs.int32_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint32_type ()) - { - execute_range_loop (rhs.uint32_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int16_type ()) - { - execute_range_loop (rhs.int16_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint16_type ()) - { - execute_range_loop (rhs.uint16_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_int8_type ()) - { - execute_range_loop (rhs.int8_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_uint8_type ()) - { - execute_range_loop (rhs.uint8_range_value (), line, ult, loop_body); - return; - } - - if (rhs.is_single_type ()) - { - execute_range_loop (rhs.float_range_value (), line, ult, loop_body); - return; - } -#endif - } - - if (rhs.is_scalar_type ()) - { - if (m_echo_state) - m_echo_file_pos = line; - - ult.assign (octave_value::op_asn_eq, rhs); - - if (loop_body) - loop_body->accept (*this); - - // Maybe decrement break and continue states. - quit_loop_now (); - - return; - } - - // Also handle any range types not explicitly handled above, though - // not as efficiently as the specialized code above. - - if (rhs.is_range () || rhs.is_matrix_type () || rhs.iscell () - || rhs.is_string () || rhs.isstruct ()) - { - // A matrix or cell is reshaped to 2 dimensions and iterated by - // columns. - - dim_vector dv = rhs.dims ().redim (2); - - octave_idx_type nrows = dv(0); - octave_idx_type steps = dv(1); - - octave_value arg = rhs; - if (rhs.ndims () > 2) - arg = arg.reshape (dv); - - if (nrows > 0 && steps > 0) - { - octave_value_list idx; - octave_idx_type iidx; - - // for row vectors, use single index to speed things up. - if (nrows == 1) + std::string arg0 = argv[0]; + std::string arg1 = argv[1]; + + if (arg1 == "on" || arg1 == "off") + std::swap (arg0, arg1); + + if (arg0 == "on") { - idx.resize (1); - iidx = 0; + if (arg1 == "all") + { + m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL); + m_echo_files.clear (); + } + else + { + std::string file = fcn_file_in_path (arg1); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg1.c_str ()); + + m_echo |= ECHO_FUNCTIONS; + m_echo_files[file] = true; + } + } + else if (arg0 == "off") + { + if (arg1 == "all") + { + m_echo = ECHO_OFF; + m_echo_files.clear (); + } + else + { + std::string file = fcn_file_in_path (arg1); + file = sys::env::make_absolute (file); + + if (file.empty ()) + error ("echo: no such file %s", arg1.c_str ()); + + m_echo_files[file] = false; + } } else - { - idx.resize (2); - idx(0) = octave_value::magic_colon_t; - iidx = 1; - } - - for (octave_idx_type i = 1; i <= steps; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - // index_op expects one-based indices. - idx(iidx) = i; - octave_value val = arg.index_op (idx); - - ult.assign (octave_value::op_asn_eq, val); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } - } - else - { - // Handle empty cases, while still assigning to loop var. - ult.assign (octave_value::op_asn_eq, arg); - } - - return; - } - - error ("invalid type in for loop expression near line %d, column %d", - cmd.line (), cmd.column ()); -} - -void -tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.control_expr (); - - octave_value rhs = expr->evaluate (*this); - - if (rhs.is_undefined ()) - return; - - if (! rhs.isstruct ()) - error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); - - // Cycle through structure elements. First element of id_list - // is set to value and the second is set to the name of the - // structure element. - - tree_argument_list *lhs = cmd.left_hand_side (); - - auto p = lhs->begin (); - - tree_expression *elt = *p++; - - octave_lvalue val_ref = elt->lvalue (*this); - - elt = *p; - - octave_lvalue key_ref = elt->lvalue (*this); - - const octave_map tmp_val = rhs.map_value (); - - tree_statement_list *loop_body = cmd.body (); - - string_vector keys = tmp_val.keys (); - - octave_idx_type nel = keys.numel (); - - for (octave_idx_type i = 0; i < nel; i++) - { - if (m_echo_state) - m_echo_file_pos = line; - - std::string key = keys[i]; - - const Cell val_lst = tmp_val.contents (key); - - octave_idx_type n = val_lst.numel (); - - octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); - - val_ref.assign (octave_value::op_asn_eq, val); - key_ref.assign (octave_value::op_asn_eq, key); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } -} - -void tree_evaluator::visit_spmd_command (tree_spmd_command& cmd) -{ - // For now, we just execute the commands serially. - - tree_statement_list *body = cmd.body (); - - if (body) - body->accept (*this); -} - -octave_value -tree_evaluator::evaluate_anon_fcn_handle (tree_anon_fcn_handle& afh) -{ - // FIXME: should CMD_LIST be limited to a single expression? - // I think that is what Matlab does. - - symbol_scope new_scope; - symbol_scope scope = afh.scope (); - if (scope) - new_scope = scope.dup (); - - tree_parameter_list *param_list = afh.parameter_list (); - tree_parameter_list *param_list_dup - = param_list ? param_list->dup (new_scope) : nullptr; - - tree_parameter_list *ret_list = nullptr; - - tree_statement_list *stmt_list = nullptr; - - symbol_scope parent_scope = get_current_scope (); - - new_scope.set_parent (parent_scope); - new_scope.set_primary_parent (parent_scope); - - tree_expression *expr = afh.expression (); - if (expr) - { - tree_expression *expr_dup = expr->dup (new_scope); - tree_statement *stmt = new tree_statement (expr_dup, nullptr); - stmt_list = new tree_statement_list (stmt); - } - - tree_anon_scopes anon_fcn_ctx (afh); - - std::set free_vars = anon_fcn_ctx.free_variables (); - - stack_frame::local_vars_map local_vars; - - std::shared_ptr frame - = m_call_stack.get_current_stack_frame (); - - for (auto& name : free_vars) - { - octave_value val = frame->varval (name); - - if (val.is_defined ()) - local_vars[name] = val; - } - - octave_user_function *af - = new octave_user_function (new_scope, param_list_dup, ret_list, - stmt_list); - - octave_function *curr_fcn = m_call_stack.current_function (); - - bool is_nested = false; - - if (curr_fcn) - { - // FIXME: maybe it would be better to just stash curr_fcn - // instead of individual bits of info about it? - - // An anonymous function defined inside another nested function - // or parent of a nested function also behaves like a nested - // function. - - if (curr_fcn->is_parent_function () || curr_fcn->is_nested_function ()) - { - is_nested = true; - af->mark_as_nested_function (); - new_scope.set_nesting_depth (parent_scope.nesting_depth () + 1); - } - - af->stash_dir_name (curr_fcn->dir_name ()); - - new_scope.cache_fcn_file_name (curr_fcn->fcn_file_name ()); - new_scope.cache_dir_name (curr_fcn->dir_name ()); - - // The following is needed so that class method dispatch works - // properly for anonymous functions that wrap class methods. - - if (curr_fcn->is_class_method () || curr_fcn->is_class_constructor ()) - af->stash_dispatch_class (curr_fcn->dispatch_class ()); - - af->stash_fcn_file_name (curr_fcn->fcn_file_name ()); - } - - af->mark_as_anonymous_function (); - - octave_value ov_fcn (af); - - return (is_nested - ? octave_value (new octave_fcn_handle (ov_fcn, local_vars, frame)) - : octave_value (new octave_fcn_handle (ov_fcn, local_vars))); -} - -octave_value_list -tree_evaluator::execute_builtin_function (octave_builtin& builtin_function, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - if (args.has_magic_colon ()) - error ("invalid use of colon in function argument list"); - - profiler::enter block (m_profiler, builtin_function); - - octave_builtin::fcn fcn = builtin_function.function (); - - if (fcn) - retval = (*fcn) (args, nargout); - else - { - octave_builtin::meth meth = builtin_function.method (); - - retval = (*meth) (m_interpreter, args, nargout); - } - - // Do not allow null values to be returned from functions. - // FIXME: perhaps true builtins should be allowed? - - retval.make_storable_values (); - - // Fix the case of a single undefined value. - // This happens when a compiled function uses - // - // octave_value retval; - // - // instead of - // - // octave_value_list retval; - // - // the idiom is very common, so we solve that here. - - if (retval.length () == 1 && retval.xelem (0).is_undefined ()) - retval.clear (); - - return retval; -} - -octave_value_list -tree_evaluator::execute_mex_function (octave_mex_function& mex_function, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - if (args.has_magic_colon ()) - error ("invalid use of colon in function argument list"); - - profiler::enter block (m_profiler, mex_function); - - retval = call_mex (mex_function, args, nargout); - - return retval; -} - -octave_value_list -tree_evaluator::execute_user_script (octave_user_script& user_script, - int nargout, - const octave_value_list& args) -{ - octave_value_list retval; - - std::string file_name = user_script.fcn_file_name (); - - if (args.length () != 0 || nargout != 0) - error ("invalid call to script %s", file_name.c_str ()); - - tree_statement_list *cmd_list = user_script.body (); - - if (! cmd_list) - return retval; - - // FIXME: Maybe this check belongs in the places where we push a new - // stack frame? Or in the call_stack push method itself? - - if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) - error ("max_recursion_depth exceeded"); - - unwind_protect_var upv (m_statement_context, SC_SCRIPT); - - profiler::enter block (m_profiler, user_script); - - if (echo ()) - push_echo_state (tree_evaluator::ECHO_SCRIPTS, file_name); - - // FIXME: Should we be using tree_evaluator::eval here? - - cmd_list->accept (*this); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - - return retval; -} - -void -tree_evaluator::visit_octave_user_script (octave_user_script&) -{ - // ?? - panic_impossible (); -} - -octave_value_list -tree_evaluator::execute_user_function (octave_user_function& user_function, - int nargout, - const octave_value_list& xargs) -{ - octave_value_list retval; - - // If this function is a classdef constructor, extract the first input - // argument, which must be the partially constructed object instance. - - octave_value_list args (xargs); - octave_value_list ret_args; - - int nargin = args.length (); - - if (user_function.is_classdef_constructor ()) - { - if (nargin > 0) - { - ret_args = args.slice (0, 1, true); - --nargin; - args = args.slice (1, nargin, true); - } - else - panic_impossible (); - } - - // FIXME: this probably shouldn't be a double-precision matrix. - Matrix ignored_outputs = ignored_fcn_outputs (); - - tree_parameter_list *param_list = user_function.parameter_list (); - - bool takes_varargs = false; - int max_inputs = 0; - - if (param_list) - { - takes_varargs = param_list->takes_varargs (); - max_inputs = param_list->length (); - } - - if (! takes_varargs && nargin > max_inputs) - { - std::string name = user_function.name (); - - if (name.empty ()) - name = "@"; - - error_with_id ("Octave:invalid-fun-call", - "%s: function called with too many inputs", - name.c_str ()); - } - - define_parameter_list_from_arg_vector (param_list, args); - - tree_parameter_list *ret_list = user_function.return_list (); - - if (ret_list && ! ret_list->takes_varargs ()) - { - int max_outputs = ret_list->length (); - - if (nargout > max_outputs) - { - std::string name = user_function.name (); - - error_with_id ("Octave:invalid-fun-call", - "%s: function called with too many outputs", - name.c_str ()); - } - } - - bind_auto_fcn_vars (xargs.name_tags (), ignored_outputs, nargin, - nargout, user_function.takes_varargs (), - user_function.all_va_args (args)); - - // For classdef constructor, pre-populate the output arguments - // with the pre-initialized object instance, extracted above. - - if (user_function.is_classdef_constructor ()) - { - if (! ret_list) - error ("%s: invalid classdef constructor, no output argument defined", - user_function.dispatch_class ().c_str ()); - - define_parameter_list_from_arg_vector (ret_list, ret_args); - } - - // FIXME: Maybe this check belongs in the places where we push a - // new stack frame? Or in the call_stack push method itself? - - if (m_call_stack.size () >= static_cast (m_max_recursion_depth)) - error ("max_recursion_depth exceeded"); - - unwind_action act2 ([&user_function] () - { - user_function.restore_warning_states (); - }); - - // Evaluate the commands that make up the function. - - unwind_protect_var upv (m_statement_context, SC_FUNCTION); - - tree_statement_list *cmd_list = user_function.body (); - - if (cmd_list) - { - profiler::enter - block (m_profiler, user_function); - - if (echo ()) - push_echo_state (tree_evaluator::ECHO_FUNCTIONS, - user_function.fcn_file_name ()); - - if (user_function.is_special_expr ()) - { - panic_if (cmd_list->length () != 1); - - tree_statement *stmt = cmd_list->front (); - - tree_expression *expr = stmt->expression (); - - if (expr) - { - m_call_stack.set_location (stmt->line (), stmt->column ()); - - retval = expr->evaluate_n (*this, nargout); - } - } - else - cmd_list->accept (*this); - - if (m_returning) - m_returning = 0; - - if (m_breaking) - m_breaking--; - } - - // Copy return values out. - - if (ret_list && ! user_function.is_special_expr ()) - { - Cell varargout; - - if (ret_list->takes_varargs ()) - { - octave_value varargout_varval = varval ("varargout"); - - if (varargout_varval.is_defined ()) - varargout = varargout_varval.xcell_value ("varargout must be a cell array object"); - } - - retval = convert_return_list_to_const_vector (ret_list, nargout, - ignored_outputs, - varargout); - } - - return retval; -} - -void -tree_evaluator::visit_octave_user_function (octave_user_function&) -{ - // ?? - panic_impossible (); -} - -void -tree_evaluator::visit_octave_user_function_header (octave_user_function&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_function_def (tree_function_def& cmd) -{ - octave_value fcn = cmd.function (); - - octave_function *f = fcn.function_value (); - - if (f) - { - std::string nm = f->name (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.install_cmdline_function (nm, fcn); - - // Make sure that any variable with the same name as the new - // function is cleared. - - assign (nm); - } -} - -void -tree_evaluator::visit_identifier (tree_identifier&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_if_clause (tree_if_clause&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_if_command (tree_if_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - // FIXME: tree_if_command_list is not derived from tree, so should it - // really have an accept method? - - tree_if_command_list *lst = cmd.cmd_list (); - - if (lst) - lst->accept (*this); -} - -void -tree_evaluator::visit_if_command_list (tree_if_command_list& lst) -{ - for (tree_if_clause *tic : lst) - { - tree_expression *expr = tic->condition (); - - if (! (in_debug_repl () - && m_call_stack.current_frame () == m_debug_frame)) - m_call_stack.set_location (tic->line (), tic->column ()); - - if (m_debug_mode && ! tic->is_else_clause ()) - do_breakpoint (tic->is_active_breakpoint (*this)); - - if (tic->is_else_clause () || is_logically_true (expr, "if")) - { - tree_statement_list *stmt_lst = tic->commands (); - - if (stmt_lst) - stmt_lst->accept (*this); - - break; - } - } -} - -void -tree_evaluator::visit_index_expression (tree_index_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_matrix (tree_matrix&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_cell (tree_cell&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_multi_assignment (tree_multi_assignment&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode && cmd.is_end_of_fcn_or_script ()) - do_breakpoint (cmd.is_active_breakpoint (*this), true); -} - -void -tree_evaluator::visit_constant (tree_constant&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_fcn_handle (tree_fcn_handle&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_parameter_list (tree_parameter_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_postfix_expression (tree_postfix_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_prefix_expression (tree_prefix_expression&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_return_command (tree_return_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - // Act like dbcont. - - if (in_debug_repl () && m_call_stack.current_frame () == m_debug_frame) - dbcont (); - else if (m_statement_context == SC_FUNCTION - || m_statement_context == SC_SCRIPT - || m_in_loop_command) - m_returning = 1; -} - -void -tree_evaluator::visit_simple_assignment (tree_simple_assignment&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_statement (tree_statement& stmt) -{ - tree_command *cmd = stmt.command (); - tree_expression *expr = stmt.expression (); - - if (cmd || expr) - { - if (! (in_debug_repl () - && m_call_stack.current_frame () == m_debug_frame)) - m_call_stack.set_location (stmt.line (), stmt.column ()); - - try - { - if (cmd) - { - unwind_protect_var *> - upv (m_lvalue_list, nullptr); - - cmd->accept (*this); - } - else - { - if (m_echo_state) - { - int line = stmt.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (expr->is_active_breakpoint (*this)); - - // FIXME: maybe all of this should be packaged in - // one virtual function that returns a flag saying whether - // or not the expression will take care of binding ans and - // printing the result. - - // FIXME: it seems that we should just have to - // evaluate the expression and that should take care of - // everything, binding ans as necessary? - - octave_value tmp_result = expr->evaluate (*this, 0); - - if (tmp_result.is_defined ()) - { - bool do_bind_ans = false; - - if (expr->is_identifier ()) - do_bind_ans = ! is_variable (expr); - else - do_bind_ans = ! expr->is_assignment_expression (); - - if (do_bind_ans) - bind_ans (tmp_result, expr->print_result () - && statement_printing_enabled ()); - } - } - } - catch (const std::bad_alloc&) - { - // FIXME: We want to use error_with_id here so that give users - // control over this error message but error_with_id will - // require some memory allocations. Is there anything we can - // do to make those more likely to succeed? - - error_with_id ("Octave:bad-alloc", - "out of memory or dimension too large for Octave's index type"); - } - catch (const interrupt_exception&) - { - // If we are debugging, then continue with next statement. - // Otherwise, jump out of here. - - if (m_debug_mode) - m_interpreter.recover_from_exception (); - else - throw; - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - if ((m_interpreter.interactive () - || application::forced_interactive ()) - && ((es.debug_on_error () - && m_bp_table.debug_on_err (es.last_error_id ())) - || (es.debug_on_caught () - && m_bp_table.debug_on_caught (es.last_error_id ()))) - && in_user_code ()) - { - es.save_exception (ee); - es.display_exception (ee); - - enter_debugger (); - - // It doesn't make sense to continue execution after an - // error occurs so force the debugger to quit all debug - // levels and return the the top prompt. - - throw quit_debug_exception (true); - } - else - throw; - } - } -} - -void -tree_evaluator::visit_statement_list (tree_statement_list& lst) -{ - // FIXME: commented out along with else clause below. - // static octave_value_list empty_list; - - auto p = lst.begin (); - - if (p != lst.end ()) - { - while (true) - { - tree_statement *elt = *p++; - - if (! elt) - error ("invalid statement found in statement list!"); - - octave_quit (); - - elt->accept (*this); - - if (m_breaking || m_continuing) - break; - - if (m_returning) - break; - - if (p == lst.end ()) - break; - else - { - // Clear previous values before next statement is - // evaluated so that we aren't holding an extra - // reference to a value that may be used next. For - // example, in code like this: - // - // X = rand (N); # refcount for X should be 1 - // # after this statement - // - // X(idx) = val; # no extra copy of X should be - // # needed, but we will be faked - // # out if retval is not cleared - // # between statements here - - // result_values = empty_list; - } + print_usage (); } - } -} - -void -tree_evaluator::visit_switch_case (tree_switch_case&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_switch_case_list (tree_switch_case_list&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_switch_command (tree_switch_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - tree_expression *expr = cmd.switch_value (); - - if (! expr) - error ("missing value in switch command near line %d, column %d", - cmd.line (), cmd.column ()); - - octave_value val = expr->evaluate (*this); - - tree_switch_case_list *lst = cmd.case_list (); - - if (lst) - { - for (tree_switch_case *t : *lst) - { - if (t->is_default_case () || switch_case_label_matches (t, val)) - { - tree_statement_list *stmt_lst = t->commands (); - - if (stmt_lst) - stmt_lst->accept (*this); - - break; - } - } - } -} - -void -tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - bool execution_error = false; - octave_scalar_map err_map; - - tree_statement_list *try_code = cmd.body (); - - if (try_code) - { - // unwind frame before catch block - - unwind_protect frame; - - interpreter_try (frame); - - // The catch code is *not* added to unwind_protect stack; it - // doesn't need to be run on interrupts. - - try - { - try_code->accept (*this); - } - catch (const execution_exception& ee) - { - execution_error = true; - - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - - err_map.assign ("message", es.last_error_message ()); - err_map.assign ("identifier", es.last_error_id ()); - err_map.assign ("stack", es.last_error_stack ()); - - m_interpreter.recover_from_exception (); - } - - // Actions attached to unwind_protect frame will run here, prior - // to executing the catch block. - } - - if (execution_error) - { - tree_statement_list *catch_code = cmd.cleanup (); - - if (catch_code) - { - tree_identifier *expr_id = cmd.identifier (); - - if (expr_id) - { - octave_lvalue ult = expr_id->lvalue (*this); - - ult.assign (octave_value::op_asn_eq, err_map); - } - - // perform actual "catch" block - catch_code->accept (*this); - } - } -} - -void -tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) -{ - unwind_protect frame; - - frame.protect_var (octave_interrupt_state); - octave_interrupt_state = 0; - - // We want to preserve the last location info for possible - // backtracking. - - frame.add (&call_stack::set_line, &m_call_stack, - m_call_stack.current_line ()); - - frame.add (&call_stack::set_column, &m_call_stack, - m_call_stack.current_column ()); - - // Similarly, if we have seen a return or break statement, allow all - // the cleanup code to run before returning or handling the break. - // We don't have to worry about continue statements because they can - // only occur in loops. - - frame.protect_var (m_returning); - m_returning = 0; - - frame.protect_var (m_breaking); - m_breaking = 0; - - try - { - if (list) - list->accept (*this); - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - if (m_breaking || m_returning) - frame.discard (2); - else - frame.run (2); - - frame.discard (2); - - throw; - } - - // The unwind_protects are popped off the stack in the reverse of - // the order they are pushed on. - - // FIXME: these statements say that if we see a break or - // return statement in the cleanup block, that we want to use the - // new value of the breaking or returning flag instead of restoring - // the previous value. Is that the right thing to do? I think so. - // Consider the case of - // - // function foo () - // unwind_protect - // fprintf (stderr, "1: this should always be executed\n"); - // break; - // fprintf (stderr, "1: this should never be executed\n"); - // unwind_protect_cleanup - // fprintf (stderr, "2: this should always be executed\n"); - // return; - // fprintf (stderr, "2: this should never be executed\n"); - // end_unwind_protect - // endfunction - // - // If we reset the value of the breaking flag, both the returning - // flag and the breaking flag will be set, and we shouldn't have - // both. So, use the most recent one. If there is no return or - // break in the cleanup block, the values should be reset to - // whatever they were when the cleanup block was entered. - - if (m_breaking || m_returning) - frame.discard (2); - else - frame.run (2); -} - -void -tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) -{ - if (m_echo_state) - { - int line = cmd.line (); - if (line < 0) - line = 1; - echo_code (line); - m_echo_file_pos = line + 1; - } - - tree_statement_list *cleanup_code = cmd.cleanup (); - - tree_statement_list *unwind_protect_code = cmd.body (); - - if (unwind_protect_code) - { - try - { - unwind_protect_code->accept (*this); - } - catch (const execution_exception& ee) - { - error_system& es = m_interpreter.get_error_system (); - - // FIXME: Maybe we should be able to temporarily set the - // interpreter's exception handling state to something "safe" - // while the cleanup block runs instead of just resetting it - // here? - es.save_exception (ee); - m_interpreter.recover_from_exception (); - - // Run the cleanup code on exceptions, so that it is run even - // in case of interrupt or out-of-memory. - do_unwind_protect_cleanup_code (cleanup_code); - - // If an error occurs inside the cleanup code, a new - // exception will be thrown instead of the original. - throw; - } - catch (const interrupt_exception&) - { - // The comments above apply here as well. - m_interpreter.recover_from_exception (); - do_unwind_protect_cleanup_code (cleanup_code); - throw; - } - - // Also execute the unwind_protect_cleanump code if the - // unwind_protect block runs without error. - do_unwind_protect_cleanup_code (cleanup_code); - } -} - -void -tree_evaluator::visit_while_command (tree_while_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.condition (); - - if (! expr) - panic_impossible (); - - for (;;) - { - if (m_echo_state) - m_echo_file_pos = line; - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (is_logically_true (expr, "while")) - { - tree_statement_list *loop_body = cmd.body (); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - } - else break; - } -} - -void -tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) -{ - int line = cmd.line (); - if (line < 0) - line = 1; - - if (m_echo_state) - { - echo_code (line); - line++; - } - - unwind_protect_var upv (m_in_loop_command, true); - - tree_expression *expr = cmd.condition (); - - if (! expr) - panic_impossible (); - - for (;;) - { - if (m_echo_state) - m_echo_file_pos = line; - - tree_statement_list *loop_body = cmd.body (); - - if (loop_body) - loop_body->accept (*this); - - if (quit_loop_now ()) - break; - - if (m_debug_mode) - do_breakpoint (cmd.is_active_breakpoint (*this)); - - if (is_logically_true (expr, "do-until")) + + default: + print_usage (); break; - } -} - -void -tree_evaluator::visit_superclass_ref (tree_superclass_ref&) -{ - panic_impossible (); -} - -void -tree_evaluator::visit_metaclass_query (tree_metaclass_query&) -{ - panic_impossible (); -} - -void tree_evaluator::bind_ans (const octave_value& val, bool print) -{ - static std::string ans = "ans"; - - if (val.is_defined ()) - { - if (val.is_cs_list ()) - { - octave_value_list lst = val.list_value (); - - for (octave_idx_type i = 0; i < lst.length (); i++) - bind_ans (lst(i), print); - } - else - { - // FIXME: Maybe assign could also return the assigned value, - // just for convenience? - - assign (ans, val); - - if (print) - { - // Use varval instead of displaying VAL directly so that - // we get the right type and value for things like - // magic_int values that may mutate when stored. - - octave_value_list args = ovl (varval (ans)); - args.stash_name_tags (string_vector (ans)); - feval ("display", args); - } - } - } -} - -void -tree_evaluator::do_breakpoint (tree_statement& stmt) -{ - do_breakpoint (stmt.is_active_breakpoint (*this), - stmt.is_end_of_fcn_or_script ()); -} - -void -tree_evaluator::do_breakpoint (bool is_breakpoint, - bool is_end_of_fcn_or_script) -{ - bool break_on_this_statement = false; - - if (is_breakpoint) - break_on_this_statement = true; - else if (m_dbstep_flag > 0) - { - if (m_call_stack.current_frame () == m_debug_frame) - { - if (m_dbstep_flag == 1 || is_end_of_fcn_or_script) - { - // We get here if we are doing a "dbstep" or a "dbstep N" and - // the count has reached 1 so that we must stop and return to - // debug prompt. Alternatively, "dbstep N" has been used but - // the end of the frame has been reached so we stop at the last - // line and return to prompt. - - break_on_this_statement = true; - } - else - { - // Executing "dbstep N". Decrease N by one and continue. - - m_dbstep_flag--; - } - - } - else if (m_dbstep_flag == 1 - && m_call_stack.current_frame () < m_debug_frame) - { - // We stepped out from the end of a function. - - m_debug_frame = m_call_stack.current_frame (); - - break_on_this_statement = true; - } - } - else if (m_dbstep_flag == -1) - { - // We get here if we are doing a "dbstep in". - - break_on_this_statement = true; - - m_debug_frame = m_call_stack.current_frame (); - } - else if (m_dbstep_flag == -2) - { - // We get here if we are doing a "dbstep out". Check for end of - // function and whether the current frame is the same as the - // cached value because we want to step out from the frame where - // "dbstep out" was evaluated, not from any functions called from - // that frame. - - if (is_end_of_fcn_or_script - && m_call_stack.current_frame () == m_debug_frame) - m_dbstep_flag = -1; - } - - if (! break_on_this_statement) - break_on_this_statement = m_break_on_next_stmt; - - m_break_on_next_stmt = false; - - if (break_on_this_statement) - { - m_dbstep_flag = 0; - - enter_debugger (); - } -} - -bool -tree_evaluator::is_logically_true (tree_expression *expr, - const char *warn_for) -{ - bool expr_value = false; - - m_call_stack.set_location (expr->line (), expr->column ()); - - octave_value t1 = expr->evaluate (*this); - - if (t1.is_defined ()) - return t1.is_true (); - else - error ("%s: undefined value used in conditional expression", warn_for); - - return expr_value; -} - -octave_value -tree_evaluator::max_recursion_depth (const octave_value_list& args, - int nargout) -{ - return set_internal_variable (m_max_recursion_depth, args, nargout, - "max_recursion_depth", 0); -} - -symbol_info_list -tree_evaluator::glob_symbol_info (const std::string& pattern) const -{ - return m_call_stack.glob_symbol_info (pattern); -} - -symbol_info_list -tree_evaluator::regexp_symbol_info (const std::string& pattern) const -{ - return m_call_stack.regexp_symbol_info (pattern); -} - -symbol_info_list -tree_evaluator::get_symbol_info (void) -{ - return m_call_stack.get_symbol_info (); -} - -symbol_info_list -tree_evaluator::top_scope_symbol_info (void) const -{ - return m_call_stack.top_scope_symbol_info (); -} - -octave_map tree_evaluator::get_autoload_map (void) const -{ - Cell fcn_names (dim_vector (m_autoload_map.size (), 1)); - Cell file_names (dim_vector (m_autoload_map.size (), 1)); - - octave_idx_type i = 0; - for (const auto& fcn_fname : m_autoload_map) - { - fcn_names(i) = fcn_fname.first; - file_names(i) = fcn_fname.second; - - i++; - } - - octave_map m; - - m.assign ("function", fcn_names); - m.assign ("file", file_names); - - return m; -} - -std::string tree_evaluator::lookup_autoload (const std::string& nm) const -{ - std::string retval; - - auto p = m_autoload_map.find (nm); - - if (p != m_autoload_map.end ()) - { - load_path& lp = m_interpreter.get_load_path (); - - retval = lp.find_file (p->second); - } - - return retval; -} - -std::list tree_evaluator::autoloaded_functions (void) const -{ - std::list names; - - for (const auto& fcn_fname : m_autoload_map) - names.push_back (fcn_fname.first); - - return names; -} - -std::list -tree_evaluator::reverse_lookup_autoload (const std::string& nm) const -{ - std::list names; - - for (const auto& fcn_fname : m_autoload_map) - if (nm == fcn_fname.second) - names.push_back (fcn_fname.first); - - return names; -} - -void tree_evaluator::add_autoload (const std::string& fcn, - const std::string& nm) -{ - std::string file_name = check_autoload_file (nm); - - m_autoload_map[fcn] = file_name; -} - -void tree_evaluator::remove_autoload (const std::string& fcn, - const std::string& nm) -{ - check_autoload_file (nm); - - // Remove function from symbol table and autoload map. - symbol_table& symtab = m_interpreter.get_symbol_table (); - - symtab.clear_dld_function (fcn); - - m_autoload_map.erase (fcn); -} - -octave_value -tree_evaluator::whos_line_format (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_whos_line_format, args, nargout, - "whos_line_format"); -} - -octave_value -tree_evaluator::silent_functions (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_silent_functions, args, nargout, - "silent_functions"); -} - -octave_value -tree_evaluator::string_fill_char (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_string_fill_char, args, nargout, - "string_fill_char"); -} - -// Final step of processing an indexing error. Add the name of the -// variable being indexed, if any, then issue an error. (Will this also -// be needed by pt-lvalue, which calls subsref?) - -void tree_evaluator::final_index_error (index_exception& ie, - const tree_expression *expr) -{ - std::string extra_message; - - if (is_variable (expr)) - { - std::string var = expr->name (); - - ie.set_var (var); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value fcn = symtab.find_function (var); - - if (fcn.is_function ()) - { - octave_function *fp = fcn.function_value (); - - if (fp && fp->name () == var) - extra_message - = " (note: variable '" + var + "' shadows function)"; - } - } - - std::string msg = ie.message () + extra_message; - - error_with_id (ie.err_id (), "%s", msg.c_str ()); -} - -octave_value -tree_evaluator::do_who (int argc, const string_vector& argv, - bool return_list, bool verbose) -{ - return m_call_stack.do_who (argc, argv, return_list, verbose); -} - -octave_value_list -tree_evaluator::make_value_list (tree_argument_list *args, - const string_vector& arg_nm) -{ - octave_value_list retval; - - if (args) - { - unwind_protect_var *> - upv (m_lvalue_list, nullptr); - - int len = args->length (); - - unwind_protect_var upv2 (m_index_position); - unwind_protect_var upv3 (m_num_indices); - - m_num_indices = len; - - std::list arg_vals; - - int k = 0; - - for (auto elt : *args) - { - // FIXME: is it possible for elt to be invalid? - - if (! elt) - break; - - m_index_position = k++; - - octave_value tmp = elt->evaluate (*this); - - if (tmp.is_cs_list ()) - { - octave_value_list tmp_ovl = tmp.list_value (); - - for (octave_idx_type i = 0; i < tmp_ovl.length (); i++) - arg_vals.push_back (tmp_ovl(i)); - } - else if (tmp.is_defined ()) - arg_vals.push_back (tmp); - } - - retval = octave_value_list (arg_vals); - } - - octave_idx_type n = retval.length (); - - if (n > 0) - retval.stash_name_tags (arg_nm); - - return retval; -} - -std::list -tree_evaluator::make_lvalue_list (tree_argument_list *lhs) -{ - std::list retval; - - for (tree_expression *elt : *lhs) - retval.push_back (elt->lvalue (*this)); - - return retval; -} - -void -tree_evaluator::push_echo_state (int type, const std::string& file_name, - int pos) -{ - unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); - - if (frame) - { - push_echo_state_cleanup (*frame); - - set_echo_state (type, file_name, pos); - } -} - -void -tree_evaluator::set_echo_state (int type, const std::string& file_name, - int pos) -{ - m_echo_state = echo_this_file (file_name, type); - m_echo_file_name = file_name; - m_echo_file_pos = pos; -} - -void -tree_evaluator::uwp_set_echo_state (bool state, const std::string& file_name, - int pos) -{ - m_echo_state = state; - m_echo_file_name = file_name; - m_echo_file_pos = pos; -} - -void -tree_evaluator::maybe_set_echo_state (void) -{ - octave_function *caller = caller_function (); - - if (caller && caller->is_user_code ()) - { - octave_user_code *fcn = dynamic_cast (caller); - - int type = fcn->is_user_function () ? ECHO_FUNCTIONS : ECHO_SCRIPTS; - - std::string file_name = fcn->fcn_file_name (); - - // We want the line where "echo" was called, not the line number - // stored in the stack frame that was created for the echo - // function (that will always be -1). - - int pos = m_call_stack.current_user_code_line (); - - if (pos < 0) - pos = 1; - - set_echo_state (type, file_name, pos); - } -} - -void -tree_evaluator::push_echo_state_cleanup (unwind_protect& frame) -{ - frame.add (&tree_evaluator::uwp_set_echo_state, this, - m_echo_state, m_echo_file_name, m_echo_file_pos); -} - -bool tree_evaluator::maybe_push_echo_state_cleanup (void) -{ - // This function is expected to be called from ECHO, which would be - // the top of the call stack. If the caller of ECHO is a - // user-defined function or script, then set up unwind-protect - // elements to restore echo state. - - unwind_protect *frame = m_call_stack.curr_fcn_unwind_protect_frame (); - - if (frame) - { - push_echo_state_cleanup (*frame); - return true; - } - - return false; -} - - -octave_value -tree_evaluator::echo (const octave_value_list& args, int) -{ - bool cleanup_pushed = maybe_push_echo_state_cleanup (); - - string_vector argv = args.make_argv (); - - switch (args.length ()) - { - case 0: - if ((m_echo & ECHO_SCRIPTS) || (m_echo & ECHO_FUNCTIONS)) - { - m_echo = ECHO_OFF; - m_echo_files.clear (); - } - else - m_echo = ECHO_SCRIPTS; - break; - - case 1: + } + + if (cleanup_pushed) + maybe_set_echo_state (); + + return octave_value (); + } + + bool tree_evaluator::in_debug_repl (void) const + { + return (m_debugger_stack.empty () + ? false : m_debugger_stack.top()->in_debug_repl ()); + } + + void tree_evaluator::dbcont (void) + { + if (! m_debugger_stack.empty ()) + m_debugger_stack.top()->dbcont (); + } + + void tree_evaluator::dbquit (bool all) + { + if (! m_debugger_stack.empty ()) + m_debugger_stack.top()->dbquit (all); + } + + static octave_value end_value (const octave_value& value, + octave_idx_type index_position, + octave_idx_type num_indices) + { + dim_vector dv = value.dims (); + int ndims = dv.ndims (); + + if (num_indices < ndims) { - std::string arg0 = argv[0]; - - if (arg0 == "on") - m_echo = ECHO_SCRIPTS; - else if (arg0 == "off") - m_echo = ECHO_OFF; + for (int i = num_indices; i < ndims; i++) + dv(num_indices-1) *= dv(i); + + if (num_indices == 1) + { + ndims = 2; + dv.resize (ndims); + dv(1) = 1; + } else { - std::string file = fcn_file_in_path (arg0); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg0.c_str ()); - - if (m_echo & ECHO_ALL) - { - // Echo is enabled for all functions, so turn it off - // for this one. - - m_echo_files[file] = false; - } - else + ndims = num_indices; + dv.resize (ndims); + } + } + + return (index_position < ndims + ? octave_value (dv(index_position)) : octave_value (1.0)); + } + + octave_value_list + tree_evaluator::evaluate_end_expression (const octave_value_list& args) + { + int nargin = args.length (); + + if (nargin != 0 && nargin != 3) + print_usage (); + + if (nargin == 3) + { + octave_idx_type index_position + = args(1).xidx_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"); + + if (num_indices < 1) + error ("end: N must be greater than zero"); + + return end_value (args(0), index_position-1, num_indices); + } + + // If m_indexed_object is undefined, then this use of 'end' is + // either appearing in a function call argument list or in an + // attempt to index an undefined symbol. There seems to be no + // reasonable way to provide a better error message. So just fail + // with an invalid use message. See bug #58830. + + if (m_indexed_object.is_undefined ()) + error ("invalid use of 'end': may only be used to index existing value"); + + octave_value expr_result; + + if (m_index_list.empty ()) + expr_result = m_indexed_object; + else + { + try + { + // When evaluating "end" with no arguments, we should have + // been called from the built-in Fend function that appears + // in the context of an argument list. Fend will be + // evaluated in its own stack frame. But we need to + // evaluate the partial expression that the special "end" + // token applies to in the calling stack frame. + + unwind_action act ([=] (std::size_t frm) + { + m_call_stack.restore_frame (frm); + }, m_call_stack.current_frame ()); + + std::size_t n = m_call_stack.find_current_user_frame (); + m_call_stack.goto_frame (n); + + // End is only valid inside argument lists used for + // indexing. The dispatch class is set by the function that + // evaluates the argument list. + + // Silently ignore extra output values. + + octave_value_list tmp + = m_indexed_object.subsref (m_index_type, m_index_list, 1); + + expr_result = tmp.length () ? tmp(0) : octave_value (); + + if (expr_result.is_cs_list ()) + err_indexed_cs_list (); + } + catch (const index_exception&) + { + error ("error evaluating partial expression for END"); + } + } + + if (expr_result.isobject ()) + { + // FIXME: is there a better way to lookup and execute a method + // that handles all the details like setting the dispatch class + // appropriately? + + std::string dispatch_class = expr_result.class_name (); + + symbol_table& symtab = m_interpreter.get_symbol_table (); + + octave_value meth = symtab.find_method ("end", dispatch_class); + + if (meth.is_defined ()) + return m_interpreter.feval + (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1); + } + + return end_value (expr_result, m_index_position, m_num_indices); + } + + octave_value + tree_evaluator::PS4 (const octave_value_list& args, int nargout) + { + return set_internal_variable (m_PS4, args, nargout, "PS4"); + } + + bool tree_evaluator::echo_this_file (const std::string& file, int type) const + { + if ((type & m_echo) == ECHO_SCRIPTS) + { + // Asking about scripts and echo is enabled for them. + return true; + } + + if ((type & m_echo) == ECHO_FUNCTIONS) + { + // Asking about functions and echo is enabled for functions. + // Now, which ones? + + auto p = m_echo_files.find (file); + + if (m_echo & ECHO_ALL) + { + // Return true ulness echo was turned off for a specific + // file. + + return (p == m_echo_files.end () || p->second); + } + else + { + // Return true if echo is specifically enabled for this file. + + return p != m_echo_files.end () && p->second; + } + } + + return false; + } + + void tree_evaluator::echo_code (int line) + { + std::string prefix = command_editor::decode_prompt_string (m_PS4); + + octave_function *curr_fcn = m_call_stack.current_function (); + + if (curr_fcn && curr_fcn->is_user_code ()) + { + octave_user_code *code = dynamic_cast (curr_fcn); + + int num_lines = line - m_echo_file_pos + 1; + + std::deque lines + = code->get_code_lines (m_echo_file_pos, num_lines); + + for (auto& elt : lines) + octave_stdout << prefix << elt << std::endl; + } + } + + // Decide if it's time to quit a for or while loop. + bool tree_evaluator::quit_loop_now (void) + { + octave_quit (); + + // Maybe handle 'continue N' someday... + + if (m_continuing) + m_continuing--; + + bool quit = (m_returning || m_breaking || m_continuing); + + if (m_breaking) + m_breaking--; + + return quit; + } + + void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names, + const Matrix& ignored_outputs, + int nargin, int nargout, + bool takes_varargs, + const octave_value_list& va_args) + { + set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names)); + set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs); + set_auto_fcn_var (stack_frame::NARGIN, nargin); + set_auto_fcn_var (stack_frame::NARGOUT, nargout); + set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ()); + + if (takes_varargs) + assign ("varargin", va_args.cell_value ()); + } + + std::string + tree_evaluator::check_autoload_file (const std::string& nm) const + { + if (sys::env::absolute_pathname (nm)) + return nm; + + std::string full_name = nm; + + octave_user_code *fcn = m_call_stack.current_user_code (); + + bool found = false; + + if (fcn) + { + std::string fname = fcn->fcn_file_name (); + + if (! fname.empty ()) + { + fname = sys::env::make_absolute (fname); + fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1); + + sys::file_stat fs (fname + nm); + + if (fs.exists ()) { - // Echo may be enabled for specific functions. - - auto p = m_echo_files.find (file); - - if (p == m_echo_files.end ()) - { - // Not this one, so enable it. - - m_echo |= ECHO_FUNCTIONS; - m_echo_files[file] = true; - } - else - { - // This one is already in the list. Flip the - // status for it. - - p->second = ! p->second; - } + full_name = fname + nm; + found = true; } } } - break; - - case 2: - { - std::string arg0 = argv[0]; - std::string arg1 = argv[1]; - - if (arg1 == "on" || arg1 == "off") - std::swap (arg0, arg1); - - if (arg0 == "on") - { - if (arg1 == "all") - { - m_echo = (ECHO_SCRIPTS | ECHO_FUNCTIONS | ECHO_ALL); - m_echo_files.clear (); - } - else - { - std::string file = fcn_file_in_path (arg1); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg1.c_str ()); - - m_echo |= ECHO_FUNCTIONS; - m_echo_files[file] = true; - } - } - else if (arg0 == "off") - { - if (arg1 == "all") - { - m_echo = ECHO_OFF; - m_echo_files.clear (); - } - else - { - std::string file = fcn_file_in_path (arg1); - file = sys::env::make_absolute (file); - - if (file.empty ()) - error ("echo: no such file %s", arg1.c_str ()); - - m_echo_files[file] = false; - } - } - else - print_usage (); - } - break; - - default: - print_usage (); - break; - } - - if (cleanup_pushed) - maybe_set_echo_state (); - - return octave_value (); -} - -bool tree_evaluator::in_debug_repl (void) const -{ - return (m_debugger_stack.empty () - ? false : m_debugger_stack.top()->in_debug_repl ()); -} - -void tree_evaluator::dbcont (void) -{ - if (! m_debugger_stack.empty ()) - m_debugger_stack.top()->dbcont (); -} - -void tree_evaluator::dbquit (bool all) -{ - if (! m_debugger_stack.empty ()) - m_debugger_stack.top()->dbquit (all); -} - -static octave_value end_value (const octave_value& value, - octave_idx_type index_position, - octave_idx_type num_indices) -{ - dim_vector dv = value.dims (); - int ndims = dv.ndims (); - - if (num_indices < ndims) - { - for (int i = num_indices; i < ndims; i++) - dv(num_indices-1) *= dv(i); - - if (num_indices == 1) - { - ndims = 2; - dv.resize (ndims); - dv(1) = 1; - } - else - { - ndims = num_indices; - dv.resize (ndims); - } - } - - return (index_position < ndims - ? octave_value (dv(index_position)) : octave_value (1.0)); -} - -octave_value_list -tree_evaluator::evaluate_end_expression (const octave_value_list& args) -{ - int nargin = args.length (); - - if (nargin != 0 && nargin != 3) - print_usage (); - - if (nargin == 3) - { - octave_idx_type index_position - = args(1).xidx_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"); - - if (num_indices < 1) - error ("end: N must be greater than zero"); - - return end_value (args(0), index_position-1, num_indices); - } - - // If m_indexed_object is undefined, then this use of 'end' is - // either appearing in a function call argument list or in an - // attempt to index an undefined symbol. There seems to be no - // reasonable way to provide a better error message. So just fail - // with an invalid use message. See bug #58830. - - if (m_indexed_object.is_undefined ()) - error ("invalid use of 'end': may only be used to index existing value"); - - octave_value expr_result; - - if (m_index_list.empty ()) - expr_result = m_indexed_object; - else - { - try - { - // When evaluating "end" with no arguments, we should have - // been called from the built-in Fend function that appears - // in the context of an argument list. Fend will be - // evaluated in its own stack frame. But we need to - // evaluate the partial expression that the special "end" - // token applies to in the calling stack frame. - - unwind_action act ([=] (std::size_t frm) - { - m_call_stack.restore_frame (frm); - }, m_call_stack.current_frame ()); - - std::size_t n = m_call_stack.find_current_user_frame (); - m_call_stack.goto_frame (n); - - // End is only valid inside argument lists used for - // indexing. The dispatch class is set by the function that - // evaluates the argument list. - - // Silently ignore extra output values. - - octave_value_list tmp - = m_indexed_object.subsref (m_index_type, m_index_list, 1); - - expr_result = tmp.length () ? tmp(0) : octave_value (); - - if (expr_result.is_cs_list ()) - err_indexed_cs_list (); - } - catch (const index_exception&) - { - error ("error evaluating partial expression for END"); - } - } - - if (expr_result.isobject ()) - { - // FIXME: is there a better way to lookup and execute a method - // that handles all the details like setting the dispatch class - // appropriately? - - std::string dispatch_class = expr_result.class_name (); - - symbol_table& symtab = m_interpreter.get_symbol_table (); - - octave_value meth = symtab.find_method ("end", dispatch_class); - - if (meth.is_defined ()) - return m_interpreter.feval - (meth, ovl (expr_result, m_index_position+1, m_num_indices), 1); - } - - return end_value (expr_result, m_index_position, m_num_indices); -} - -octave_value -tree_evaluator::PS4 (const octave_value_list& args, int nargout) -{ - return set_internal_variable (m_PS4, args, nargout, "PS4"); -} - -bool tree_evaluator::echo_this_file (const std::string& file, int type) const -{ - if ((type & m_echo) == ECHO_SCRIPTS) - { - // Asking about scripts and echo is enabled for them. - return true; - } - - if ((type & m_echo) == ECHO_FUNCTIONS) - { - // Asking about functions and echo is enabled for functions. - // Now, which ones? - - auto p = m_echo_files.find (file); - - if (m_echo & ECHO_ALL) - { - // Return true ulness echo was turned off for a specific - // file. - - return (p == m_echo_files.end () || p->second); - } - else - { - // Return true if echo is specifically enabled for this file. - - return p != m_echo_files.end () && p->second; - } - } - - return false; -} - -void tree_evaluator::echo_code (int line) -{ - std::string prefix = command_editor::decode_prompt_string (m_PS4); - - octave_function *curr_fcn = m_call_stack.current_function (); - - if (curr_fcn && curr_fcn->is_user_code ()) - { - octave_user_code *code = dynamic_cast (curr_fcn); - - int num_lines = line - m_echo_file_pos + 1; - - std::deque lines - = code->get_code_lines (m_echo_file_pos, num_lines); - - for (auto& elt : lines) - octave_stdout << prefix << elt << std::endl; - } -} - -// Decide if it's time to quit a for or while loop. -bool tree_evaluator::quit_loop_now (void) -{ - octave_quit (); - - // Maybe handle 'continue N' someday... - - if (m_continuing) - m_continuing--; - - bool quit = (m_returning || m_breaking || m_continuing); - - if (m_breaking) - m_breaking--; - - return quit; -} - -void tree_evaluator::bind_auto_fcn_vars (const string_vector& arg_names, - const Matrix& ignored_outputs, - int nargin, int nargout, - bool takes_varargs, - const octave_value_list& va_args) -{ - set_auto_fcn_var (stack_frame::ARG_NAMES, Cell (arg_names)); - set_auto_fcn_var (stack_frame::IGNORED, ignored_outputs); - set_auto_fcn_var (stack_frame::NARGIN, nargin); - set_auto_fcn_var (stack_frame::NARGOUT, nargout); - set_auto_fcn_var (stack_frame::SAVED_WARNING_STATES, octave_value ()); - - if (takes_varargs) - assign ("varargin", va_args.cell_value ()); -} - -std::string -tree_evaluator::check_autoload_file (const std::string& nm) const -{ - if (sys::env::absolute_pathname (nm)) - return nm; - - std::string full_name = nm; - - octave_user_code *fcn = m_call_stack.current_user_code (); - - bool found = false; - - if (fcn) - { - std::string fname = fcn->fcn_file_name (); - - if (! fname.empty ()) - { - fname = sys::env::make_absolute (fname); - fname = fname.substr (0, fname.find_last_of (sys::file_ops::dir_sep_str ()) + 1); - - sys::file_stat fs (fname + nm); - - if (fs.exists ()) - { - full_name = fname + nm; - found = true; - } - } - } - - if (! found) - warning_with_id ("Octave:autoload-relative-file-name", - "autoload: '%s' is not an absolute filename", - nm.c_str ()); - - return full_name; -} + + if (! found) + warning_with_id ("Octave:autoload-relative-file-name", + "autoload: '%s' is not an absolute filename", + nm.c_str ()); + + return full_name; + } DEFMETHOD (max_recursion_depth, interp, args, nargout, doc: /* -*- texinfo -*- diff -r 9089bd969b37 -r bd9da634f00d liboctave/array/Array.h --- a/liboctave/array/Array.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/array/Array.h Tue Dec 06 15:17:16 2022 -0500 @@ -663,12 +663,6 @@ OCTARRAY_OVERRIDABLE_FUNC_API const T * data (void) const { return m_slice_data; } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead") - OCTARRAY_OVERRIDABLE_FUNC_API const T * fortran_vec (void) const - { return data (); } -#endif - OCTARRAY_API T * fortran_vec (void); OCTARRAY_OVERRIDABLE_FUNC_API bool is_shared (void) diff -r 9089bd969b37 -r bd9da634f00d liboctave/array/DiagArray2.h --- a/liboctave/array/DiagArray2.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/array/DiagArray2.h Tue Dec 06 15:17:16 2022 -0500 @@ -168,11 +168,6 @@ const T * data (void) const { return Array::data (); } -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - OCTAVE_DEPRECATED (7, "for read-only access, use 'data' method instead") - const T * fortran_vec (void) const { return Array::data (); } -#endif - T * fortran_vec (void) { return Array::fortran_vec (); } void print_info (std::ostream& os, const std::string& prefix) const diff -r 9089bd969b37 -r bd9da634f00d liboctave/array/Range.cc --- a/liboctave/array/Range.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/array/Range.cc Tue Dec 06 15:17:16 2022 -0500 @@ -453,553 +453,3 @@ } OCTAVE_END_NAMESPACE(octave) - -bool -Range::all_elements_are_ints (void) const -{ - // If the base and increment are ints, the final value in the range will also - // be an integer, even if the limit is not. If there is one or fewer - // elements only the base needs to be an integer. - - return (! (octave::math::isnan (m_base) || octave::math::isnan (m_inc)) - && (octave::math::nint_big (m_base) == m_base || m_numel < 1) - && (octave::math::nint_big (m_inc) == m_inc || m_numel <= 1)); -} - -octave_idx_type -Range::nnz (void) const -{ - octave_idx_type retval = 0; - - if (! isempty ()) - { - if ((m_base > 0.0 && m_limit > 0.0) || (m_base < 0.0 && m_limit < 0.0)) - { - // All elements have the same sign, hence there are no zeros. - retval = m_numel; - } - else if (m_inc != 0.0) - { - if (m_base == 0.0 || m_limit == 0.0) - // Exactly one zero at beginning or end of range. - retval = m_numel - 1; - else if ((m_base / m_inc) != std::floor (m_base / m_inc)) - // Range crosses negative/positive without hitting zero. - retval = m_numel; - else - // Range crosses negative/positive and hits zero. - retval = m_numel - 1; - } - else - { - // All elements are equal (m_inc = 0) but not positive or negative, - // therefore all elements are zero. - retval = 0; - } - } - - return retval; -} - -Matrix -Range::matrix_value (void) const -{ - Matrix retval (1, m_numel); - - if (m_numel > 0) - { - // The first element must always be *exactly* the base. - // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). - retval(0) = m_base; - - double b = m_base; - double increment = m_inc; - for (octave_idx_type i = 1; i < m_numel - 1; i++) - retval.xelem (i) = b + i * increment; - - retval.xelem (m_numel - 1) = m_limit; - } - - return retval; -} - -double -Range::checkelem (octave_idx_type i) const -{ - if (i < 0 || i >= m_numel) - octave::err_index_out_of_range (2, 2, i+1, m_numel, dims ()); - - if (i == 0) - return m_base; - else if (i < m_numel - 1) - return m_base + i * m_inc; - else - return m_limit; -} - -double -Range::checkelem (octave_idx_type i, octave_idx_type j) const -{ - // Ranges are *always* row vectors. - if (i != 0) - octave::err_index_out_of_range (1, 1, i+1, m_numel, dims ()); - - return checkelem (j); -} - -double -Range::elem (octave_idx_type i) const -{ - if (i == 0) - return m_base; - else if (i < m_numel - 1) - return m_base + i * m_inc; - else - return m_limit; -} - -Array -Range::index (const octave::idx_vector& idx) const -{ - Array retval; - - octave_idx_type n = m_numel; - - if (idx.is_colon ()) - { - retval = matrix_value ().reshape (dim_vector (m_numel, 1)); - } - else - { - if (idx.extent (n) != n) - octave::err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); // throws - - dim_vector idx_dims = idx.orig_dimensions (); - octave_idx_type idx_len = idx.length (n); - - // taken from Array.cc. - if (n != 1 && idx_dims.isvector ()) - idx_dims = dim_vector (1, idx_len); - - retval.clear (idx_dims); - - // Loop over all values in IDX, executing the lambda expression - // for each index value. - - double *array = retval.fortran_vec (); - - idx.loop (n, [=, &array] (idx_vector i) - { - if (i == 0) - *array++ = m_base; - else if (i < m_numel - 1) - *array++ = m_base + i * m_inc; - else - *array++ = m_limit; - }); - } - - return retval; -} - -// NOTE: max and min only return useful values if numel > 0. -// do_minmax_body() in max.cc avoids calling Range::min/max if numel == 0. - -double -Range::min (void) const -{ - double retval = 0.0; - if (m_numel > 0) - { - if (m_inc > 0) - retval = m_base; - else - { - retval = m_base + (m_numel - 1) * m_inc; - - // Require '<=' test. See note in max (). - if (retval <= m_limit) - retval = m_limit; - } - - } - return retval; -} - -double -Range::max (void) const -{ - double retval = 0.0; - if (m_numel > 0) - { - if (m_inc > 0) - { - retval = m_base + (m_numel - 1) * m_inc; - - // On some machines (x86 with extended precision floating point - // arithmetic, for example) it is possible that we can overshoot the - // limit by approximately the machine precision even though we were - // very careful in our calculation of the number of elements. - // Therefore, we clip the result to the limit if it overshoots. - // The test also includes equality (>= m_limit) to have expressions - // such as -5:1:-0 result in a -0 endpoint. - if (retval >= m_limit) - retval = m_limit; - } - else - retval = m_base; - } - return retval; -} - -void -Range::sort_internal (bool ascending) -{ - if ((ascending && m_base > m_limit && m_inc < 0.0) - || (! ascending && m_base < m_limit && m_inc > 0.0)) - { - std::swap (m_base, m_limit); - m_inc = -m_inc; - } -} - -void -Range::sort_internal (Array& sidx, bool ascending) -{ - octave_idx_type nel = numel (); - - sidx.resize (dim_vector (1, nel)); - - octave_idx_type *psidx = sidx.fortran_vec (); - - bool reverse = false; - - if ((ascending && m_base > m_limit && m_inc < 0.0) - || (! ascending && m_base < m_limit && m_inc > 0.0)) - { - std::swap (m_base, m_limit); - m_inc = -m_inc; - reverse = true; - } - - octave_idx_type tmp = (reverse ? nel - 1 : 0); - octave_idx_type stp = (reverse ? -1 : 1); - - for (octave_idx_type i = 0; i < nel; i++, tmp += stp) - psidx[i] = tmp; -} - -Matrix -Range::diag (octave_idx_type k) const -{ - return matrix_value ().diag (k); -} - -Range -Range::sort (octave_idx_type dim, sortmode mode) const -{ - Range retval = *this; - - if (dim == 1) - { - if (mode == ASCENDING) - retval.sort_internal (true); - else if (mode == DESCENDING) - retval.sort_internal (false); - } - else if (dim != 0) - (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); - - return retval; -} - -Range -Range::sort (Array& sidx, octave_idx_type dim, - sortmode mode) const -{ - Range retval = *this; - - if (dim == 1) - { - if (mode == ASCENDING) - retval.sort_internal (sidx, true); - else if (mode == DESCENDING) - retval.sort_internal (sidx, false); - } - else if (dim != 0) - (*current_liboctave_error_handler) ("Range::sort: invalid dimension"); - - return retval; -} - -sortmode -Range::issorted (sortmode mode) const -{ - if (m_numel > 1 && m_inc > 0) - mode = (mode == DESCENDING) ? UNSORTED : ASCENDING; - else if (m_numel > 1 && m_inc < 0) - mode = (mode == ASCENDING) ? UNSORTED : DESCENDING; - else - mode = (mode == UNSORTED) ? ASCENDING : mode; - - return mode; -} - -void -Range::set_base (double b) -{ - if (m_base != b) - { - m_base = b; - - init (); - } -} - -void -Range::set_limit (double l) -{ - if (m_limit != l) - { - m_limit = l; - - init (); - } -} - -void -Range::set_inc (double i) -{ - if (m_inc != i) - { - m_inc = i; - - init (); - } -} - -std::ostream& -operator << (std::ostream& os, const Range& a) -{ - double b = a.base (); - double increment = a.increment (); - octave_idx_type nel = a.numel (); - - if (nel > 1) - { - // First element must be the base *exactly* (e.g., -0). - os << b << ' '; - for (octave_idx_type i = 1; i < nel-1; i++) - os << b + i * increment << ' '; - } - - // Print out the last element exactly, rather than a calculated last element. - os << a.m_limit << "\n"; - - return os; -} - -std::istream& -operator >> (std::istream& is, Range& a) -{ - is >> a.m_base; - if (is) - { - double tmp_limit; - is >> tmp_limit; - - if (is) - is >> a.m_inc; - - // Clip the m_limit to the true limit, rebuild numel, clear cache - a.set_limit (tmp_limit); - } - - return is; -} - -// DEPRECATED in Octave 7. -Range operator - (const Range& r) -{ - return Range (-r.base (), -r.limit (), -r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator + (double x, const Range& r) -{ - return Range (x + r.base (), x + r.limit (), r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator + (const Range& r, double x) -{ - return Range (r.base () + x, r.limit () + x, r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator - (double x, const Range& r) -{ - return Range (x - r.base (), x - r.limit (), -r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator - (const Range& r, double x) -{ - return Range (r.base () - x, r.limit () - x, r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator * (double x, const Range& r) -{ - return Range (x * r.base (), x * r.limit (), x * r.increment (), r.numel ()); -} - -// DEPRECATED in Octave 7. -Range operator * (const Range& r, double x) -{ - return Range (r.base () * x, r.limit () * x, r.increment () * x, r.numel ()); -} - -// C See Knuth, Art Of Computer Programming, Vol. 1, Problem 1.2.4-5. -// C -// C===Tolerant FLOOR function. -// C -// C X - is given as a Double Precision argument to be operated on. -// C It is assumed that X is represented with M mantissa bits. -// C CT - is given as a Comparison Tolerance such that -// C 0.LT.CT.LE.3-SQRT(5)/2. If the relative difference between -// C X and A whole number is less than CT, then TFLOOR is -// C returned as this whole number. By treating the -// C floating-point numbers as a finite ordered set note that -// C the heuristic EPS=2.**(-(M-1)) and CT=3*EPS causes -// C arguments of TFLOOR/TCEIL to be treated as whole numbers -// C if they are exactly whole numbers or are immediately -// C adjacent to whole number representations. Since EPS, the -// C "distance" between floating-point numbers on the unit -// C interval, and M, the number of bits in X'S mantissa, exist -// C on every floating-point computer, TFLOOR/TCEIL are -// C consistently definable on every floating-point computer. -// C -// C For more information see the following references: -// C (1) P. E. Hagerty, "More On Fuzzy Floor And Ceiling," APL QUOTE -// C QUAD 8(4):20-24, June 1978. Note that TFLOOR=FL5. -// C (2) L. M. Breed, "Definitions For Fuzzy Floor And Ceiling", APL -// C QUOTE QUAD 8(3):16-23, March 1978. This paper cites FL1 through -// C FL5, the history of five years of evolutionary development of -// C FL5 - the seven lines of code below - by open collaboration -// C and corroboration of the mathematical-computing community. -// C -// C Penn State University Center for Academic Computing -// C H. D. Knoble - August, 1978. - -static inline double -tfloor (double x, double ct) -{ -// C---------FLOOR(X) is the largest integer algebraically less than -// C or equal to X; that is, the unfuzzy FLOOR function. - -// DINT (X) = X - DMOD (X, 1.0); -// FLOOR (X) = DINT (X) - DMOD (2.0 + DSIGN (1.0, X), 3.0); - -// C---------Hagerty's FL5 function follows... - - double q = 1.0; - - if (x < 0.0) - q = 1.0 - ct; - - double rmax = q / (2.0 - ct); - - double t1 = 1.0 + std::floor (x); - t1 = (ct / q) * (t1 < 0.0 ? -t1 : t1); - t1 = (rmax < t1 ? rmax : t1); - t1 = (ct > t1 ? ct : t1); - t1 = std::floor (x + t1); - - if (x <= 0.0 || (t1 - x) < rmax) - return t1; - else - return t1 - 1.0; -} - -static inline bool -teq (double u, double v, - double ct = 3.0 * std::numeric_limits::epsilon ()) -{ - double tu = std::abs (u); - double tv = std::abs (v); - - return std::abs (u - v) < ((tu > tv ? tu : tv) * ct); -} - -octave_idx_type -Range::numel_internal (void) const -{ - octave_idx_type retval = -1; - - if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc) - || octave::math::isnan (m_limit)) - retval = -2; - else if (octave::math::isinf (m_limit) - && ((m_inc > 0 && m_limit > 0) - || (m_inc < 0 && m_limit < 0))) - retval = std::numeric_limits::max () - 1; - else if (m_inc == 0 - || (m_limit > m_base && m_inc < 0) - || (m_limit < m_base && m_inc > 0)) - { - retval = 0; - } - else - { - double ct = 3.0 * std::numeric_limits::epsilon (); - - double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct); - - octave_idx_type n_elt = (tmp > 0.0 - ? static_cast (tmp) : 0); - - // If the final element that we would compute for the range is equal to - // the limit of the range, or is an adjacent floating point number, - // accept it. Otherwise, try a range with one fewer element. If that - // fails, try again with one more element. - // - // I'm not sure this is very good, but it seems to work better than just - // using tfloor as above. For example, without it, the expression - // 1.8:0.05:1.9 fails to produce the expected result of [1.8, 1.85, 1.9]. - - if (! teq (m_base + (n_elt - 1) * m_inc, m_limit)) - { - if (teq (m_base + (n_elt - 2) * m_inc, m_limit)) - n_elt--; - else if (teq (m_base + n_elt * m_inc, m_limit)) - n_elt++; - } - - retval = ((n_elt < std::numeric_limits::max ()) - ? n_elt : -1); - } - - return retval; -} - -double -Range::limit_internal (void) const -{ - double new_limit = m_inc > 0 ? max () : min (); - - // If result must be an integer then force the new_limit to be one. - if (all_elements_are_ints ()) - new_limit = std::round (new_limit); - - return new_limit; -} - -void -Range::init (void) -{ - m_numel = numel_internal (); - - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); -} diff -r 9089bd969b37 -r bd9da634f00d liboctave/array/Range.h --- a/liboctave/array/Range.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/array/Range.h Tue Dec 06 15:17:16 2022 -0500 @@ -40,550 +40,360 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// For now, only define for floating point types. However, we only -// need range as a temporary local variable in make_float_range -// in ov.cc. - -template -class -range::value>::type> -{ -public: - - range (void) - : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0), - m_reverse (false) - { } - - // LIMIT is an upper limit and may be outside the range of actual - // values. For floating point ranges, we perform a tolerant check - // to attempt to capture limit in the set of values if it is "close" - // to the value of base + a multiple of the increment. - - range (const T& base, const T& increment, const T& limit, - bool reverse = false) - : m_base (base), m_increment (increment), m_limit (limit), - m_final (), m_numel (), m_reverse (reverse) - { - init (); - } - - range (const T& base, const T& limit) - : m_base (base), m_increment (1), m_limit (limit), m_final (), m_numel (), - m_reverse (false) - { - init (); - } + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. - // Allow conversion from (presumably) properly constructed Range - // objects. The values of base, limit, increment, and numel must be - // consistent. - - // FIXME: Actually check that base, limit, increment, and numel are - // consistent? - - range (const T& base, const T& increment, const T& limit, - octave_idx_type numel, bool reverse = false) - : m_base (base), m_increment (increment), m_limit (limit), - m_final (limit), m_numel (numel), m_reverse (reverse) - { } - - // We don't use a constructor for this because it will conflict with - // range (base, limit, increment) when T is octave_idx_type. - - static range make_n_element_range (const T& base, const T& increment, - octave_idx_type numel, - bool reverse = false) - { - // We could just make this constructor public, but it allows - // inconsistent ranges to be constructed. And it is probably much - // clearer to see "make_n_element_range" instead of puzzling over the - // purpose of this strange constructor form. - - T final_val = (reverse ? base - (numel - 1) * increment - : base + (numel - 1) * increment); - - return range (base, increment, final_val, numel, reverse); - } - - range (const range& r) - : m_base (r.m_base), m_increment (r.m_increment), - m_limit (r.m_limit), m_final (r.m_final), - m_numel (r.m_numel), m_reverse (r.m_reverse) - { } - - range& operator = (const range& r) + template + class + range::value>::type> { - if (this != &r) - { - m_base = r.m_base; - m_increment = r.m_increment; - m_limit = r.m_limit; - m_final = r.m_final; - m_numel = r.m_numel; - m_reverse = r.m_reverse; - } + public: + + range (void) + : m_base (0), m_increment (0), m_limit (0), m_final (0), m_numel (0), + m_reverse (false) + { } + + // LIMIT is an upper limit and may be outside the range of actual + // values. For floating point ranges, we perform a tolerant check + // to attempt to capture limit in the set of values if it is "close" + // to the value of base + a multiple of the increment. - return *this; - } - - ~range (void) = default; + range (const T& base, const T& increment, const T& limit, + bool reverse = false) + : m_base (base), m_increment (increment), m_limit (limit), + m_final (), m_numel (), m_reverse (reverse) + { + init (); + } - T base (void) const { return m_base; } - T increment (void) const { return m_increment; } - T limit (void) const { return m_limit; } - bool reverse (void) const { return m_reverse; } + range (const T& base, const T& limit) + : m_base (base), m_increment (1), m_limit (limit), m_final (), m_numel (), + m_reverse (false) + { + init (); + } + + // Allow conversion from (presumably) properly constructed Range + // objects. The values of base, limit, increment, and numel must be + // consistent. - T final_value (void) const { return m_final; } + // FIXME: Actually check that base, limit, increment, and numel are + // consistent? - T min (void) const - { - return (m_numel > 0 - ? ((m_reverse ? m_increment > T (0) - : m_increment > T (0)) ? base () : final_value ()) - : T (0)); - } + range (const T& base, const T& increment, const T& limit, + octave_idx_type numel, bool reverse = false) + : m_base (base), m_increment (increment), m_limit (limit), + m_final (limit), m_numel (numel), m_reverse (reverse) + { } + + // We don't use a constructor for this because it will conflict with + // range (base, limit, increment) when T is octave_idx_type. - T max (void) const - { - return (m_numel > 0 - ? ((m_reverse ? m_increment < T (0) - : m_increment > T (0)) ? final_value () : base ()) - : T (0)); - } + static range make_n_element_range (const T& base, const T& increment, + octave_idx_type numel, + bool reverse = false) + { + // We could just make this constructor public, but it allows + // inconsistent ranges to be constructed. And it is probably much + // clearer to see "make_n_element_range" instead of puzzling over the + // purpose of this strange constructor form. - octave_idx_type numel (void) const { return m_numel; } + T final_val = (reverse ? base - (numel - 1) * increment + : base + (numel - 1) * increment); + + return range (base, increment, final_val, numel, reverse); + } + + range (const range& r) + : m_base (r.m_base), m_increment (r.m_increment), + m_limit (r.m_limit), m_final (r.m_final), + m_numel (r.m_numel), m_reverse (r.m_reverse) + { } - // To support things like "for i = 1:Inf; ...; end" that are - // required for Matlab compatibility, creation of a range object - // like 1:Inf is allowed with m_numel set to - // numeric_limits::max(). However, it is not - // possible to store these ranges. The following function allows - // us to easily distinguish ranges with an infinite number of - // elements. There are specializations for double and float. + range& operator = (const range& r) + { + if (this != &r) + { + m_base = r.m_base; + m_increment = r.m_increment; + m_limit = r.m_limit; + m_final = r.m_final; + m_numel = r.m_numel; + m_reverse = r.m_reverse; + } - bool is_storable (void) const { return true; } + return *this; + } + + ~range (void) = default; - dim_vector dims (void) const { return dim_vector (1, m_numel); } + T base (void) const { return m_base; } + T increment (void) const { return m_increment; } + T limit (void) const { return m_limit; } + bool reverse (void) const { return m_reverse; } - octave_idx_type rows (void) const { return 1; } + T final_value (void) const { return m_final; } - octave_idx_type cols (void) const { return numel (); } - octave_idx_type columns (void) const { return numel (); } + T min (void) const + { + return (m_numel > 0 + ? ((m_reverse ? m_increment > T (0) + : m_increment > T (0)) ? base () : final_value ()) + : T (0)); + } - bool isempty (void) const { return numel () == 0; } + T max (void) const + { + return (m_numel > 0 + ? ((m_reverse ? m_increment < T (0) + : m_increment > T (0)) ? final_value () : base ()) + : T (0)); + } - bool all_elements_are_ints (void) const { return true; } + octave_idx_type numel (void) const { return m_numel; } - sortmode issorted (sortmode mode = ASCENDING) const - { - if (m_numel > 1 && (m_reverse ? m_increment < T (0) - : m_increment > T (0))) - mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING); - else if (m_numel > 1 && (m_reverse ? m_increment > T (0) - : m_increment < T (0))) - mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING); - else - mode = ((mode == UNSORTED) ? ASCENDING : mode); + // To support things like "for i = 1:Inf; ...; end" that are + // required for Matlab compatibility, creation of a range object + // like 1:Inf is allowed with m_numel set to + // numeric_limits::max(). However, it is not + // possible to store these ranges. The following function allows + // us to easily distinguish ranges with an infinite number of + // elements. There are specializations for double and float. + + bool is_storable (void) const { return true; } + + dim_vector dims (void) const { return dim_vector (1, m_numel); } + + octave_idx_type rows (void) const { return 1; } + + octave_idx_type cols (void) const { return numel (); } + octave_idx_type columns (void) const { return numel (); } + + bool isempty (void) const { return numel () == 0; } + + bool all_elements_are_ints (void) const { return true; } - return mode; - } - - OCTAVE_API octave_idx_type nnz (void) const; + sortmode issorted (sortmode mode = ASCENDING) const + { + if (m_numel > 1 && (m_reverse ? m_increment < T (0) + : m_increment > T (0))) + mode = ((mode == DESCENDING) ? UNSORTED : ASCENDING); + else if (m_numel > 1 && (m_reverse ? m_increment > T (0) + : m_increment < T (0))) + mode = ((mode == ASCENDING) ? UNSORTED : DESCENDING); + else + mode = ((mode == UNSORTED) ? ASCENDING : mode); - // Support for single-index subscripting, without generating matrix cache. + return mode; + } + + OCTAVE_API octave_idx_type nnz (void) const; - T checkelem (octave_idx_type i) const - { - if (i < 0 || i >= m_numel) - err_index_out_of_range (2, 2, i+1, m_numel, dims ()); + // Support for single-index subscripting, without generating matrix cache. + + T checkelem (octave_idx_type i) const + { + if (i < 0 || i >= m_numel) + err_index_out_of_range (2, 2, i+1, m_numel, dims ()); - if (i == 0) - // Required for proper NaN handling. - return (m_numel == 1 ? final_value () : m_base); - else if (i < m_numel - 1) - return (m_reverse ? m_base + T (i) * m_increment - : m_base + T (i) * m_increment); - else - return final_value (); - } + if (i == 0) + // Required for proper NaN handling. + return (m_numel == 1 ? final_value () : m_base); + else if (i < m_numel - 1) + return (m_reverse ? m_base + T (i) * m_increment + : m_base + T (i) * m_increment); + else + return final_value (); + } - T checkelem (octave_idx_type i, octave_idx_type j) const - { - // Ranges are *always* row vectors. - if (i != 0) - err_index_out_of_range (1, 1, i+1, m_numel, dims ()); + T checkelem (octave_idx_type i, octave_idx_type j) const + { + // Ranges are *always* row vectors. + if (i != 0) + err_index_out_of_range (1, 1, i+1, m_numel, dims ()); - return checkelem (j); - } + return checkelem (j); + } - T elem (octave_idx_type i) const - { - if (i == 0) - // Required for proper NaN handling. - return (m_numel == 1 ? final_value () : m_base); - else if (i < m_numel - 1) - return (m_reverse ? m_base - T (i) * m_increment - : m_base + T (i) * m_increment); - else - return final_value (); - } + T elem (octave_idx_type i) const + { + if (i == 0) + // Required for proper NaN handling. + return (m_numel == 1 ? final_value () : m_base); + else if (i < m_numel - 1) + return (m_reverse ? m_base - T (i) * m_increment + : m_base + T (i) * m_increment); + else + return final_value (); + } - T elem (octave_idx_type /* i */, octave_idx_type j) const - { - return elem (j); - } + T elem (octave_idx_type /* i */, octave_idx_type j) const + { + return elem (j); + } - T operator () (octave_idx_type i) const - { - return elem (i); - } + T operator () (octave_idx_type i) const + { + return elem (i); + } - T operator () (octave_idx_type i, octave_idx_type j) const - { - return elem (i, j); - } + T operator () (octave_idx_type i, octave_idx_type j) const + { + return elem (i, j); + } - Array index (const idx_vector& idx) const - { - Array retval; + Array index (const idx_vector& idx) const + { + Array retval; - octave_idx_type n = m_numel; + octave_idx_type n = m_numel; - if (idx.is_colon ()) - { - retval = array_value ().reshape (dim_vector (m_numel, 1)); - } - else - { - if (idx.extent (n) != n) - err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); + if (idx.is_colon ()) + { + retval = array_value ().reshape (dim_vector (m_numel, 1)); + } + else + { + if (idx.extent (n) != n) + err_index_out_of_range (1, 1, idx.extent (n), n, dims ()); - dim_vector idx_dims = idx.orig_dimensions (); - octave_idx_type idx_len = idx.length (n); + dim_vector idx_dims = idx.orig_dimensions (); + octave_idx_type idx_len = idx.length (n); - // taken from Array.cc. - if (n != 1 && idx_dims.isvector ()) - idx_dims = dim_vector (1, idx_len); + // taken from Array.cc. + if (n != 1 && idx_dims.isvector ()) + idx_dims = dim_vector (1, idx_len); - retval.clear (idx_dims); + retval.clear (idx_dims); - // Loop over all values in IDX, executing the lambda - // expression for each index value. + // Loop over all values in IDX, executing the lambda + // expression for each index value. - T *array = retval.fortran_vec (); + T *array = retval.fortran_vec (); - idx.loop (n, [=, &array] (octave_idx_type i) - { - if (i == 0) - // Required for proper NaN handling. - *array++ = (m_numel == 0 ? m_final : m_base); - else if (i < m_numel - 1) - *array++ = (m_reverse ? m_base - T (i) * m_increment - : m_base + T (i) * m_increment); - else - *array++ = m_final; - }); - } + idx.loop (n, [=, &array] (octave_idx_type i) + { + if (i == 0) + // Required for proper NaN handling. + *array++ = (m_numel == 0 ? m_final : m_base); + else if (i < m_numel - 1) + *array++ = (m_reverse ? m_base - T (i) * m_increment + : m_base + T (i) * m_increment); + else + *array++ = m_final; + }); + } - return retval; - } + return retval; + } - Array diag (octave_idx_type k) const - { - return array_value ().diag (k); - } + Array diag (octave_idx_type k) const + { + return array_value ().diag (k); + } - Array array_value (void) const - { - octave_idx_type nel = numel (); + Array array_value (void) const + { + octave_idx_type nel = numel (); - Array retval (dim_vector (1, nel)); + Array retval (dim_vector (1, nel)); - if (nel == 1) - // Required for proper NaN handling. - retval(0) = final_value (); - else if (nel > 1) - { - // The first element must always be *exactly* the base. - // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). - retval(0) = m_base; + if (nel == 1) + // Required for proper NaN handling. + retval(0) = final_value (); + else if (nel > 1) + { + // The first element must always be *exactly* the base. + // E.g, -0 would otherwise become +0 in the loop (-0 + 0*increment). + retval(0) = m_base; - if (m_reverse) - for (octave_idx_type i = 1; i < nel - 1; i++) - retval.xelem (i) = m_base - i * m_increment; - else - for (octave_idx_type i = 1; i < nel - 1; i++) - retval.xelem (i) = m_base + i * m_increment; + if (m_reverse) + for (octave_idx_type i = 1; i < nel - 1; i++) + retval.xelem (i) = m_base - i * m_increment; + else + for (octave_idx_type i = 1; i < nel - 1; i++) + retval.xelem (i) = m_base + i * m_increment; - retval.xelem (nel - 1) = final_value (); - } + retval.xelem (nel - 1) = final_value (); + } - return retval; - } + return retval; + } -private: + private: - T m_base; - T m_increment; - T m_limit; - T m_final; - octave_idx_type m_numel; - bool m_reverse; + T m_base; + T m_increment; + T m_limit; + T m_final; + octave_idx_type m_numel; + bool m_reverse; - // Setting the number of elements to zero when the increment is zero - // is intentional and matches the behavior of Matlab's colon - // operator. + // Setting the number of elements to zero when the increment is zero + // is intentional and matches the behavior of Matlab's colon + // operator. - // These calculations are appropriate for integer ranges. There are - // specializations for double and float. + // These calculations are appropriate for integer ranges. There are + // specializations for double and float. - void init (void) - { - if (m_reverse) - { - m_numel = ((m_increment == T (0) - || (m_limit > m_base && m_increment > T (0)) - || (m_limit < m_base && m_increment < T (0))) - ? T (0) - : (m_base - m_limit - m_increment) / m_increment); + void init (void) + { + if (m_reverse) + { + m_numel = ((m_increment == T (0) + || (m_limit > m_base && m_increment > T (0)) + || (m_limit < m_base && m_increment < T (0))) + ? T (0) + : (m_base - m_limit - m_increment) / m_increment); - m_final = m_base - (m_numel - 1) * m_increment; - } - else - { - m_numel = ((m_increment == T (0) - || (m_limit > m_base && m_increment < T (0)) - || (m_limit < m_base && m_increment > T (0))) - ? T (0) - : (m_limit - m_base + m_increment) / m_increment); + m_final = m_base - (m_numel - 1) * m_increment; + } + else + { + m_numel = ((m_increment == T (0) + || (m_limit > m_base && m_increment < T (0)) + || (m_limit < m_base && m_increment > T (0))) + ? T (0) + : (m_limit - m_base + m_increment) / m_increment); - m_final = m_base + (m_numel - 1) * m_increment; - } - } -}; + m_final = m_base + (m_numel - 1) * m_increment; + } + } + }; -// Specializations defined externally. + // Specializations defined externally. -template <> OCTAVE_API bool range::all_elements_are_ints (void) const; -template <> OCTAVE_API bool range::all_elements_are_ints (void) const; + template <> OCTAVE_API bool range::all_elements_are_ints (void) const; + template <> OCTAVE_API bool range::all_elements_are_ints (void) const; -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); -// For now, only define for floating point types. However, we only -// need range as a temporary local variable in make_float_range -// in ov.cc. + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. #if 0 -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); -template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); + template <> OCTAVE_API void range::init (void); #endif -template <> OCTAVE_API bool range::is_storable (void) const; -template <> OCTAVE_API bool range::is_storable (void) const; + template <> OCTAVE_API bool range::is_storable (void) const; + template <> OCTAVE_API bool range::is_storable (void) const; -template <> OCTAVE_API octave_idx_type range::nnz (void) const; -template <> OCTAVE_API octave_idx_type range::nnz (void) const; + template <> OCTAVE_API octave_idx_type range::nnz (void) const; + template <> OCTAVE_API octave_idx_type range::nnz (void) const; OCTAVE_END_NAMESPACE(octave) -class -Range -{ -public: - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (void) - : m_base (0), m_limit (0), m_inc (0), m_numel (0) - { } - - // Assume range is already properly constructed, so just copy internal - // values. However, we set LIMIT to the computed final value because - // that mimics the behavior of the other Range class constructors that - // reset limit to the computed final value. - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (const octave::range& r) - : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()), - m_numel (r.numel ()) - { } - - Range (const Range& r) = default; - - Range& operator = (const Range& r) = default; - - ~Range (void) = default; - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double l) - : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ()) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double l, double i) - : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ()) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - // NOTE: The following constructor may be deprecated and removed after - // the arithmetic operators are removed. - - // For operators' usage (to preserve element count) and to create - // constant row vectors (obsolete usage). - - OCTAVE_DEPRECATED (7, "use the 'octave::range' class instead") - Range (double b, double i, octave_idx_type n) - : m_base (b), m_limit (b + (n-1) * i), m_inc (i), m_numel (n) - { - if (! octave::math::isinf (m_limit)) - m_limit = limit_internal (); - } - - // The range has a finite number of elements. - bool ok (void) const - { - return (octave::math::isfinite (m_limit) - && (m_numel >= 0 || m_numel == -2)); - } - - double base (void) const { return m_base; } - double limit (void) const { return m_limit; } - double inc (void) const { return m_inc; } - double increment (void) const { return m_inc; } - - // We adjust the limit to be the final value, so return that. We - // could introduce a new variable to store the final value separately, - // but it seems like that would just add confusion. If we changed - // the meaning of the limit function, we would change the behavior of - // programs that expect limit to be the final value instead of the - // value of the limit when the range was created. This problem will - // be fixed with the new template range class. - double final_value (void) const { return m_limit; } - - octave_idx_type numel (void) const { return m_numel; } - - dim_vector dims (void) const { return dim_vector (1, m_numel); } - - octave_idx_type rows (void) const { return 1; } - - octave_idx_type cols (void) const { return numel (); } - octave_idx_type columns (void) const { return numel (); } - - bool isempty (void) const { return numel () == 0; } - - OCTAVE_API bool all_elements_are_ints (void) const; - - OCTAVE_API Matrix matrix_value (void) const; - - OCTAVE_API double min (void) const; - OCTAVE_API double max (void) const; - - OCTAVE_API void sort_internal (bool ascending = true); - OCTAVE_API void sort_internal (Array& sidx, bool ascending = true); - - OCTAVE_API Matrix diag (octave_idx_type k = 0) const; - - OCTAVE_API Range sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const; - OCTAVE_API Range sort (Array& sidx, octave_idx_type dim = 0, - sortmode mode = ASCENDING) const; - - OCTAVE_API sortmode issorted (sortmode mode = ASCENDING) const; - - OCTAVE_API octave_idx_type nnz (void) const; - - // Support for single-index subscripting, without generating matrix cache. - - OCTAVE_API double checkelem (octave_idx_type i) const; - OCTAVE_API double checkelem (octave_idx_type i, octave_idx_type j) const; - - OCTAVE_API double elem (octave_idx_type i) const; - double elem (octave_idx_type /* i */, octave_idx_type j) const - { return elem (j); } - - double operator () (octave_idx_type i) const { return elem (i); } - double operator () (octave_idx_type i, octave_idx_type j) const - { return elem (i, j); } - - OCTAVE_API Array index (const octave::idx_vector& i) const; - - OCTAVE_API void set_base (double b); - - OCTAVE_API void set_limit (double l); - - OCTAVE_API void set_inc (double i); - - friend OCTAVE_API std::ostream& operator << (std::ostream& os, - const Range& r); - friend OCTAVE_API std::istream& operator >> (std::istream& is, Range& r); - - friend OCTAVE_API Range operator - (const Range& r); - friend OCTAVE_API Range operator + (double x, const Range& r); - friend OCTAVE_API Range operator + (const Range& r, double x); - friend OCTAVE_API Range operator - (double x, const Range& r); - friend OCTAVE_API Range operator - (const Range& r, double x); - friend OCTAVE_API Range operator * (double x, const Range& r); - friend OCTAVE_API Range operator * (const Range& r, double x); - -private: - - double m_base; - double m_limit; - double m_inc; - - octave_idx_type m_numel; - - OCTAVE_API octave_idx_type numel_internal (void) const; - - OCTAVE_API double limit_internal (void) const; - - OCTAVE_API void init (void); - -protected: - - // NOTE: The following constructor may be removed when the arithmetic - // operators are removed. - - // For operators' usage (to allow all values to be set directly). - Range (double b, double l, double i, octave_idx_type n) - : m_base (b), m_limit (l), m_inc (i), m_numel (n) - { } -}; - -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator + (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator + (const Range& r, double x); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator - (const Range& r, double x); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator * (double x, const Range& r); - -OCTAVE_DEPRECATED (7, "arithmetic operations on Range objects are unreliable") -extern OCTAVE_API Range operator * (const Range& r, double x); #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/numeric/CollocWt.h --- a/liboctave/numeric/CollocWt.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/numeric/CollocWt.h Tue Dec 06 15:17:16 2022 -0500 @@ -209,9 +209,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::CollocWt' instead") -typedef octave::CollocWt CollocWt; #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/numeric/oct-convn.h --- a/liboctave/numeric/oct-convn.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/numeric/oct-convn.h Tue Dec 06 15:17:16 2022 -0500 @@ -158,152 +158,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline NDArray -convn (const NDArray& a, const NDArray& b, convn_type ct) -{ - return octave::convn (a, b, static_cast (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline Matrix -convn (const Matrix& a, const Matrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline Matrix -convn (const Matrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// double complex X double real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexNDArray -convn (const ComplexNDArray& a, const NDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const Matrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ColumnVector& c, const RowVector& r, - convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// double complex X double complex - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexNDArray -convn (const ComplexNDArray& a, const ComplexNDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ComplexMatrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline ComplexMatrix -convn (const ComplexMatrix& a, const ComplexColumnVector& c, - const ComplexRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float real X float real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatNDArray -convn (const FloatNDArray& a, const FloatNDArray& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatMatrix -convn (const FloatMatrix& a, const FloatMatrix& b, convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatMatrix -convn (const FloatMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float complex X float real - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexNDArray -convn (const FloatComplexNDArray& a, const FloatNDArray& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatMatrix& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatColumnVector& c, - const FloatRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} - -// float complex X float complex - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexNDArray -convn (const FloatComplexNDArray& a, const FloatComplexNDArray& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatComplexMatrix& b, - convn_type ct) -{ - return octave::convn (a, b, octave::convert_enum (ct)); -} - -OCTAVE_DEPRECATED (7, "use 'octave::convn' instead") -inline FloatComplexMatrix -convn (const FloatComplexMatrix& a, const FloatComplexColumnVector& c, - const FloatComplexRowVector& r, convn_type ct) -{ - return octave::convn (a, c, r, octave::convert_enum (ct)); -} #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/numeric/oct-norm.cc --- a/liboctave/numeric/oct-norm.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/numeric/oct-norm.cc Tue Dec 06 15:17:16 2022 -0500 @@ -65,261 +65,261 @@ OCTAVE_BEGIN_NAMESPACE(octave) -// Theory: norm accumulator is an object that has an accum method able -// to handle both real and complex element, and a cast operator -// returning the intermediate norm. Reference: Higham, N. "Estimating -// the Matrix p-Norm." Numer. Math. 62, 539-555, 1992. + // Theory: norm accumulator is an object that has an accum method able + // to handle both real and complex element, and a cast operator + // returning the intermediate norm. Reference: Higham, N. "Estimating + // the Matrix p-Norm." Numer. Math. 62, 539-555, 1992. -// norm accumulator for the p-norm -template -class norm_accumulator_p -{ -public: - norm_accumulator_p () { } // we need this one for Array - norm_accumulator_p (R pp) : m_p(pp), m_scl(0), m_sum(1) { } + // norm accumulator for the p-norm + template + class norm_accumulator_p + { + public: + norm_accumulator_p () { } // we need this one for Array + norm_accumulator_p (R pp) : m_p(pp), m_scl(0), m_sum(1) { } - template - void accum (U val) - { - octave_quit (); - R t = std::abs (val); - if (m_scl == t) // we need this to handle Infs properly - m_sum += 1; - else if (m_scl < t) - { - m_sum *= std::pow (m_scl/t, m_p); + template + void accum (U val) + { + octave_quit (); + R t = std::abs (val); + if (m_scl == t) // we need this to handle Infs properly m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += std::pow (t/m_scl, m_p); - } + else if (m_scl < t) + { + m_sum *= std::pow (m_scl/t, m_p); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += std::pow (t/m_scl, m_p); + } + + operator R () { return m_scl * std::pow (m_sum, 1/m_p); } - operator R () { return m_scl * std::pow (m_sum, 1/m_p); } + private: + R m_p, m_scl, m_sum; + }; -private: - R m_p, m_scl, m_sum; -}; + // norm accumulator for the minus p-pseudonorm + template + class norm_accumulator_mp + { + public: + norm_accumulator_mp () { } // we need this one for Array + norm_accumulator_mp (R pp) : m_p(pp), m_scl(0), m_sum(1) { } -// norm accumulator for the minus p-pseudonorm -template -class norm_accumulator_mp -{ -public: - norm_accumulator_mp () { } // we need this one for Array - norm_accumulator_mp (R pp) : m_p(pp), m_scl(0), m_sum(1) { } + template + void accum (U val) + { + octave_quit (); + R t = 1 / std::abs (val); + if (m_scl == t) + m_sum += 1; + else if (m_scl < t) + { + m_sum *= std::pow (m_scl/t, m_p); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += std::pow (t/m_scl, m_p); + } - template - void accum (U val) + operator R () { return m_scl * std::pow (m_sum, -1/m_p); } + + private: + R m_p, m_scl, m_sum; + }; + + // norm accumulator for the 2-norm (euclidean) + template + class norm_accumulator_2 { - octave_quit (); - R t = 1 / std::abs (val); - if (m_scl == t) - m_sum += 1; - else if (m_scl < t) - { - m_sum *= std::pow (m_scl/t, m_p); + public: + norm_accumulator_2 () : m_scl(0), m_sum(1) { } + + void accum (R val) + { + R t = std::abs (val); + if (m_scl == t) m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += std::pow (t/m_scl, m_p); - } + else if (m_scl < t) + { + m_sum *= pow2 (m_scl/t); + m_sum += 1; + m_scl = t; + } + else if (t != 0) + m_sum += pow2 (t/m_scl); + } - operator R () { return m_scl * std::pow (m_sum, -1/m_p); } + void accum (std::complex val) + { + accum (val.real ()); + accum (val.imag ()); + } + + operator R () { return m_scl * std::sqrt (m_sum); } + + private: + static inline R pow2 (R x) { return x*x; } + + //-------- -private: - R m_p, m_scl, m_sum; -}; + R m_scl, m_sum; + }; -// norm accumulator for the 2-norm (euclidean) -template -class norm_accumulator_2 -{ -public: - norm_accumulator_2 () : m_scl(0), m_sum(1) { } + // norm accumulator for the 1-norm (city metric) + template + class norm_accumulator_1 + { + public: + norm_accumulator_1 () : m_sum (0) { } + template + void accum (U val) + { + m_sum += std::abs (val); + } - void accum (R val) + operator R () { return m_sum; } + + private: + R m_sum; + }; + + // norm accumulator for the inf-norm (max metric) + template + class norm_accumulator_inf { - R t = std::abs (val); - if (m_scl == t) - m_sum += 1; - else if (m_scl < t) - { - m_sum *= pow2 (m_scl/t); - m_sum += 1; - m_scl = t; - } - else if (t != 0) - m_sum += pow2 (t/m_scl); - } + public: + norm_accumulator_inf () : m_max (0) { } + template + void accum (U val) + { + if (math::isnan (val)) + m_max = numeric_limits::NaN (); + else + m_max = std::max (m_max, std::abs (val)); + } + + operator R () { return m_max; } - void accum (std::complex val) + private: + R m_max; + }; + + // norm accumulator for the -inf pseudonorm (min abs value) + template + class norm_accumulator_minf { - accum (val.real ()); - accum (val.imag ()); - } + public: + norm_accumulator_minf () : m_min (numeric_limits::Inf ()) { } + template + void accum (U val) + { + if (math::isnan (val)) + m_min = numeric_limits::NaN (); + else + m_min = std::min (m_min, std::abs (val)); + } - operator R () { return m_scl * std::sqrt (m_sum); } - -private: - static inline R pow2 (R x) { return x*x; } + operator R () { return m_min; } - //-------- - - R m_scl, m_sum; -}; + private: + R m_min; + }; -// norm accumulator for the 1-norm (city metric) -template -class norm_accumulator_1 -{ -public: - norm_accumulator_1 () : m_sum (0) { } - template - void accum (U val) + // norm accumulator for the 0-pseudonorm (hamming distance) + template + class norm_accumulator_0 { - m_sum += std::abs (val); + public: + norm_accumulator_0 () : m_num (0) { } + template + void accum (U val) + { + if (val != static_cast (0)) ++m_num; + } + + operator R () { return m_num; } + + private: + unsigned int m_num; + }; + + // OK, we're armed :) Now let's go for the fun + + template + inline void vector_norm (const Array& v, R& res, ACC acc) + { + for (octave_idx_type i = 0; i < v.numel (); i++) + acc.accum (v(i)); + + res = acc; } - operator R () { return m_sum; } - -private: - R m_sum; -}; + // dense versions + template + void column_norms (const MArray& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (1, m.columns ())); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + ACC accj = acc; + for (octave_idx_type i = 0; i < m.rows (); i++) + accj.accum (m(i, j)); -// norm accumulator for the inf-norm (max metric) -template -class norm_accumulator_inf -{ -public: - norm_accumulator_inf () : m_max (0) { } - template - void accum (U val) - { - if (math::isnan (val)) - m_max = numeric_limits::NaN (); - else - m_max = std::max (m_max, std::abs (val)); + res.xelem (j) = accj; + } } - operator R () { return m_max; } - -private: - R m_max; -}; - -// norm accumulator for the -inf pseudonorm (min abs value) -template -class norm_accumulator_minf -{ -public: - norm_accumulator_minf () : m_min (numeric_limits::Inf ()) { } - template - void accum (U val) + template + void row_norms (const MArray& m, MArray& res, ACC acc) { - if (math::isnan (val)) - m_min = numeric_limits::NaN (); - else - m_min = std::min (m_min, std::abs (val)); - } - - operator R () { return m_min; } + res = MArray (dim_vector (m.rows (), 1)); + std::vector acci (m.rows (), acc); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + for (octave_idx_type i = 0; i < m.rows (); i++) + acci[i].accum (m(i, j)); + } -private: - R m_min; -}; - -// norm accumulator for the 0-pseudonorm (hamming distance) -template -class norm_accumulator_0 -{ -public: - norm_accumulator_0 () : m_num (0) { } - template - void accum (U val) - { - if (val != static_cast (0)) ++m_num; + for (octave_idx_type i = 0; i < m.rows (); i++) + res.xelem (i) = acci[i]; } - operator R () { return m_num; } - -private: - unsigned int m_num; -}; - -// OK, we're armed :) Now let's go for the fun - -template -inline void vector_norm (const Array& v, R& res, ACC acc) -{ - for (octave_idx_type i = 0; i < v.numel (); i++) - acc.accum (v(i)); + // sparse versions + template + void column_norms (const MSparse& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (1, m.columns ())); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + ACC accj = acc; + for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) + accj.accum (m.data (k)); - res = acc; -} - -// dense versions -template -void column_norms (const MArray& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (1, m.columns ())); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - ACC accj = acc; - for (octave_idx_type i = 0; i < m.rows (); i++) - accj.accum (m(i, j)); - - res.xelem (j) = accj; - } -} + res.xelem (j) = accj; + } + } -template -void row_norms (const MArray& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (m.rows (), 1)); - std::vector acci (m.rows (), acc); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - for (octave_idx_type i = 0; i < m.rows (); i++) - acci[i].accum (m(i, j)); - } - - for (octave_idx_type i = 0; i < m.rows (); i++) - res.xelem (i) = acci[i]; -} + template + void row_norms (const MSparse& m, MArray& res, ACC acc) + { + res = MArray (dim_vector (m.rows (), 1)); + std::vector acci (m.rows (), acc); + for (octave_idx_type j = 0; j < m.columns (); j++) + { + for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) + acci[m.ridx (k)].accum (m.data (k)); + } -// sparse versions -template -void column_norms (const MSparse& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (1, m.columns ())); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - ACC accj = acc; - for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) - accj.accum (m.data (k)); - - res.xelem (j) = accj; - } -} + for (octave_idx_type i = 0; i < m.rows (); i++) + res.xelem (i) = acci[i]; + } -template -void row_norms (const MSparse& m, MArray& res, ACC acc) -{ - res = MArray (dim_vector (m.rows (), 1)); - std::vector acci (m.rows (), acc); - for (octave_idx_type j = 0; j < m.columns (); j++) - { - for (octave_idx_type k = m.cidx (j); k < m.cidx (j+1); k++) - acci[m.ridx (k)].accum (m.data (k)); - } - - for (octave_idx_type i = 0; i < m.rows (); i++) - res.xelem (i) = acci[i]; -} - -// now the dispatchers + // now the dispatchers #define DEFINE_DISPATCHER(FCN_NAME, ARG_TYPE, RES_TYPE) \ template \ RES_TYPE FCN_NAME (const ARG_TYPE& v, R p) \ @@ -345,224 +345,216 @@ return res; \ } -DEFINE_DISPATCHER (vector_norm, MArray, R) -DEFINE_DISPATCHER (column_norms, MArray, MArray) -DEFINE_DISPATCHER (row_norms, MArray, MArray) -DEFINE_DISPATCHER (column_norms, MSparse, MArray) -DEFINE_DISPATCHER (row_norms, MSparse, MArray) + DEFINE_DISPATCHER (vector_norm, MArray, R) + DEFINE_DISPATCHER (column_norms, MArray, MArray) + DEFINE_DISPATCHER (row_norms, MArray, MArray) + DEFINE_DISPATCHER (column_norms, MSparse, MArray) + DEFINE_DISPATCHER (row_norms, MSparse, MArray) -// The approximate subproblem in Higham's method. Find lambda and mu such -// that norm ([lambda, mu], p) == 1 and norm (y*lambda + col*mu, p) is -// maximized. -// Real version. As in Higham's paper. -template -static void -higham_subp (const ColVectorT& y, const ColVectorT& col, - octave_idx_type nsamp, R p, R& lambda, R& mu) -{ - R nrm = 0; - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - R lambda1 = cos (fi); - R mu1 = sin (fi); - R lmnr = std::pow (std::pow (std::abs (lambda1), p) + - std::pow (std::abs (mu1), p), 1/p); - lambda1 /= lmnr; mu1 /= lmnr; - R nrm1 = vector_norm (lambda1 * y + mu1 * col, p); - if (nrm1 > nrm) - { - lambda = lambda1; - mu = mu1; - nrm = nrm1; - } - } -} + // The approximate subproblem in Higham's method. Find lambda and mu such + // that norm ([lambda, mu], p) == 1 and norm (y*lambda + col*mu, p) is + // maximized. + // Real version. As in Higham's paper. + template + static void + higham_subp (const ColVectorT& y, const ColVectorT& col, + octave_idx_type nsamp, R p, R& lambda, R& mu) + { + R nrm = 0; + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + R lambda1 = cos (fi); + R mu1 = sin (fi); + R lmnr = std::pow (std::pow (std::abs (lambda1), p) + + std::pow (std::abs (mu1), p), 1/p); + lambda1 /= lmnr; mu1 /= lmnr; + R nrm1 = vector_norm (lambda1 * y + mu1 * col, p); + if (nrm1 > nrm) + { + lambda = lambda1; + mu = mu1; + nrm = nrm1; + } + } + } -// Complex version. Higham's paper does not deal with complex case, so we -// use a simple extension. First, guess the magnitudes as in real version, -// then try to rotate lambda to improve further. -template -static void -higham_subp (const ColVectorT& y, const ColVectorT& col, - octave_idx_type nsamp, R p, - std::complex& lambda, std::complex& mu) -{ - typedef std::complex CR; - R nrm = 0; - lambda = 1.0; - CR lamcu = lambda / std::abs (lambda); - // Probe magnitudes - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - R lambda1 = cos (fi); - R mu1 = sin (fi); - R lmnr = std::pow (std::pow (std::abs (lambda1), p) + - std::pow (std::abs (mu1), p), 1/p); - lambda1 /= lmnr; mu1 /= lmnr; - R nrm1 = vector_norm (lambda1 * lamcu * y + mu1 * col, p); - if (nrm1 > nrm) - { - lambda = lambda1 * lamcu; - mu = mu1; - nrm = nrm1; - } - } - R lama = std::abs (lambda); - // Probe orientation - for (octave_idx_type i = 0; i < nsamp; i++) - { - octave_quit (); - R fi = i * static_cast (M_PI) / nsamp; - lamcu = CR (cos (fi), sin (fi)); - R nrm1 = vector_norm (lama * lamcu * y + mu * col, p); - if (nrm1 > nrm) - { - lambda = lama * lamcu; - nrm = nrm1; - } - } -} + // Complex version. Higham's paper does not deal with complex case, so we + // use a simple extension. First, guess the magnitudes as in real version, + // then try to rotate lambda to improve further. + template + static void + higham_subp (const ColVectorT& y, const ColVectorT& col, + octave_idx_type nsamp, R p, + std::complex& lambda, std::complex& mu) + { + typedef std::complex CR; + R nrm = 0; + lambda = 1.0; + CR lamcu = lambda / std::abs (lambda); + // Probe magnitudes + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + R lambda1 = cos (fi); + R mu1 = sin (fi); + R lmnr = std::pow (std::pow (std::abs (lambda1), p) + + std::pow (std::abs (mu1), p), 1/p); + lambda1 /= lmnr; mu1 /= lmnr; + R nrm1 = vector_norm (lambda1 * lamcu * y + mu1 * col, p); + if (nrm1 > nrm) + { + lambda = lambda1 * lamcu; + mu = mu1; + nrm = nrm1; + } + } + R lama = std::abs (lambda); + // Probe orientation + for (octave_idx_type i = 0; i < nsamp; i++) + { + octave_quit (); + R fi = i * static_cast (M_PI) / nsamp; + lamcu = CR (cos (fi), sin (fi)); + R nrm1 = vector_norm (lama * lamcu * y + mu * col, p); + if (nrm1 > nrm) + { + lambda = lama * lamcu; + nrm = nrm1; + } + } + } -// the p-dual element (should work for both real and complex) -template -inline T elem_dual_p (T x, R p) -{ - return math::signum (x) * std::pow (std::abs (x), p-1); -} + // the p-dual element (should work for both real and complex) + template + inline T elem_dual_p (T x, R p) + { + return math::signum (x) * std::pow (std::abs (x), p-1); + } -// the VectorT is used for vectors, but actually it has to be -// a Matrix type to allow all the operations. For instance SparseMatrix -// does not support multiplication with column/row vectors. -// the dual vector -template -VectorT dual_p (const VectorT& x, R p, R q) -{ - VectorT res (x.dims ()); - for (octave_idx_type i = 0; i < x.numel (); i++) - res.xelem (i) = elem_dual_p (x(i), p); - return res / vector_norm (res, q); -} + // the VectorT is used for vectors, but actually it has to be + // a Matrix type to allow all the operations. For instance SparseMatrix + // does not support multiplication with column/row vectors. + // the dual vector + template + VectorT dual_p (const VectorT& x, R p, R q) + { + VectorT res (x.dims ()); + for (octave_idx_type i = 0; i < x.numel (); i++) + res.xelem (i) = elem_dual_p (x(i), p); + return res / vector_norm (res, q); + } -// Higham's hybrid method -template -R higham (const MatrixT& m, R p, R tol, int maxiter, - VectorT& x) -{ - x.resize (m.columns (), 1); - // the OSE part - VectorT y(m.rows (), 1, 0), z(m.rows (), 1); - typedef typename VectorT::element_type RR; - RR lambda = 0; - RR mu = 1; - for (octave_idx_type k = 0; k < m.columns (); k++) - { - octave_quit (); - VectorT col (m.column (k)); - if (k > 0) - higham_subp (y, col, 4*k, p, lambda, mu); - for (octave_idx_type i = 0; i < k; i++) - x(i) *= lambda; - x(k) = mu; - y = lambda * y + mu * col; - } - - // the PM part - x = x / vector_norm (x, p); - R q = p/(p-1); + // Higham's hybrid method + template + R higham (const MatrixT& m, R p, R tol, int maxiter, + VectorT& x) + { + x.resize (m.columns (), 1); + // the OSE part + VectorT y(m.rows (), 1, 0), z(m.rows (), 1); + typedef typename VectorT::element_type RR; + RR lambda = 0; + RR mu = 1; + for (octave_idx_type k = 0; k < m.columns (); k++) + { + octave_quit (); + VectorT col (m.column (k)); + if (k > 0) + higham_subp (y, col, 4*k, p, lambda, mu); + for (octave_idx_type i = 0; i < k; i++) + x(i) *= lambda; + x(k) = mu; + y = lambda * y + mu * col; + } - R gamma = 0, gamma1; - int iter = 0; - while (iter < maxiter) - { - octave_quit (); - y = m*x; - gamma1 = gamma; - gamma = vector_norm (y, p); - z = dual_p (y, p, q); - z = z.hermitian (); - z = z * m; + // the PM part + x = x / vector_norm (x, p); + R q = p/(p-1); - if (iter > 0 && (vector_norm (z, q) <= gamma - || (gamma - gamma1) <= tol*gamma)) - break; + R gamma = 0, gamma1; + int iter = 0; + while (iter < maxiter) + { + octave_quit (); + y = m*x; + gamma1 = gamma; + gamma = vector_norm (y, p); + z = dual_p (y, p, q); + z = z.hermitian (); + z = z * m; - z = z.hermitian (); - x = dual_p (z, q, p); - iter++; - } + if (iter > 0 && (vector_norm (z, q) <= gamma + || (gamma - gamma1) <= tol*gamma)) + break; - return gamma; -} + z = z.hermitian (); + x = dual_p (z, q, p); + iter++; + } -// derive column vector and SVD types + return gamma; + } -static const char *p_less1_gripe = "xnorm: p must be >= 1"; + // derive column vector and SVD types -// Static constant to control the maximum number of iterations. 100 seems to -// be a good value. Eventually, we can provide a means to change this -// constant from Octave. -static int max_norm_iter = 100; + static const char *p_less1_gripe = "xnorm: p must be >= 1"; -// version with SVD for dense matrices -template -R svd_matrix_norm (const MatrixT& m, R p, VectorT) -{ - // NOTE: The octave:: namespace tags are needed for the following - // function calls until the deprecated inline functions are removed - // from oct-norm.h. + // Static constant to control the maximum number of iterations. 100 seems to + // be a good value. Eventually, we can provide a means to change this + // constant from Octave. + static int max_norm_iter = 100; - R res = 0; - if (p == 2) - { - math::svd fact (m, math::svd::Type::sigma_only); - res = fact.singular_values () (0, 0); - } - else if (p == 1) - res = octave::xcolnorms (m, static_cast (1)).max (); - else if (lo_ieee_isinf (p) && p > 1) - res = octave::xrownorms (m, static_cast (1)).max (); - else if (p > 1) - { - VectorT x; - const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); - res = higham (m, p, sqrteps, max_norm_iter, x); - } - else - (*current_liboctave_error_handler) ("%s", p_less1_gripe); - - return res; -} + // version with SVD for dense matrices + template + R svd_matrix_norm (const MatrixT& m, R p, VectorT) + { + R res = 0; + if (p == 2) + { + math::svd fact (m, math::svd::Type::sigma_only); + res = fact.singular_values () (0, 0); + } + else if (p == 1) + res = xcolnorms (m, static_cast (1)).max (); + else if (lo_ieee_isinf (p) && p > 1) + res = xrownorms (m, static_cast (1)).max (); + else if (p > 1) + { + VectorT x; + const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); + res = higham (m, p, sqrteps, max_norm_iter, x); + } + else + (*current_liboctave_error_handler) ("%s", p_less1_gripe); -// SVD-free version for sparse matrices -template -R matrix_norm (const MatrixT& m, R p, VectorT) -{ - // NOTE: The octave:: namespace tags are needed for the following - // function calls until the deprecated inline functions are removed - // from oct-norm.h. + return res; + } - R res = 0; - if (p == 1) - res = octave::xcolnorms (m, static_cast (1)).max (); - else if (lo_ieee_isinf (p) && p > 1) - res = octave::xrownorms (m, static_cast (1)).max (); - else if (p > 1) - { - VectorT x; - const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); - res = higham (m, p, sqrteps, max_norm_iter, x); - } - else - (*current_liboctave_error_handler) ("%s", p_less1_gripe); + // SVD-free version for sparse matrices + template + R matrix_norm (const MatrixT& m, R p, VectorT) + { + R res = 0; + if (p == 1) + res = xcolnorms (m, static_cast (1)).max (); + else if (lo_ieee_isinf (p) && p > 1) + res = xrownorms (m, static_cast (1)).max (); + else if (p > 1) + { + VectorT x; + const R sqrteps = std::sqrt (std::numeric_limits::epsilon ()); + res = higham (m, p, sqrteps, max_norm_iter, x); + } + else + (*current_liboctave_error_handler) ("%s", p_less1_gripe); - return res; -} + return res; + } -// and finally, here's what we've promised in the header file + // and finally, here's what we've promised in the header file #define DEFINE_XNORM_FCNS(PREFIX, RTYPE) \ RTYPE xnorm (const PREFIX##ColumnVector& x, RTYPE p) \ @@ -582,21 +574,21 @@ return vector_norm (x, static_cast (2)); \ } -DEFINE_XNORM_FCNS(, double) -DEFINE_XNORM_FCNS(Complex, double) -DEFINE_XNORM_FCNS(Float, float) -DEFINE_XNORM_FCNS(FloatComplex, float) + DEFINE_XNORM_FCNS(, double) + DEFINE_XNORM_FCNS(Complex, double) + DEFINE_XNORM_FCNS(Float, float) + DEFINE_XNORM_FCNS(FloatComplex, float) -// this is needed to avoid copying the sparse matrix for xfrobnorm -template -inline void array_norm_2 (const T *v, octave_idx_type n, R& res) -{ - norm_accumulator_2 acc; - for (octave_idx_type i = 0; i < n; i++) - acc.accum (v[i]); + // this is needed to avoid copying the sparse matrix for xfrobnorm + template + inline void array_norm_2 (const T *v, octave_idx_type n, R& res) + { + norm_accumulator_2 acc; + for (octave_idx_type i = 0; i < n; i++) + acc.accum (v[i]); - res = acc; -} + res = acc; + } #define DEFINE_XNORM_SPARSE_FCNS(PREFIX, RTYPE) \ RTYPE xnorm (const Sparse##PREFIX##Matrix& x, RTYPE p) \ @@ -610,8 +602,8 @@ return res; \ } -DEFINE_XNORM_SPARSE_FCNS(, double) -DEFINE_XNORM_SPARSE_FCNS(Complex, double) + DEFINE_XNORM_SPARSE_FCNS(, double) + DEFINE_XNORM_SPARSE_FCNS(Complex, double) #define DEFINE_COLROW_NORM_FCNS(PREFIX, RPREFIX, RTYPE) \ RPREFIX##RowVector \ @@ -625,12 +617,12 @@ return row_norms (m, p); \ } \ -DEFINE_COLROW_NORM_FCNS(,, double) -DEFINE_COLROW_NORM_FCNS(Complex,, double) -DEFINE_COLROW_NORM_FCNS(Float, Float, float) -DEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float) + DEFINE_COLROW_NORM_FCNS(, , double) + DEFINE_COLROW_NORM_FCNS(Complex, , double) + DEFINE_COLROW_NORM_FCNS(Float, Float, float) + DEFINE_COLROW_NORM_FCNS(FloatComplex, Float, float) -DEFINE_COLROW_NORM_FCNS(Sparse,, double) -DEFINE_COLROW_NORM_FCNS(SparseComplex,, double) + DEFINE_COLROW_NORM_FCNS(Sparse, , double) + DEFINE_COLROW_NORM_FCNS(SparseComplex, , double) OCTAVE_END_NAMESPACE(octave) diff -r 9089bd969b37 -r bd9da634f00d liboctave/numeric/oct-norm.h --- a/liboctave/numeric/oct-norm.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/numeric/oct-norm.h Tue Dec 06 15:17:16 2022 -0500 @@ -32,14 +32,6 @@ #include "oct-cmplx.h" -// The remaining includes can be removed when the deprecated functions -// at the end of this file are removed. - -#include "dColVector.h" -#include "dRowVector.h" -#include "fColVector.h" -#include "fRowVector.h" - OCTAVE_BEGIN_NAMESPACE(octave) extern OCTAVE_API double xnorm (const ColumnVector&, double p = 2); @@ -88,198 +80,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ColumnVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const RowVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const Matrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const Matrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexColumnVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexRowVector& v, double p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const ComplexMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const ComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatColumnVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatRowVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatMatrix& m, float p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline float xfrobnorm (const FloatMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexColumnVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexRowVector& v, float p = 2) -{ - return octave::xnorm (v, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline float xnorm (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline float xfrobnorm (const FloatComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const SparseMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const SparseMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xnorm' instead") -inline double xnorm (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xnorm (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xfrobnorm' instead") -inline double xfrobnorm (const SparseComplexMatrix& m) -{ - return octave::xfrobnorm (m); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const Matrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const Matrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const ComplexMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const ComplexMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline FloatRowVector xcolnorms (const FloatMatrix& m, float p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline FloatColumnVector xrownorms (const FloatMatrix& m, float p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline FloatRowVector xcolnorms (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline FloatColumnVector xrownorms (const FloatComplexMatrix& m, float p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const SparseMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const SparseMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xcolnorms' instead") -inline RowVector xcolnorms (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xcolnorms (m, p); -} - -OCTAVE_DEPRECATED (7, "use 'octave::xrownorms' instead") -inline ColumnVector xrownorms (const SparseComplexMatrix& m, double p = 2) -{ - return octave::xrownorms (m, p); -} #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/numeric/oct-spparms.h --- a/liboctave/numeric/oct-spparms.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/numeric/oct-spparms.h Tue Dec 06 15:17:16 2022 -0500 @@ -116,9 +116,4 @@ OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -OCTAVE_DEPRECATED (7, "use 'octave::sparse_params' instead") -typedef octave::sparse_params octave_sparse_params; #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/util/lo-ieee.h --- a/liboctave/util/lo-ieee.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/util/lo-ieee.h Tue Dec 06 15:17:16 2022 -0500 @@ -156,17 +156,4 @@ #endif -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) - -OCTAVE_DEPRECATED (7, "use '__lo_ieee_isfinite' instead") -inline int __lo_ieee_finite (double x) { return __lo_ieee_isfinite (x); } - -OCTAVE_DEPRECATED (7, "use '__lo_ieee_float_isfinite' instead") -inline int __lo_ieee_float_finite (float x) -{ return __lo_ieee_float_isfinite (x); } - -#define lo_ieee_finite(x) lo_ieee_isfinite(x) - #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d liboctave/util/lo-utils.cc --- a/liboctave/util/lo-utils.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/util/lo-utils.cc Tue Dec 06 15:17:16 2022 -0500 @@ -47,473 +47,479 @@ OCTAVE_BEGIN_NAMESPACE(octave) -bool is_int_or_inf_or_nan (double x) -{ - return math::isnan (x) || math::x_nint (x) == x; -} + bool is_int_or_inf_or_nan (double x) + { + return math::isnan (x) || math::x_nint (x) == x; + } + + bool too_large_for_float (double x) + { + return (math::isfinite (x) + && fabs (x) > std::numeric_limits::max ()); + } + + bool too_large_for_float (const Complex& x) + { + return (too_large_for_float (x.real ()) + || too_large_for_float (x.imag ())); + } + + bool is_int_or_inf_or_nan (float x) + { + return math::isnan (x) || math::x_nint (x) == x; + } -bool too_large_for_float (double x) -{ - return (math::isfinite (x) - && fabs (x) > std::numeric_limits::max ()); -} + // Save a string. + + char * strsave (const char *s) + { + if (! s) + return nullptr; -bool too_large_for_float (const Complex& x) -{ - return (too_large_for_float (x.real ()) - || too_large_for_float (x.imag ())); -} + int len = strlen (s); + char *tmp = new char [len+1]; + tmp = strcpy (tmp, s); + return tmp; + } + + std::string fgets (FILE *f) + { + bool eof; + return fgets (f, eof); + } + + std::string fgets (FILE *f, bool& eof) + { + eof = false; + + std::string retval; -bool is_int_or_inf_or_nan (float x) -{ - return math::isnan (x) || math::x_nint (x) == x; -} + int grow_size = 1024; + int max_size = grow_size; + + char *buf = static_cast (std::malloc (max_size)); + if (! buf) + (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); -// Save a string. + char *bufptr = buf; + int len = 0; -char * strsave (const char *s) -{ - if (! s) - return nullptr; + do + { + if (std::fgets (bufptr, grow_size, f)) + { + len = strlen (bufptr); - int len = strlen (s); - char *tmp = new char [len+1]; - tmp = strcpy (tmp, s); - return tmp; -} + if (len == grow_size - 1) + { + int tmp = bufptr - buf + grow_size - 1; + grow_size *= 2; + max_size += grow_size; + auto tmpbuf = static_cast (std::realloc (buf, max_size)); + if (! tmpbuf) + { + free (buf); + (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); + } + buf = tmpbuf; + bufptr = buf + tmp; -std::string fgets (FILE *f) -{ - bool eof; - return fgets (f, eof); -} + if (*(bufptr-1) == '\n') + { + *bufptr = '\0'; + retval = buf; + } + } + else if (bufptr[len-1] != '\n') + { + bufptr[len++] = '\n'; + bufptr[len] = '\0'; + retval = buf; + } + else + retval = buf; + } + else + { + if (len == 0) + { + eof = true; -std::string fgets (FILE *f, bool& eof) -{ - eof = false; + free (buf); + + buf = nullptr; + } + + break; + } + } + while (retval.empty ()); + + free (buf); + + octave_quit (); - std::string retval; + return retval; + } - int grow_size = 1024; - int max_size = grow_size; + std::string fgetl (FILE *f) + { + bool eof; + return fgetl (f, eof); + } + + std::string fgetl (FILE *f, bool& eof) + { + std::string retval = fgets (f, eof); + + if (! retval.empty () && retval.back () == '\n') + retval.pop_back (); - char *buf = static_cast (std::malloc (max_size)); - if (! buf) - (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); + return retval; + } + + template + T + read_value (std::istream& is) + { + T retval; + is >> retval; + return retval; + } - char *bufptr = buf; - int len = 0; + template OCTAVE_API bool read_value (std::istream& is); + template OCTAVE_API octave_int8 read_value (std::istream& is); + template OCTAVE_API octave_int16 read_value (std::istream& is); + template OCTAVE_API octave_int32 read_value (std::istream& is); + template OCTAVE_API octave_int64 read_value (std::istream& is); + template OCTAVE_API octave_uint8 read_value (std::istream& is); + template OCTAVE_API octave_uint16 read_value (std::istream& is); + template OCTAVE_API octave_uint32 read_value (std::istream& is); + template OCTAVE_API octave_uint64 read_value (std::istream& is); - do - { - if (std::fgets (bufptr, grow_size, f)) + // Note that the caller is responsible for repositioning the stream on + // failure. + + template + T + read_inf_nan_na (std::istream& is, char c0) + { + T val = 0.0; + + switch (c0) + { + case 'i': case 'I': { - len = strlen (bufptr); - - if (len == grow_size - 1) + char c1 = is.get (); + if (c1 == 'n' || c1 == 'N') { - int tmp = bufptr - buf + grow_size - 1; - grow_size *= 2; - max_size += grow_size; - auto tmpbuf = static_cast (std::realloc (buf, max_size)); - if (! tmpbuf) + char c2 = is.get (); + if (c2 == 'f' || c2 == 'F') { - free (buf); - (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); + val = std::numeric_limits::infinity (); + is.peek (); // Potentially set EOF bit } - buf = tmpbuf; - bufptr = buf + tmp; + else + is.setstate (std::ios::failbit); + } + else + is.setstate (std::ios::failbit); + } + break; - if (*(bufptr-1) == '\n') + case 'n': case 'N': + { + char c1 = is.get (); + if (c1 == 'a' || c1 == 'A') + { + char c2 = is.get (); + if (c2 == 'n' || c2 == 'N') { - *bufptr = '\0'; - retval = buf; + val = std::numeric_limits::quiet_NaN (); + is.peek (); // Potentially set EOF bit + } + else + { + val = numeric_limits::NA (); + if (c2 != std::istream::traits_type::eof ()) + is.putback (c2); + else + is.clear (is.rdstate () & ~std::ios::failbit); } } - else if (bufptr[len-1] != '\n') - { - bufptr[len++] = '\n'; - bufptr[len] = '\0'; - retval = buf; - } else - retval = buf; + is.setstate (std::ios::failbit); } - else + break; + + default: + (*current_liboctave_error_handler) + ("read_inf_nan_na: invalid character '%c'", c0); + } + + return val; + } + + // Read a double value. Discard any sign on NaN and NA. + + template + double + read_fp_value (std::istream& is) + { + T val = 0.0; + + // FIXME: resetting stream position is likely to fail unless we are + // reading from a file. + std::streampos pos = is.tellg (); + + is >> std::ws; // skip through whitespace and advance stream pointer + + bool neg = false; + char c1 = is.get (); + switch (c1) + { + case '-': + neg = true; + OCTAVE_FALLTHROUGH; + + case '+': { - if (len == 0) + char c2 = 0; + c2 = is.get (); + if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') + val = read_inf_nan_na (is, c2); + else if (isspace (c2)) + is.setstate (std::ios::failbit); + else { - eof = true; - - free (buf); - - buf = nullptr; + is.putback (c2); + is >> val; } - break; + if (neg && ! math::isnan (val) && ! is.fail ()) + val = -val; } - } - while (retval.empty ()); - - free (buf); - - octave_quit (); - - return retval; -} + break; -std::string fgetl (FILE *f) -{ - bool eof; - return fgetl (f, eof); -} + case 'i': case 'I': + case 'n': case 'N': + val = read_inf_nan_na (is, c1); + break; -std::string fgetl (FILE *f, bool& eof) -{ - std::string retval = fgets (f, eof); - - if (! retval.empty () && retval.back () == '\n') - retval.pop_back (); - - return retval; -} + default: + is.putback (c1); + is >> val; + break; + } -template -T -read_value (std::istream& is) -{ - T retval; - is >> retval; - return retval; -} + std::ios::iostate status = is.rdstate (); + if (status & std::ios::failbit) + { + // Convert MAX_VAL returned by C++ streams for very large numbers to Inf + if (val == std::numeric_limits::max ()) + { + if (neg) + val = -std::numeric_limits::infinity (); + else + val = std::numeric_limits::infinity (); + is.clear (status & ~std::ios::failbit); + } + else + { + // True error. + // Reset stream to original position, clear eof bit, pass status on. + is.clear (); + is.seekg (pos); + is.setstate (status & ~std::ios_base::eofbit); + } + } -template OCTAVE_API bool read_value (std::istream& is); -template OCTAVE_API octave_int8 read_value (std::istream& is); -template OCTAVE_API octave_int16 read_value (std::istream& is); -template OCTAVE_API octave_int32 read_value (std::istream& is); -template OCTAVE_API octave_int64 read_value (std::istream& is); -template OCTAVE_API octave_uint8 read_value (std::istream& is); -template OCTAVE_API octave_uint16 read_value (std::istream& is); -template OCTAVE_API octave_uint32 read_value (std::istream& is); -template OCTAVE_API octave_uint64 read_value (std::istream& is); + return val; + } -// Note that the caller is responsible for repositioning the stream on -// failure. + template + std::complex + read_cx_fp_value (std::istream& is) + { + T re = 0.0; + T im = 0.0; -template -T -read_inf_nan_na (std::istream& is, char c0) -{ - T val = 0.0; + std::complex cx = 0.0; + + char ch = ' '; - switch (c0) - { - case 'i': case 'I': + while (isspace (ch)) + ch = is.get (); + + if (ch == '(') { - char c1 = is.get (); - if (c1 == 'n' || c1 == 'N') + re = read_value (is); + ch = is.get (); + + if (ch == ',') { - char c2 = is.get (); - if (c2 == 'f' || c2 == 'F') - val = std::numeric_limits::infinity (); + im = read_value (is); + ch = is.get (); + + if (ch == ')') + cx = std::complex (re, im); else is.setstate (std::ios::failbit); } - else - is.setstate (std::ios::failbit); - } - break; - - case 'n': case 'N': - { - char c1 = is.get (); - if (c1 == 'a' || c1 == 'A') - { - char c2 = is.get (); - if (c2 == 'n' || c2 == 'N') - val = std::numeric_limits::quiet_NaN (); - else - { - val = numeric_limits::NA (); - if (c2 != std::istream::traits_type::eof ()) - is.putback (c2); - else - is.clear (is.rdstate () & ~std::ios::failbit); - } - } + else if (ch == ')') + cx = re; else is.setstate (std::ios::failbit); } - break; - - default: - (*current_liboctave_error_handler) - ("read_inf_nan_na: invalid character '%c'", c0); - } - - return val; -} - -// Read a double value. Discard any sign on NaN and NA. - -template -double -read_fp_value (std::istream& is) -{ - T val = 0.0; - - // FIXME: resetting stream position is likely to fail unless we are - // reading from a file. - std::streampos pos = is.tellg (); - - char c1 = ' '; + else + { + is.putback (ch); + cx = read_value (is); + } - while (isspace (c1)) - c1 = is.get (); - - bool neg = false; - - switch (c1) - { - case '-': - neg = true; - OCTAVE_FALLTHROUGH; + return cx; + } - case '+': - { - char c2 = 0; - c2 = is.get (); - if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - val = read_inf_nan_na (is, c2); - else - { - is.putback (c2); - is >> val; - } + // FIXME: Could we use traits and enable_if to avoid duplication in the + // following specializations? - if (neg && ! is.fail ()) - val = -val; - } - break; + template <> OCTAVE_API double read_value (std::istream& is) + { + return read_fp_value (is); + } - case 'i': case 'I': - case 'n': case 'N': - val = read_inf_nan_na (is, c1); - break; + template <> OCTAVE_API Complex read_value (std::istream& is) + { + return read_cx_fp_value (is); + } - default: - is.putback (c1); - is >> val; - break; - } + template <> OCTAVE_API float read_value (std::istream& is) + { + return read_fp_value (is); + } - std::ios::iostate status = is.rdstate (); - if (status & std::ios::failbit) - { - // Convert MAX_VAL returned by C++ streams for very large numbers to Inf - if (val == std::numeric_limits::max ()) - { - if (neg) - val = -std::numeric_limits::infinity (); - else - val = std::numeric_limits::infinity (); - is.clear (status & ~std::ios::failbit); - } - else - { - // True error. Reset stream to original position and pass status on. - is.clear (); - is.seekg (pos); - is.setstate (status); - } - } - - return val; -} + template <> OCTAVE_API FloatComplex read_value (std::istream& is) + { + return read_cx_fp_value (is); + } -template -std::complex -read_cx_fp_value (std::istream& is) -{ - T re = 0.0; - T im = 0.0; - - std::complex cx = 0.0; - - char ch = ' '; - - while (isspace (ch)) - ch = is.get (); - - if (ch == '(') - { - re = read_value (is); - ch = is.get (); - - if (ch == ',') - { - im = read_value (is); - ch = is.get (); + template + void + write_value (std::ostream& os, const T& value) + { + os << value; + } - if (ch == ')') - cx = std::complex (re, im); - else - is.setstate (std::ios::failbit); - } - else if (ch == ')') - cx = re; - else - is.setstate (std::ios::failbit); - } - else - { - is.putback (ch); - cx = read_value (is); - } - - return cx; -} - -// FIXME: Could we use traits and enable_if to avoid duplication in the -// following specializations? + template OCTAVE_API void + write_value (std::ostream& os, const bool& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int8& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int16& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int32& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_int64& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint8& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint16& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint32& value); + template OCTAVE_API void + write_value (std::ostream& os, const octave_uint64& value); -template <> OCTAVE_API double read_value (std::istream& is) -{ - return read_fp_value (is); -} - -template <> OCTAVE_API Complex read_value (std::istream& is) -{ - return read_cx_fp_value (is); -} + // Note: precision is supposed to be managed outside of this function by + // setting stream parameters. -template <> OCTAVE_API float read_value (std::istream& is) -{ - return read_fp_value (is); -} - -template <> OCTAVE_API FloatComplex read_value (std::istream& is) -{ - return read_cx_fp_value (is); -} - -template -void -write_value (std::ostream& os, const T& value) -{ - os << value; -} + template <> OCTAVE_API void + write_value (std::ostream& os, const double& value) + { + if (lo_ieee_is_NA (value)) + os << "NA"; + else if (lo_ieee_isnan (value)) + os << "NaN"; + else if (lo_ieee_isinf (value)) + os << (value < 0 ? "-Inf" : "Inf"); + else + os << value; + } -template OCTAVE_API void -write_value (std::ostream& os, const bool& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int8& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int16& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int32& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_int64& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint8& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint16& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint32& value); -template OCTAVE_API void -write_value (std::ostream& os, const octave_uint64& value); + template <> OCTAVE_API void + write_value (std::ostream& os, const Complex& value) + { + os << '('; + write_value (os, real (value)); + os << ','; + write_value (os, imag (value)); + os << ')'; + } -// Note: precision is supposed to be managed outside of this function by -// setting stream parameters. - -template <> OCTAVE_API void -write_value (std::ostream& os, const double& value) -{ - if (lo_ieee_is_NA (value)) - os << "NA"; - else if (lo_ieee_isnan (value)) - os << "NaN"; - else if (lo_ieee_isinf (value)) - os << (value < 0 ? "-Inf" : "Inf"); - else - os << value; -} + // Note: precision is supposed to be managed outside of this function by + // setting stream parameters. -template <> OCTAVE_API void -write_value (std::ostream& os, const Complex& value) -{ - os << '('; - write_value (os, real (value)); - os << ','; - write_value (os, imag (value)); - os << ')'; -} - -// Note: precision is supposed to be managed outside of this function by -// setting stream parameters. + template <> OCTAVE_API void + write_value (std::ostream& os, const float& value) + { + if (lo_ieee_is_NA (value)) + os << "NA"; + else if (lo_ieee_isnan (value)) + os << "NaN"; + else if (lo_ieee_isinf (value)) + os << (value < 0 ? "-Inf" : "Inf"); + else + os << value; + } -template <> OCTAVE_API void -write_value (std::ostream& os, const float& value) -{ - if (lo_ieee_is_NA (value)) - os << "NA"; - else if (lo_ieee_isnan (value)) - os << "NaN"; - else if (lo_ieee_isinf (value)) - os << (value < 0 ? "-Inf" : "Inf"); - else - os << value; -} - -template <> OCTAVE_API void -write_value (std::ostream& os, const FloatComplex& value) -{ - os << '('; - write_value (os, real (value)); - os << ','; - write_value (os, imag (value)); - os << ')'; -} + template <> OCTAVE_API void + write_value (std::ostream& os, const FloatComplex& value) + { + os << '('; + write_value (os, real (value)); + os << ','; + write_value (os, imag (value)); + os << ')'; + } OCTAVE_BEGIN_NAMESPACE(math) -bool int_multiply_overflow (int a, int b, int *r) -{ - return octave_i_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (int a, int b, int *r) + { + return octave_i_multiply_overflow_wrapper (a, b, r); + } -bool int_multiply_overflow (long int a, long int b, long int *r) -{ - return octave_li_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (long int a, long int b, long int *r) + { + return octave_li_multiply_overflow_wrapper (a, b, r); + } #if defined (OCTAVE_HAVE_LONG_LONG_INT) -bool int_multiply_overflow (long long int a, long long int b, - long long int *r) -{ - return octave_lli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (long long int a, long long int b, + long long int *r) + { + return octave_lli_multiply_overflow_wrapper (a, b, r); + } #endif -bool int_multiply_overflow (unsigned int a, unsigned int b, - unsigned int *r) -{ - return octave_ui_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned int a, unsigned int b, + unsigned int *r) + { + return octave_ui_multiply_overflow_wrapper (a, b, r); + } -bool int_multiply_overflow (unsigned long int a, unsigned long int b, - unsigned long int *r) -{ - return octave_uli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned long int a, unsigned long int b, + unsigned long int *r) + { + return octave_uli_multiply_overflow_wrapper (a, b, r); + } #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) -bool int_multiply_overflow (unsigned long long int a, - unsigned long long int b, - unsigned long long int *r) -{ - return octave_ulli_multiply_overflow_wrapper (a, b, r); -} + bool int_multiply_overflow (unsigned long long int a, + unsigned long long int b, + unsigned long long int *r) + { + return octave_ulli_multiply_overflow_wrapper (a, b, r); + } #endif OCTAVE_END_NAMESPACE(math) diff -r 9089bd969b37 -r bd9da634f00d liboctave/util/lo-utils.h --- a/liboctave/util/lo-utils.h Tue Dec 06 14:23:21 2022 -0500 +++ b/liboctave/util/lo-utils.h Tue Dec 06 15:17:16 2022 -0500 @@ -137,146 +137,4 @@ OCTAVE_END_NAMESPACE(math) OCTAVE_END_NAMESPACE(octave) -#if defined (OCTAVE_PROVIDE_DEPRECATED_SYMBOLS) -template -OCTAVE_DEPRECATED (7, "use 'octave::any_all_test' instead") -bool -any_all_test (F fcn, const T *m, octave_idx_type len) -{ - return octave::any_all_test (fcn, m, len); -} - -OCTAVE_DEPRECATED (7, "use 'octave::is_int_or_inf_or_nan' instead") -inline bool xis_int_or_inf_or_nan (double x) -{ - return octave::is_int_or_inf_or_nan (x); -} - -template -OCTAVE_DEPRECATED (7, "use 'octave::is_one_or_zero' instead") -bool -xis_one_or_zero (const T& x) -{ - return octave::is_one_or_zero (x); -} - -template -OCTAVE_DEPRECATED (7, "use 'octave::is_zero' instead") -bool -xis_zero (const T& x) -{ - return octave::is_zero (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (double x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (const Complex& x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xis_int_or_inf_or_nan (float x) -{ - return octave::is_int_or_inf_or_nan (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::' instead") -inline bool xtoo_large_for_float (float x) -{ - return octave::too_large_for_float (x); -} - -OCTAVE_DEPRECATED (7, "use 'octave::strsave' instead") -inline char * strsave (const char *s) -{ - return octave::strsave (s); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead") -inline std::string octave_fgets (std::FILE *f) -{ - return octave::fgets (f); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead") -inline std::string octave_fgetl (std::FILE *f) -{ - return octave::fgetl (f); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgets' instead") -inline std::string octave_fgets (std::FILE *f, bool& eof) -{ - return octave::fgets (f, eof); -} - -OCTAVE_DEPRECATED (7, "use 'octave::fgetl' instead") -inline std::string octave_fgetl (std::FILE *f, bool& eof) -{ - return octave::fgetl (f, eof); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline double -octave_read_double (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline Complex -octave_read_complex (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline float -octave_read_float (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::read_value' instead") -inline FloatComplex -octave_read_float_complex (std::istream& is) -{ - return octave::read_value (is); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_double (std::ostream& os, double value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_complex (std::ostream& os, const Complex& value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_float (std::ostream& os, float value) -{ - octave::write_value (os, value); -} - -OCTAVE_DEPRECATED (7, "use 'octave::write_value' instead") -inline void -octave_write_float_complex (std::ostream& os, const FloatComplex& value) -{ - octave::write_value (os, value); -} #endif - -#endif diff -r 9089bd969b37 -r bd9da634f00d oct-conf-post-public.in.h --- a/oct-conf-post-public.in.h Tue Dec 06 14:23:21 2022 -0500 +++ b/oct-conf-post-public.in.h Tue Dec 06 15:17:16 2022 -0500 @@ -39,7 +39,7 @@ OCTAVE_ATTRIBUTE_NAME in place of vendor specific attribute mechanisms. As compilers evolve, the underlying implementation can be changed with the macro definitions below. FIXME: Update macros - to use C++ standard attribute syntax when Octave moves to C++ 2011 + to use C++ standard attribute syntax when Octave moves to C++ 2014 standard. */ #if defined (__GNUC__) diff -r 9089bd969b37 -r bd9da634f00d scripts/deprecated/disable_diagonal_matrix.m --- a/scripts/deprecated/disable_diagonal_matrix.m Tue Dec 06 14:23:21 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## 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 -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_diagonal_matrix () -## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_diagonal_matrix (@var{new_val}, "local") -## -## @code{disable_diagonal_matrix} is deprecated and will be removed in Octave -## version 9. Use @code{optimize_diagonal_matrix} instead. -## -## Query or set whether storing diagonal matrices in a special space-efficient -## format is disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_diagonal_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_diagonal_matrix is obsolete and will be removed from a future version of Octave, please use optimize_diagonal_matrix instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_diagonal_matrix (); - elseif (nargout == 0) - optimize_diagonal_matrix (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_diagonal_matrix (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 9089bd969b37 -r bd9da634f00d scripts/deprecated/disable_permutation_matrix.m --- a/scripts/deprecated/disable_permutation_matrix.m Tue Dec 06 14:23:21 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## 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 -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_permutation_matrix () -## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_permutation_matrix (@var{new_val}, "local") -## -## @code{disable_permutation_matrix} is deprecated and will be removed in -## Octave version 9. Use @code{optimize_permutation_matrix} instead. -## -## Query or set whether storing permutation matrices in a special -## space-efficient format is disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_permutation_matrix (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_permutation_matrix is obsolete and will be removed from a future version of Octave, please use optimize_permutation_matrix instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_permutation_matrix (); - elseif (nargout == 0) - optimize_permutation_matrix (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_permutation_matrix (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 9089bd969b37 -r bd9da634f00d scripts/deprecated/disable_range.m --- a/scripts/deprecated/disable_range.m Tue Dec 06 14:23:21 2022 -0500 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -######################################################################## -## -## Copyright (C) 2021-2022 The Octave Project Developers -## -## See the file COPYRIGHT.md in the top-level directory of this -## distribution or . -## -## 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 -## . -## -######################################################################## - -## -*- texinfo -*- -## @deftypefn {} {@var{val} =} disable_range () -## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val}) -## @deftypefnx {} {@var{old_val} =} disable_range (@var{new_val}, "local") -## -## @code{disable_range} is deprecated and will be removed in Octave version 9. -## Use @code{optimize_range} instead. -## -## Query or set whether storing ranges in a special space-efficient format is -## disabled. -## -## The default value is false. If this option is set to true, Octave will -## store ranges as full matrices. -## -## When called from inside a function with the @qcode{"local"} option, the -## setting is changed locally for the function and any subroutines it calls. -## The original setting is restored when exiting the function. -## @seealso{disable_diagonal_matrix, disable_permutation_matrix} -## @end deftypefn - -## FIXME: DEPRECATED: Remove in version 9. - -function retval = disable_range (varargin) - - persistent warned = false; - if (! warned) - warned = true; - warning ("Octave:deprecated-function", - "disable_range is obsolete and will be removed from a future version of Octave, please use optimize_range instead\n"); - endif - - if (nargin == 0) - retval = ! optimize_range (); - elseif (nargout == 0) - optimize_range (! varargin{1}, varargin{2:end}); - else - retval = ! optimize_range (! varargin{1}, varargin{2:end}); - endif - -endfunction diff -r 9089bd969b37 -r bd9da634f00d scripts/deprecated/module.mk --- a/scripts/deprecated/module.mk Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/deprecated/module.mk Tue Dec 06 15:17:16 2022 -0500 @@ -2,9 +2,6 @@ %canon_reldir%_FCN_FILES = \ %reldir%/.oct-config \ - %reldir%/disable_diagonal_matrix.m \ - %reldir%/disable_permutation_matrix.m \ - %reldir%/disable_range.m \ %reldir%/shift.m \ %reldir%/sparse_auto_mutate.m diff -r 9089bd969b37 -r bd9da634f00d scripts/geometry/tsearchn.m --- a/scripts/geometry/tsearchn.m Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/geometry/tsearchn.m Tue Dec 06 15:17:16 2022 -0500 @@ -26,15 +26,17 @@ ## -*- texinfo -*- ## @deftypefn {} {@var{idx} =} tsearchn (@var{x}, @var{t}, @var{xi}) ## @deftypefnx {} {[@var{idx}, @var{p}] =} tsearchn (@var{x}, @var{t}, @var{xi}) -## Search for the enclosing Delaunay convex hull. +## Find the simplexes enclosing the given points. ## -## For @code{@var{t} = delaunayn (@var{x})}, finds the index in @var{t} -## containing the points @var{xi}. For points outside the convex hull, -## @var{idx} is NaN. +## @code{tsearchn} is typically used with @code{delaunayn}: +## @code{@var{t} = delaunayn (@var{x})} returns a set of simplexes @code{t}, +## then @code{tsearchn} returns the row index of @var{t} containing each point +## of @var{xi}. For points outside the convex hull, @var{idx} is NaN. ## -## If requested @code{tsearchn} also returns the Barycentric coordinates -## @var{p} of the enclosing triangles. -## @seealso{delaunay, delaunayn} +## If requested, @code{tsearchn} also returns the barycentric coordinates +## @var{p} of the enclosing simplexes. +## +## @seealso{delaunay, delaunayn, tsearch} ## @end deftypefn function [idx, p] = tsearchn (x, t, xi) @@ -43,57 +45,53 @@ print_usage (); endif + if (columns (x) != columns (xi)) + error ("tsearchn: number of columns of X and XI must match"); + endif + + if (max (t(:)) > rows (x)) + error ("tsearchn: triangulation T must not access points outside X"); + endif + + if (nargout <= 1 && columns (x) == 2) # pass to the faster tsearch.cc + idx = tsearch (x(:,1), x(:,2), t, xi(:,1), xi(:,2)); + return; + endif + nt = rows (t); [m, n] = size (x); mi = rows (xi); idx = NaN (mi, 1); p = NaN (mi, n + 1); - ni = [1:mi].'; - for i = 1 : nt - ## Only calculate the Barycentric coordinates for points that have not - ## already been found in a triangle. - b = cart2bary (x (t (i, :), :), xi(ni,:)); - ## Our points xi are in the current triangle if - ## (all (b >= 0) && all (b <= 1)). However as we impose that - ## sum (b,2) == 1 we only need to test all(b>=0). Note need to add - ## a small margin for rounding errors - intri = all (b >= -1e-12, 2); - idx(ni(intri)) = i; - p(ni(intri),:) = b(intri, :); - ni(intri) = []; - endfor + for i = 1 : nt # each simplex in turn -endfunction - -function Beta = cart2bary (T, P) + T = x(t(i, :), :); # T is the current simplex + P = xi(ni, :); # P is the set of points left to calculate - ## Conversion of Cartesian to Barycentric coordinates. - ## Given a reference simplex in N dimensions represented by an - ## N+1-by-N matrix, an arbitrary point P in Cartesian coordinates, - ## represented by an N-by-1 column vector can be written as - ## - ## P = Beta * T - ## - ## Where Beta is an N+1 vector of the barycentric coordinates. A criteria - ## on Beta is that - ## - ## sum (Beta) == 1 - ## - ## and therefore we can write the above as - ## - ## P - T(end, :) = Beta(1:end-1) * (T(1:end-1,:) - ones (N,1) * T(end,:)) - ## - ## and then we can solve for Beta as - ## - ## Beta(1:end-1) = (P - T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:)) - ## Beta(end) = sum (Beta) - ## - ## Note code below is generalized for multiple values of P, one per row. - [M, N] = size (P); - Beta = (P - ones (M,1) * T(end,:)) / (T(1:end-1,:) - ones (N,1) * T(end,:)); - Beta (:,end+1) = 1 - sum (Beta, 2); + ## Convert to barycentric coords: these are used to express a point P + ## as P = Beta * T + ## where T is a simplex. + ## + ## If 0 <= Beta <= 1, then the linear combination is also convex, + ## and the point P is inside the simplex T, otherwise it is outside. + ## Since the equation system is underdetermined, we apply the constraint + ## sum (Beta) == 1 to make it unique up to scaling. + ## + ## Note that the code below is vectorized over P, one point per row. + + b = (P - T(end,:)) / (T(1:end-1,:) - T(end,:)); + b(:, end+1) = 1 - sum (b, 2); + + ## The points xi are inside the current simplex if + ## (all (b >= 0) && all (b <= 1)). As sum (b,2) == 1, we only need to + ## test all(b>=0). + inside = all (b >= -1e-12, 2); # -1e-12 instead of 0 for rounding errors + idx(ni(inside)) = i; + p(ni(inside), :) = b(inside, :); + ni = ni(! inside); + endfor endfunction @@ -121,3 +119,10 @@ %! [idx, p] = tsearchn (x,tri,[1,1]); %! assert (idx, NaN); %! assert (p, [NaN, NaN, NaN]); + +## Test input validation +%!error tsearchn () +%!error tsearchn (1) +%!error tsearchn (1, 2) +%!error tsearchn ([1,2], 3, 4) +%!error tsearchn (1, 2, 3) diff -r 9089bd969b37 -r bd9da634f00d scripts/linear-algebra/module.mk --- a/scripts/linear-algebra/module.mk Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/linear-algebra/module.mk Tue Dec 06 15:17:16 2022 -0500 @@ -35,6 +35,7 @@ %reldir%/rref.m \ %reldir%/subspace.m \ %reldir%/trace.m \ + %reldir%/tensorprod.m \ %reldir%/vech.m \ %reldir%/vecnorm.m diff -r 9089bd969b37 -r bd9da634f00d scripts/linear-algebra/tensorprod.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scripts/linear-algebra/tensorprod.m Tue Dec 06 15:17:16 2022 -0500 @@ -0,0 +1,437 @@ +######################################################################## +## +## Copyright (C) 2022 The Octave Project Developers +## +## See the file COPYRIGHT.md in the top-level directory of this +## distribution or . +## +## 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 +## . +## +######################################################################## + +## -*- texinfo -*- +## @deftypefn {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dimA}, @var{dimB}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @var{dim}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}) +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, "all") +## @deftypefnx {} {@var{C} =} tensorprod (@var{A}, @var{B}, @dots{}, "NumDimensionsA", @var{value}) +## Compute the tensor product between numeric tensors @var{A} and @var{B}. +## +## The dimensions of @var{A} and @var{B} that are contracted are defined by +## @var{dimA} and @var{dimB}, respectively. @var{dimA} and @var{dimB} are +## scalars or equal length vectors that define the dimensions to match up. +## The matched dimensions of @var{A} and @var{B} must have equal lengths. +## +## When @var{dim} is used, it is equivalent to @var{dimA} = @var{dimB} = +## @var{dim}. +## +## When no dimensions are specified, @var{dimA} = @var{dimB} = []. This +## computes the outer product between @var{A} and @var{B}. +## +## Using the "all" option results in the inner product between @var{A} and +## @var{B}. This requires size(@var{A}) == size(@var{B}). +## +## Use the property-value pair with the property name "NumDimensionsA" when +## @var{A} has trailing singleton dimensions that should be transfered to +## @var{C}. The specified @var{value} should be the total number of +## dimensions of @var{A}. +## +## Matlab Compatibility: Octave does not currently support the "name=value" +## syntax for the "NumDimensionsA" parameter. +## +## @seealso{kron, dot, mtimes} +## @end deftypefn + +function C = tensorprod (A, B, varargin) + + ## FIXME: shortcut code paths could be added for trivial cases, such as if + ## either A or B are a scalars, null, identity tensors, etc. + + if (nargin < 2 || nargin > 6) + print_usage (); + endif + + ## Check that A and B are single or double + if (! isfloat (A)) + error ("tensorprod: A must be a single or double precision array"); + endif + + if (! isfloat (B)) + error ("tensorprod: B must be a single or double precision array"); + endif + + ## Check for misplaced NumDimensionsA property + if (nargin > 2) + if (strcmpi (varargin{end}, "NumDimensionsA")) + error (["tensorprod: a value for the NumDimensionsA property must ", ... + "be provided"]); + elseif (strcmpi ( strtok (inputname (nargin, false)), "NumDimensionsA")) + ## FIXME: Add support for keyword=value syntax + error (["tensorprod: NumDimensionsA=ndimsA syntax is not yet ", ... + "supported in Octave - provide the value as a ", ... + "property-value pair"]); + endif + endif + + ## Check for NumDimensionsA property + if (nargin > 3) + if (strcmpi (varargin{end - 1}, "NumDimensionsA")) + if (! (isnumeric (varargin{end}) && isscalar (varargin{end}))) + error (["tensorprod: value for NumDimensionsA must be a ", ... + "numeric scalar"]); + elseif (varargin{end} < 1 || rem (varargin{end}, 1) != 0) + error (["tensorprod: value for NumDimensionsA must be a ", ... + "positive integer"]); + endif + NumDimensionsA = varargin{end}; + endif + endif + + existNumDimensionsA = exist ("NumDimensionsA"); + ndimargs = nargin - 2 - 2 * existNumDimensionsA; + + ## Set dimA and dimB + if (ndimargs == 0) + ## Calling without dimension arguments + dimA = []; + dimB = []; + elseif (ndimargs == 1) + ## Calling with dim or "all" option + if (isnumeric (varargin{1})) + if (! (isvector (varargin{1}) || isnull (varargin{1}))) + error ("tensorprod: dim must be a numeric vector of integers or []"); + endif + ## Calling with dim + dimA = transpose ([varargin{1}(:)]); + elseif (ischar (varargin{1})) + if (strcmpi (varargin{1}, "all")) + if (! size_equal (A, B)) + error (["tensorprod: size of A and B must be identical when ", ... + "using the 'all' option"]); + endif + else + error ("tensorprod: unknown option '%s'", varargin{1}); + endif + ## Calling with "all" option + dimA = 1:ndims(A); + else + error (["tensorprod: third argument must be a numeric vector of ", ... + "integers, [], or 'all'"]); + endif + dimB = dimA; + elseif (ndimargs == 2) + ## Calling with dimA and dimB + if (! (isnumeric (varargin{1}) && (isvector (varargin{1}) || ... + isnull (varargin{1})))) + error("tensorprod: dimA must be a numeric vector of integers or []"); + endif + + if (! (isnumeric (varargin{2}) && (isvector (varargin{2}) || ... + isnull (varargin{2})))) + error ("tensorprod: dimB must be a numeric vector of integers or []"); + endif + + if (length (varargin{1}) != length (varargin{2})) + error (["tensorprod: an equal number of dimensions must be ", ... + "matched for A and B"]); + endif + dimA = transpose ([varargin{1}(:)]); + dimB = transpose ([varargin{2}(:)]); + else + ## Something is wrong - try to find the error + for i = 1:ndimargs + if (ischar (varargin{i})) + if (strcmpi (varargin{i}, "NumDimensionsA")) + error ("tensorprod: misplaced 'NumDimensionsA' option"); + elseif (strcmpi (varargin{i}, "all")) + error ("tensorprod: misplaced 'all' option"); + else + error ("tensorprod: unknown option '%s'", varargin{i}); + endif + elseif (! isnumeric (varargin{i})) + error (["tensorprod: optional arguments must be numeric vectors ", ... + "of integers, [], 'all', or 'NumDimensionsA'"]); + endif + endfor + error ("tensorprod: too many dimension inputs given"); + endif + + ## Check that dimensions are positive integers ([] will also pass) + if (any ([dimA < 1, dimB < 1, (rem (dimA, 1) != 0), (rem (dimB, 1) != 0)])) + error ("tensorprod: dimension(s) must be positive integer(s)"); + endif + + ## Check that the length of matched dimensions are equal + if (any (size (A, dimA) != size (B, dimB))) + error (["tensorprod: matched dimension(s) of A and B must have the ", ... + "same length(s)"]); + endif + + ## Find size and ndims of A and B + ndimsA = max ([ndims(A), max(dimA)]); + sizeA = size (A, 1:ndimsA); + ndimsB = max ([ndims(B), max(dimB)]); + sizeB = size (B, 1:ndimsB); + + ## Take NumDimensionsA property into account + if (existNumDimensionsA) + if (NumDimensionsA < ndimsA) + if (ndimargs == 1) + error (["tensorprod: highest dimension of dim must be less than ", ... + "or equal to NumDimensionsA"]); + elseif (ndimargs == 2) + error (["tensorprod: highest dimension of dimA must be less ", ... + "than or equal to NumDimensionsA"]); + else + error (["tensorprod: NumDimensionsA cannot be smaller than the ", ... + "number of dimensions of A"]); + endif + elseif (NumDimensionsA > ndimsA) + sizeA = [sizeA, ones(1, NumDimensionsA - ndimsA)]; + ndimsA = NumDimensionsA; + endif + endif + + ## Interchange the dimension to sum over the end of A and the front of B + ## Prepare for A + remainDimA = setdiff (1:ndimsA, dimA); # Dimensions of A to keep + newDimOrderA = [remainDimA, dimA]; # New dim order [to_keep, to_contract] + newSizeA = [prod(sizeA(remainDimA)), prod(sizeA(dimA))]; # Temp. 2D size for A + remainSizeA = sizeA(remainDimA); # Contrib. to size of C from remaining A dims + + ## Prepare for B (See comments for A. Note that in principle, + ## prod (sizeB (dimB)) should always be equal to prod (sizeA (dimA)). May + ## be able to optimize further here. + remainDimB = setdiff (1:ndimsB, dimB); + newDimOrderB = [remainDimB, dimB]; + newSizeB = [prod(sizeB(remainDimB)), prod(sizeB(dimB))]; + remainSizeB = sizeB(remainDimB); + + ## Do reshaping into 2D array + newA = reshape (permute (A, newDimOrderA), newSizeA); + newB = reshape (permute (B, newDimOrderB), newSizeB); + + ## Compute + C = newA * transpose (newB); + + ## If not an inner product, reshape back to tensor + if (! isscalar (C)) + C = reshape (C, [remainSizeA, remainSizeB]); + endif + +endfunction + + +%!assert (tensorprod (2, 3), 6) +%!assert (tensorprod (2, 3, 1), 6) +%!assert (tensorprod (2, 3, 2), 6) +%!assert (tensorprod (2, 3, 10), 6) +%!assert (tensorprod (2, 3, [1 2]), 6) +%!assert (tensorprod (2, 3, [1 10]), 6) +%!assert (tensorprod (2, 3, []), 6) +%!assert (tensorprod (2, 3, 2, 1), 6) +%!assert (tensorprod (2, 3, [], []), 6) + +%!shared v1, v2, M1, M2, T +%! v1 = [1, 2]; +%! M1 = [1, 2; 3, 4]; +%! M2 = [1, 2; 3, 4; 5, 6]; +%! T = cat (3, M2, M2); + +%!assert (tensorprod (3, v1), reshape ([3, 6], [1, 1, 1, 2])); +%!assert (tensorprod (v1, 3), [3, 6]); +%!assert (tensorprod (v1, v1, "all"), 5); +%!assert (tensorprod (v1, v1), reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, 1), [1, 2; 2, 4]); +%!assert (tensorprod (v1, v1, 2), 5); +%!assert (tensorprod (v1, v1, 3), reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, 5), reshape ([1, 2, 2, 4], [1, 2, 1, 1, 1, 2])); + +%!assert (tensorprod (M1, v1), cat (4, [1,2;3,4], [2,4;6,8])) +%!assert (tensorprod (M1, v1'), cat (3, [1,2;3,4], [2,4;6,8])) +%!assert (tensorprod (v1, M1), reshape ([1 2 3 6 2 4 4 8], [1,2,2,2])) +%!assert (tensorprod (v1', M1), reshape ([1 2 3 6 2 4 4 8], [2,1,2,2])) +%!assert (tensorprod (M1, v1', 2, 1), [5; 11]) +%!assert (tensorprod (M1, v1', 4, 4), cat(4, M1, 2*M1)) +%!assert (tensorprod (M1, v1', [1, 3]), [7; 10]) +%!assert (tensorprod (M1, v1', [1, 3], [1, 3]), [7; 10]) +%!assert (tensorprod (M1, v1', [2, 3], [1, 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2; 3], [1; 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2; 3], [1, 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [2, 3], [1; 3]), [5; 11]) +%!assert (tensorprod (M1, v1', [], []), cat (3, M1, 2*M1)) +%!assert (tensorprod (M1, M1, "all"), 30) +%!assert (tensorprod (M1, M1, 1), [10, 14; 14, 20]) +%!assert (tensorprod (M1, M1, 2), [5, 11; 11, 25]) +%!assert (tensorprod (M1, M2, 2), [5, 11, 17; 11, 25, 39]) +%!assert (tensorprod (M1, M2, 1, 2), [7, 15, 23; 10, 22, 34]) +%!assert (tensorprod (M1, M2), reshape ([1,3,2,4,3,9,6,12,5,15,10,20,2,6,4, ... +%! 8,4,12,8,16,6,18,12,24], [2,2,3,2])) + +%!assert (tensorprod (T, M1), +%! reshape([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,2, ... +%! 6,10,4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24], +%! [3,2,2,2,2])) +%!assert (tensorprod (T, M1, 2), +%! cat (3, [5, 5; 11 11; 17, 17], [11, 11; 25, 25; 39, 39])) +%!assert (tensorprod (T, M2, 1), cat (3, [35, 35; 44, 44], [44, 44; 56, 56])) +%!assert (tensorprod (T, M2, 2), cat (3, [5, 5; 11, 11; 17, 17], +%! [11,11;25,25;39,39], [17, 17; 39, 39; 61, 61])) +%!assert (tensorprod (T, T, "all"), 182) +%!assert (tensorprod (T, T, 1), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,2,2])) +%!assert (tensorprod (T, T, 2), +%! reshape ([5,11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61,5, ... +%! 11,17,5,11,17,11,25,39,11,25,39,17,39,61,17,39,61], +%! [3,2,3,2])) +%!assert (tensorprod (T, T, 3), +%! reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ... +%! 20,8,16,24,8,24,40,16,32,48,12,36,60,24,48,72], [3,2,3,2])); +%!assert (tensorprod (T, T, 10), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ... +%! 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ... +%! 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ... +%! 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ... +%! 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ... +%! 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ... +%! 18,30,12,24,36,6,18,30,12,24,36], +%! [3,2,2,1,1,1,1,1,1,3,2,2])) +%!assert (tensorprod (T, T, []), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18, ... +%! 5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10, ... +%! 4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36, ... +%! 6,18,30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18, ... +%! 3,9,15,6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10, ... +%! 4,8,12,2,6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6, ... +%! 18,30,12,24,36,6,18,30,12,24,36], +%! [3,2,2,3,2,2])) +%!assert (tensorprod (T, T, 2, 3), +%! reshape ([3,7,11,3,7,11,9,21,33,9,21,33,15,35,55,15,35,55,6,14, ... +%! 22,6,14,22,12,28,44,12,28,44,18,42,66,18,42,66], +%! [3,2,3,2])) +%!assert (tensorprod (T, T(1:2, 1:2, :), [2, 3],[1, 3]), +%! [14, 20; 30, 44; 46, 68]) +%!assert (tensorprod (T, T(1:2, 1:2, :), [3, 2],[1, 3]), +%! [12, 18; 28, 42; 44, 66]) +%!assert (tensorprod (T, reshape (T, [2, 2, 3]), 2, 1), +%! reshape ([7,15,23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56,7,15, ... +%! 23,7,15,23,9,23,37,9,23,37,16,36,56,16,36,56], +%! [3,2,2,3])) +%!assert (tensorprod (T, T, [1, 3]), [70, 88; 88, 112]) +%!assert (tensorprod (T, T, [1, 3]), tensorprod (T, T, [3, 1])) +%!assert (tensorprod (T, reshape (T, [2, 2, 3]), [2, 3], [1, 2]), +%! [16, 23, 25; 38, 51, 59; 60, 79, 93]) + +## NumDimensionsA tests +%!assert (tensorprod (v1, v1, "NumDimensionsA", 2), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 2])); +%!assert (tensorprod (v1, v1, "numdimensionsa", 2), +%! tensorprod (v1, v1, "NumDimensionsA", 2)); +%!assert (tensorprod (v1, v1, "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, [], "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, [], [], "NumDimensionsA", 3), +%! reshape ([1, 2, 2, 4], [1, 2, 1, 1, 2])); +%!assert (tensorprod (v1, v1, "all", "NumDimensionsA", 3), 5); +%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 2), [5; 11]); +%!assert (tensorprod (M1, v1, 2, "NumDimensionsA", 5), [5; 11]); +%!assert (tensorprod (M1, v1, [2, 3], "NumDimensionsA", 5), [5; 11]); +%!assert (tensorprod (M1, M2, "NumDimensionsA", 2), reshape ([1,3,2,4,3,9,6, ... +%! 12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,3,2])) +%!assert (tensorprod (M1, M2, "NumDimensionsA", 3), reshape ([1,3,2,4,3,9,6, ... +%! 12,5,15,10,20,2,6,4,8,4,12,8,16,6,18,12,24], [2,2,1,3,2])) +%!assert (tensorprod (T, T, 1, "NumDimensionsA", 3), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,2,2])) +%!assert (tensorprod (T, T, 3, "NumDimensionsA", 3), +%! reshape ([2,6,10,4,8,12,6,18,30,12,24,36,10,30,50,20,40,60,4,12, ... +%! 20,8,16,24, 8,24,40,16,32,48,12,36,60,24,48,72], +%! [3,2,3,2])) +%!assert (tensorprod (T, T, 1, "NumDimensionsA", 4), +%! reshape ([35,44,35,44,44,56,44,56,35,44,35,44,44,56,44,56], +%! [2,2,1,2,2])) +%!assert (tensorprod (T, T, 4, "NumDimensionsA", 4), +%! reshape ([1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15,6,12,18,5, ... +%! 15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2,6,10,4,8, ... +%! 12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24,36,6,18, ... +%! 30,12,24,36,1,3,5,2,4,6,1,3,5,2,4,6,3,9,15,6,12,18,3,9,15, ... +%! 6,12,18,5,15,25,10,20,30,5,15,25,10,20,30,2,6,10,4,8,12,2, ... +%! 6,10,4,8,12,4,12,20,8,16,24,4,12,20,8,16,24,6,18,30,12,24, ... +%! 36,6,18,30,12,24,36], +%! [3,2,2,3,2,2])) + +## Test empty inputs +%!assert (tensorprod ([], []), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], 1), []) +%!assert (tensorprod (1, []), zeros (1, 1, 0, 0)) +%!assert (tensorprod (zeros (0, 0, 0), zeros (0, 0, 0)), zeros (0, 0, 0, 0, 0, 0)) +%!assert (tensorprod ([], [], []), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], [], 1), []) +%!assert (tensorprod ([], [], 2), []) +%!assert (tensorprod ([], [], 3), zeros (0, 0, 0, 0)) +%!assert (tensorprod ([], [], 4), zeros (0, 0, 1, 0, 0)) +%!assert (tensorprod ([], [], 5), zeros (0, 0, 1, 1, 0, 0)) +%!assert (tensorprod ([], [], 3, "NumDimensionsA", 4), zeros (0, 0, 1, 0, 0)) +%!assert (tensorprod ([], [], 3, 4, "NumDimensionsA", 5), zeros (0, 0, 1, 1, 0, 0)) + +## Test input validation +%!error tensorprod () +%!error tensorprod (1) +%!error tensorprod (1,2,3,4,5,6,7) +%!error tensorprod ("foo", 1) +%!error tensorprod (1, "bar") +%!error tensorprod (int32(1), 1) +%!error tensorprod (1, int32(1)) +%!error tensorprod (1, 1, "foo") +%!error tensorprod (1, 1, 1, "foo", 1) +%!error tensorprod (1, 1, "foo", 1) +%!error tensorprod (1, 1, 1, "bar") +%!error tensorprod (1, 1, zeros(0,0,0), []) +%!error tensorprod (1, 1, [], zeros(0,0,0)) +%!error tensorprod (1, 1, zeros(0,0,0)) +%!error tensorprod (1, 1, 1, "all", 1) +%!error tensorprod (1, 1, "NumDimensionsA", 1, 1) +%!error tensorprod (1, 1, 1, {}, 1) +%!error tensorprod (ones (3, 4), ones (4, 3), 1) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, 1) +%!error tensorprod (1, 1, 0) +%!error tensorprod (1, 1, -1) +%!error tensorprod (1, 1, 1.5) +%!error tensorprod (1, 1, NaN) +%!error tensorprod (1, 1, Inf) +%!error tensorprod (1, 1, {}) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, [1, 2]) +%!error tensorprod (ones (3, 4), ones (4, 3), 1, []) +%!error tensorprod (ones (3, 4), ones (4, 3), [], [1, 2]) +%!error tensorprod (ones (3, 4), ones (4, 3), "all") +%!error tensorprod (1, 1, "NumDimensionsA") +%!error tensorprod (ones (2, 2, 2), 1, "NumDimensionsA", 2) +%!error tensorprod (1, 1, 5, "NumDimensionsA", 4) +%!error tensorprod (1, 1, 5, 5, "NumDimensionsA", 4) +%!error tensorprod (1, 1, NumDimensionsA=4) +%!error tensorprod (1, 1, numdimensionsa=4) +%!error tensorprod (1, 1, 2, 1, 1) +%!error tensorprod (1, 1, 2, 1, 1, 1) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", "foo") +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", {}) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", -1) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", 0) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", 1.5) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", NaN) +%!error tensorprod (1, 1, 2, 1, "NumDimensionsA", Inf) diff -r 9089bd969b37 -r bd9da634f00d scripts/plot/util/__pltopt__.m --- a/scripts/plot/util/__pltopt__.m Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/plot/util/__pltopt__.m Tue Dec 06 15:17:16 2022 -0500 @@ -158,12 +158,6 @@ topt = opt(1); n = 1; - if (any (topt == "0":"6")) - warning ("Octave:deprecated-option", ... - ["%s: using numbers to select line colors is deprecated. ", ... - "Use the corresponding color identifier instead."], caller); - endif - ## LineStyles if (strncmp (opt, "--", 2) || strncmp (opt, "-.", 2)) options.linestyle = opt(1:2); @@ -195,20 +189,19 @@ topt = "+"; endif options.marker = topt; - ## Numeric color specs are for backward compatibility. Don't document. - elseif (topt == "k" || topt == "0") + elseif (topt == "k") options.color = [0, 0, 0]; - elseif (topt == "r" || topt == "1") + elseif (topt == "r") if (strncmp (opt, "red", 3)) n = 3; endif options.color = [1, 0, 0]; - elseif (topt == "g" || topt == "2") + elseif (topt == "g") if (strncmp (opt, "green", 5)) n = 5; endif options.color = [0, 1, 0]; - elseif (topt == "b" || topt == "3") + elseif (topt == "b") if (strncmp (opt, "black", 5)) options.color = [0, 0, 0]; n = 5; @@ -223,17 +216,17 @@ n = 6; endif options.color = [1, 1, 0]; - elseif (topt == "m" || topt == "4") + elseif (topt == "m") if (strncmp (opt, "magenta", 7)) n = 7; endif options.color = [1, 0, 1]; - elseif (topt == "c" || topt == "5") + elseif (topt == "c") if (strncmp (opt, "cyan", 4)) n = 4; endif options.color = [0, 1, 1]; - elseif (topt == "w" || topt == "6") + elseif (topt == "w") if (strncmp (opt, "white", 5)) n = 5; endif diff -r 9089bd969b37 -r bd9da634f00d scripts/plot/util/private/__print_parse_opts__.m --- a/scripts/plot/util/private/__print_parse_opts__.m Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/plot/util/private/__print_parse_opts__.m Tue Dec 06 15:17:16 2022 -0500 @@ -234,7 +234,7 @@ if (any (strcmp (unsupported, arg_st.devopt))) warning ('Octave:print:deprecated-format', - 'print: "%s" format is no more officially supported', ... + 'print: "%s" format is no longer officially supported', arg_st.devopt); endif diff -r 9089bd969b37 -r bd9da634f00d scripts/strings/isstring.m --- a/scripts/strings/isstring.m Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/strings/isstring.m Tue Dec 06 15:17:16 2022 -0500 @@ -46,7 +46,7 @@ print_usage (); endif - tf = false; + tf = isa (s, 'string'); endfunction @@ -60,4 +60,3 @@ %!assert (isstring ({"b"}), false) %!error isstring () -%!error isstring ("a", "b") diff -r 9089bd969b37 -r bd9da634f00d scripts/testfun/oruntests.m --- a/scripts/testfun/oruntests.m Tue Dec 06 14:23:21 2022 -0500 +++ b/scripts/testfun/oruntests.m Tue Dec 06 15:17:16 2022 -0500 @@ -71,29 +71,34 @@ no_tests = {}; printf ("Processing files in %s:\n\n", directory); fflush (stdout); - for i = 1:numel (flist) - f = flist{i}; - if ((length (f) > 2 && strcmpi (f((end-1):end), ".m")) - || (length (f) > 3 && strcmpi (f((end-2):end), ".cc"))) - ff = fullfile (directory, f); - if (! isfile (ff)) - continue; + unwind_protect + old_dir = cd (directory); + for i = 1:numel (flist) + f = flist{i}; + if ((length (f) > 2 && strcmpi (f((end-1):end), ".m")) + || (length (f) > 3 && strcmpi (f((end-2):end), ".cc"))) + ff = fullfile (directory, f); + if (! isfile (ff)) + continue; + endif + if (has_tests (ff)) + print_test_file_name (f); + [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet"); + print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs); + fflush (stdout); + elseif (has_functions (ff)) + no_tests(end+1) = f; + endif + elseif (f(1) == "@") + f = fullfile (directory, f); + if (isfolder (f)) + dirs(end+1) = f; + endif endif - if (has_tests (ff)) - print_test_file_name (f); - [p, n, xf, xb, sk, rtsk, rgrs] = test (ff, "quiet"); - print_pass_fail (p, n, xf, xb, sk, rtsk, rgrs); - fflush (stdout); - elseif (has_functions (ff)) - no_tests(end+1) = f; - endif - elseif (f(1) == "@") - f = fullfile (directory, f); - if (isfolder (f)) - dirs(end+1) = f; - endif - endif - endfor + endfor + unwind_protect_cleanup + cd (old_dir); + end_unwind_protect if (! isempty (no_tests)) printf ("\nThe following files in %s have no tests:\n\n", directory); printf ("%s", list_in_columns (no_tests)); diff -r 9089bd969b37 -r bd9da634f00d src/main-gui.cc --- a/src/main-gui.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/src/main-gui.cc Tue Dec 06 15:17:16 2022 -0500 @@ -52,6 +52,7 @@ #include "octave-build-info.h" #include "qt-application.h" #include "sysdep.h" +#include "version.h" static void check_hg_versions (void) @@ -143,7 +144,8 @@ octave::sys::env::set_program_name (argv[0]); - octave::qt_application app (argc, argv); + octave::qt_application app ("octave", "octave-gui", OCTAVE_VERSION, + argc, argv); int ret = app.execute (); diff -r 9089bd969b37 -r bd9da634f00d src/mkoctfile.in.cc --- a/src/mkoctfile.in.cc Tue Dec 06 14:23:21 2022 -0500 +++ b/src/mkoctfile.in.cc Tue Dec 06 15:17:16 2022 -0500 @@ -356,11 +356,6 @@ vars["LD_STATIC_FLAG"] = get_variable ("LD_STATIC_FLAG", %OCTAVE_CONF_LD_STATIC_FLAG%); - // FIXME: Remove LFLAGS in Octave 9 - vars["LFLAGS"] = get_variable ("LFLAGS", DEFAULT_LDFLAGS); - if (vars["LFLAGS"] != DEFAULT_LDFLAGS) - std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl; - vars["F77_INTEGER8_FLAG"] = get_variable ("F77_INTEGER8_FLAG", %OCTAVE_CONF_F77_INTEGER_8_FLAG%); vars["ALL_FFLAGS"] = vars["FFLAGS"] + ' ' + vars["F77_INTEGER8_FLAG"]; @@ -888,10 +883,6 @@ { ++i; - // FIXME: Remove LFLAGS checking in Octave 9 - if (argv[i] == "LFLAGS") - std::cerr << "mkoctfile: warning: LFLAGS is deprecated and will be removed in a future version of Octave, use LDFLAGS instead" << std::endl; - if (! var_to_print.empty ()) std::cerr << "mkoctfile: warning: only one '" << arg << "' option will be processed" << std::endl; @@ -1317,13 +1308,12 @@ octave_libs = "-L" + quote_path (vars["OCTLIBDIR"]) + ' ' + vars["OCTAVE_LIBS"]; - // FIXME: Remove LFLAGS in Octave 9 std::string cmd = (vars["CXXLD"] + ' ' + vars["CPPFLAGS"] + ' ' + vars["ALL_CXXFLAGS"] + ' ' + vars["RDYNAMIC_FLAG"] + ' ' + pass_on_options + ' ' + output_option + ' ' + objfiles + ' ' + libfiles + ' ' + ldflags + ' ' + vars["ALL_LDFLAGS"] + ' ' - + vars["LFLAGS"] + ' ' + octave_libs + ' ' + + octave_libs + ' ' + vars["OCTAVE_LINK_OPTS"] + ' ' + vars["OCTAVE_LINK_DEPS"]); int status = run_command (cmd, verbose, printonly); @@ -1348,12 +1338,11 @@ + ' ' + vars["OCTAVE_LIBS"]; #endif - // FIXME: Remove LFLAGS in Octave 9 std::string cmd = (vars["CXXLD"] + ' ' + vars["ALL_CXXFLAGS"] + ' ' + pass_on_options + " -o " + octfile + ' ' + objfiles + ' ' + libfiles + ' ' + ldflags + ' ' + vars["DL_LDFLAGS"] + ' ' - + vars["LDFLAGS"] + ' ' + vars["LFLAGS"] + ' ' + octave_libs + ' ' + + vars["LDFLAGS"] + ' ' + octave_libs + ' ' + vars["OCT_LINK_OPTS"] + ' ' + vars["OCT_LINK_DEPS"]); #if defined (OCTAVE_USE_WINDOWS_API) || defined(CROSS) diff -r 9089bd969b37 -r bd9da634f00d test/io.tst --- a/test/io.tst Tue Dec 06 14:23:21 2022 -0500 +++ b/test/io.tst Tue Dec 06 15:17:16 2022 -0500 @@ -297,6 +297,118 @@ %!assert (sscanf ('0177 08', '%i'), [127; 0; 8]) %!assert (sscanf ('0177 08', '%d'), [177; 8]) +## Extensive testing of '%c' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%c'); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10c'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c'); +%! assert (val, 'abcde'); +%! assert (cnt, 2); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3c', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%c', 5); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); + +## Extensive testing of '%s' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%s'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10s'); +%! assert (val, 'abcde'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s'); +%! assert (val, 'abcde'); +%! assert (cnt, 2); +%! assert (msg, ''); +%! assert (pos, 6); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%3s', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%1s', 5); +%! assert (val, 'abcde'); +%! assert (cnt, 5); +%! assert (msg, ''); +%! assert (pos, 6); + +## Extensive testing of '%[]' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]'); +%! assert (val, 'abc'); +%! assert (cnt, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[a-c]', 1); +%! assert (val, 'ab'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 3); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[a-c]', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); + +## Extensive testing of '%[^]' +%!test +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%10[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]'); +%! assert (val, 'abc'); +%! assert (cnt, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 4); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%2[^de]', 1); +%! assert (val, 'ab'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 3); +%! [val, cnt, msg, pos] = sscanf ('abcde', '%[^de]', 1); +%! assert (val, 'abc'); +%! assert (cnt, 1); +%! assert (msg, ''); +%! assert (pos, 4); + ## bug #47741 %!assert (sscanf ('2147483647', '%d'), 2147483647) %!assert (sscanf ('2147483647', '%i'), 2147483647) @@ -389,10 +501,169 @@ %!test <*62723> %! [val, count, msg, pos] = sscanf ("p", "%c"); -%! assert (val, "p"); +%! assert (val, 'p'); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 2); + +%!test <*62723> +%! [val, count, msg, pos] = sscanf (' ,1 ', ' %s ', 1); +%! assert (val, ',1'); %! assert (count, 1); -%! assert (msg, ""); -%! assert (pos, 2); +%! assert (msg, ''); +%! assert (pos, 5); + +## Test NaN at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 n', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 na', '%f'); +%! assert (val, [2; 3; NA]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 7); +%! [val, count, msg, pos] = sscanf ('2 3 nan', '%f'); +%! assert (val, [2; 3; NaN]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 8); + +## Test NaN within string +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 n 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 na 4', '%f'); +%! assert (val, [2; 3; NA; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 9); +%! [val, count, msg, pos] = sscanf ('2 3 nan 4', '%f'); +%! assert (val, [2; 3; NaN; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 10); + +## Test Inf at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 i', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 in', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 inf', '%f'); +%! assert (val, [2; 3; Inf]); +%! assert (count, 3); +%! assert (msg, ''); +%! assert (pos, 8); + +## Test Inf within string +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 i 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 in 4', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 inf 4', '%f'); +%! assert (val, [2; 3; Inf; 4]); +%! assert (count, 4); +%! assert (msg, ''); +%! assert (pos, 10); + +## Test '-' at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 -', '%d'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 -', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '-' within string +%!test <63383> +%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%d'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('1 2 - 3', '%f'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '+' at EOF +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('2 3 +', '%d'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('2 3 +', '%f'); +%! assert (val, [2; 3]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +## Test '+' within string +%!test <63383> +%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%d'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('1 2 + 3', '%f'); +%! assert (val, [1; 2]); +%! assert (count, 2); +%! assert (msg, 'sscanf: format failed to match'); +%! assert (pos, 5); + +%## Test +NA, -NA, +NAN, -NAN +%!test <*63383> +%! [val, count, msg, pos] = sscanf ('+NA -NA 1 +NAN -NAN', '%f'); +%! assert (val, [NA; NA; 1; NaN; NaN]); +%! assert (count, 5); +%! assert (msg, ''); +%! assert (pos, 20); +%! [val, count, msg, pos] = sscanf ('-NA', '%f'); +%! assert (val, NA); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, count, msg, pos] = sscanf ('+NA', '%f'); +%! assert (val, NA); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 4); +%! [val, count, msg, pos] = sscanf ('-NaN', '%f'); +%! assert (val, NaN); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 5); +%! [val, count, msg, pos] = sscanf ('+NaN', '%f'); +%! assert (val, NaN); +%! assert (count, 1); +%! assert (msg, ''); +%! assert (pos, 5); %!test %! [a, b, c] = sscanf ("1.2 3 foo", "%f%d%s", "C"); @@ -403,14 +674,16 @@ %! && v1 == [1; 2; 3; 4; 5; 6] && c1 == 6 && ischar (m1) %! && v2 == [1; 2] && c2 == 2 && ischar (m2))); -%!error sscanf () -%!error sscanf (1, 2) -%!error sscanf ("foo", "bar", "C", 1) - %!test %! [x, n] = sscanf (" 0.024000 0.200 0.200 2.000 1987 5 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 4 5 1 2 2 5 5 8 2 8 12 6 15 18 28 26 47 88 118 162 192 130 88 56 27 23 14 9 6 3 4 1 0 2 3 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0.026000 0.250 0.250 2.100 3115 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 1 0 1 1 1 0 1 0 1 3 2 0 5 15 25 44 66 145 179 193 172 104 57 17 11 12 2 1 0 1 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.028000 0.300 0.300 2.200 4929 3 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 1 0 1 2 2 3 2 3 14 21 49 80 148 184 218 159 124 63 37 13 12 3 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.030000 0.350 0.350 2.300 7051 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 2 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 0 2 0 0 0 1 5 6 14 28 51 88 154 177 208 169 124 65 39 15 5 3 3 2 1 0 1 0 1 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.032000 0.400 0.400 2.400 9113 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 2 0 1 0 0 1 1 0 2 3 5 3 17 30 60 117 156 189 209 129 102 64 56 16 11 4 2 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0.034000 0.450 0.450 2.500 11811 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 5 5 15 21 57 99 149 190 195 159 130 69 41 16 10 2 5 3 0 1 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.036000 0.500 0.500 2.600 14985 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 2 2 6 10 34 60 95 126 177 194 155 99 71 44 17 6 7 2 0 0 0 3 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.038000 0.550 0.550 2.700 18391 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 2 0 0 1 1 0 1 2 1 0 0 0 1 0 1 3 6 19 27 52 95 161 154 169 134 94 64 37 19 9 6 0 2 1 0 0 0 0 1 2 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 2 2 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.040000 0.600 0.600 2.800 22933 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 2 0 3 4 7 18 27 47 82 134 163 133 138 101 58 34 26 10 5 2 1 2 1 1 0 2 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.042000 0.650 0.650 2.900 27719 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 2 8 16 37 51 87 128 153 146 123 105 62 35 24 8 3 5 0 1 2 1 0 0 0 1 1 1 0 0 0 1 0 1 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.044000 0.700 0.700 3.000 32922 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 2 0 0 0 0 0 0 0 0 2 1 0 0 0 0 1 1 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 1 1 0 0 0 1 4 3 5 5 15 35 54 88 132 168 149 105 92 62 30 16 17 4 5 1 0 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.046000 0.750 0.750 3.100 38973 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 4 3 5 20 37 56 94 110 135 149 124 84 58 36 17 14 7 1 0 2 0 1 0 0 1 1 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.048000 0.800 0.800 3.200 45376 5 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0 0 2 1 1 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 3 18 34 55 82 104 135 116 99 79 60 51 29 10 4 3 1 1 1 0 0 1 0 0 0 1 0 0 3 1 2 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.050000 0.850 0.850 3.300 52060 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 2 2 1 3 12 24 40 39 107 121 127 138 100 86 68 44 23 15 7 3 1 1 0 1 1 0 0 2 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 1 1 0 1 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.052000 0.900 0.900 3.400 59454 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 1 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 1 0 0 2 0 2 1 0 0 0 1 0 0 1 0 0 0 0 0 3 3 6 21 32 68 90 132 111 122 107 73 57 47 24 11 7 4 2 2 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 2 0 1 1 0 0 1 0 0 0 0 0 3 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0.054000 0.950 0.950 3.500 67013 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 0 0 1 0 0 1 1 0 0 0 1 0 1 0 1 2 4 3 7 9 28 31 71 94 115 96 108 78 82 60 38 17 12 11 4 3 1 1 0 2 1 0 0 0 2 1 3 0 0 0 0 3 0 0 1 0 0 0 0 0 0 0 2 0 0 0 1 0 2 0 1 0 2 0 1 0 0 1 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0.056000 1.000 1.000 3.600 75475 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 3 0 0 1 1 2 0 1 4 0 1 8 6 7 17 41 56 71 109 113 84 103 72 54 35 22 6 9 1 7 5 4 0 0 1 0 0 0 0 0 0 1 0 0 2 1 0 0 0 0 2 0 0 1 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 3 0 0 0 1 0 0 0 0 0 0 1 1 0 0 2 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.058000 1.050 1.050 3.700 83558 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 2 0 0 1 0 3 2 3 6 15 27 41 77 73 94 94 92 76 61 56 42 23 13 11 6 2 1 2 0 1 2 0 0 1 0 1 0 0 1 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1 0 0 0 0 2 0 0 0 0 0 1 2 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0.060000 1.100 1.100 3.800 93087 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 1 2 2 0 0 0 1 0 1 1 0 0 0 1 1 0 4 0 0 1 2 0 3 1 3 5 13 33 31 65 75 77 96 97 80 59 45 36 32 18 2 5 0 1 0 0 1 0 0 3 0 0 0 0 1 0 0 0 0 0 1 0 0 1 2 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 0 2 0 0 2 0 1 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.062000 1.150 1.150 3.900 102829 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 1 0 1 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 0 0 1 1 0 0 1 0 1 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 2 0 2 1 2 0 0 2 4 3 5 11 9 23 43 53 68 65 87 83 77 59 49 34 18 15 9 4 2 3 2 0 0 0 4 0 1 1 0 0 2 0 0 1 0 0 0 0 1 1 1 0 1 0 0 0 0 2 0 0 0 0 1 0 0 1 1 1 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0.064000 1.200 1.200 4.000 113442 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 1 0 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 1 1 1 0 1 1 1 1 1 0 0 0 1 2 0 0 0 2 0 4 5 11 13 29 39 61 68 61 75 76 74 73 44 37 29 19 6 3 3 2 0 1 2 1 0 0 0 0 1 1 1 0 1 1 0 0 0 1 0 1 1 0 1 2 0 2 1 1 1 0 0 0 0 1 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0.066000 1.250 1.250 4.100 126668 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 1 0 0 0 1 1 2 3 0 2 1 2 0 1 0 3 0 0 0 1 0 1 1 3 0 0 1 3 0 2 4 3 12 12 30 48 56 66 77 78 71 82 52 31 32 19 20 16 8 2 1 3 0 0 2 1 0 1 0 1 0 0 0 1 3 1 0 1 0 1 1 1 0 0 0 0 0 2 0 2 0 0 0 0 0 1 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 2 0 3 1 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.068000 1.300 1.300 4.200 138042 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 0 2 0 0 1 0 1 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 0 0 0 0 3 0 0 1 0 0 1 2 0 0 0 3 0 1 0 0 3 0 1 0 1 1 3 1 4 7 11 14 27 36 44 68 72 70 71 45 44 46 29 13 16 11 5 2 0 3 0 0 0 0 1 1 2 0 0 1 1 2 1 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 2 0 0 1 1 0 1 1 1 0 0 1 0 0 1 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.070000 1.350 1.350 4.300 152335 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 2 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 1 1 1 0 1 1 0 1 1 1 1 0 2 0 0 0 0 0 2 0 1 7 14 19 34 35 54 72 68 72 68 58 48 36 37 27 25 17 1 4 1 0 0 0 1 2 2 0 0 1 1 1 2 1 0 3 1 0 1 0 2 1 0 0 0 1 1 1 2 0 0 0 0 1 1 0 1 1 0 2 1 1 1 1 0 0 0 1 1 0 0 2 0 0 1 0 0 0 1 1 0 2 1 1 0 0 0 0 2 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0.072000 1.400 1.400 4.400 166280 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 1 0 1 1 1 0 0 1 0 1 0 0 3 4 2 2 0 0 0 0 0 1 1 3 1 0 3 2 2 1 2 2 0 2 2 1 8 14 26 24 29 47 47 68 65 63 55 42 41 26 29 17 8 4 4 1 0 1 2 0 0 0 1 1 2 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 1 0 0 1 2 1 2 1 0 0 0 0 0 1 1 2 0 2 2 0 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0.074000 1.450 1.450 4.500 179484 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 1 0 0 1 0 1 2 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 1 0 1 0 1 1 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 1 1 0 1 1 1 2 0 0 1 1 2 1 0 1 1 2 2 0 1 5 6 10 20 43 50 57 62 53 62 66 45 42 33 27 26 23 14 3 0 2 0 1 0 0 1 1 0 0 2 1 1 0 0 3 0 1 1 1 0 1 1 0 1 0 1 2 1 0 0 1 2 0 2 0 0 0 0 1 1 3 1 0 0 2 1 1 1 0 0 0 0 0 0 1 2 0 1 0 0 0 0 0 1 1 0 2 0 0 0 0 0 1 0 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0.076000 1.500 1.500 4.600 197657 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 2 0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 2 0 0 0 2 1 1 0 1 1 0 1 1 3 2 1 1 2 1 0 1 0 0 0 0 0 1 1 1 0 5 3 7 12 24 38 32 41 48 54 66 71 49 46 31 38 25 15 8 6 6 5 0 1 3 0 1 1 1 1 1 0 1 2 0 1 0 0 0 1 0 2 1 2 0 0 0 0 1 3 1 0 0 0 0 1 1 0 1 0 1 1 1 1 1 0 4 1 1 1 0 3 0 0 0 2 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0.078000 1.550 1.550 4.700 212054 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 1 0 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 2 0 0 0 1 0 0 1 0 1 1 0 1 3 1 0 0 1 2 0 0 0 1 0 0 0 0 0 2 1 2 1 1 1 0 0 1 5 1 1 2 3 5 7 9 11 22 31 37 48 50 52 54 57 37 38 38 33 24 11 19 11 3 1 2 0 3 3 2 1 0 1 3 0 1 1 1 1 1 2 0 0 0 1 1 2 0 1 1 3 0 1 1 0 0 1 0 2 0 1 0 0 1 3 0 2 0 1 0 1 2 0 1 1 1 1 1 0 3 0 1 0 0 0 1 0 0 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0 0 0 0 0 0.080000 1.600 1.600 4.800 231971 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 2 0 0 0 1 1 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 2 0 0 0 1 0 0 0 0 0 1 0 0 0 0 1 2 1 0 1 1 1 0 1 0 0 1 0 1 3 0 0 0 1 0 0 0 1 1 1 0 0 4 1 1 0 2 0 1 1 1 2 0 0 0 1 0 1 2 1 2 3 2 0 1 0 4 3 1 1 1 1 3 1 0 0 0 2 1 0 2 7 17 13 29 47 58 59 52 38 51 51 38 34 35 21 14 13 4 1 0 1 1 1 0 2 2 4 1 0 1 1 4 0 0 0 2 0 2 2 2 0 0 1 3 2 1 1 2 2 2 2 1 0 3 0 2 1 2 1 2 2 0 0 1 1 0 2 0 2 2 0 1 0 2 2 3 1 2 3 1 1 0 1 0 2 0 1 2 1 2 0 2 1 0 0 3 0 0 1 1 1 1 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0.082000 1.650 1.650 4.900 252503 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 2 0 0 0 0 0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 0 0 1 0 1 2 2 2 1 0 2 0 1 0 1 1 2 2 0 3 0 0 4 1 0 0 3 0 0 1 2 0 1 1 1 3 0 1 0 2 9 11 25 27 34 53 41 49 43 47 36 31 38 22 30 22 18 9 5 9 2 2 1 2 2 3 1 4 1 1 0 0 1 2 0 2 1 0 0 1 3 2 2 1 0 0 0 1 2 1 0 0 0 2 1 1 0 2 0 0 1 0 0 2 1 3 1 1 1 0 2 1 1 0 2 1 0 1 3 0 0 0 0 2 0 0 1 0 0 0 0 0 1 2 1 1 1 0 2 1 0 0 0 2 0 1 0 0 0 0 1 0 0 0 0 1 0 0 2 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0.084000 1.700 1.700 5.000 267889 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 1 1 0 0 0 0 0 0 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 1 0 3 0 1 1 1 0 1 2 1 0 2 0 2 4 0 1 0 0 0 1 1 0 1 3 2 0 2 0 4 0 0 2 0 1 4 2 4 3 3 6 10 14 28 37 54 36 40 52 40 50 46 40 32 26 29 12 18 5 2 0 2 4 1 2 1 0 2 1 2 2 1 0 1 0 2 1 2 4 1 1 5 1 0 2 0 1 2 3 2 2 1 2 1 0 2 1 2 1 1 4 1 2 1 4 0 2 2 0 0 3 1 0 2 0 0 1 1 1 0 0 2 1 0 0 0 0 0 0 0 1 1 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0.086000 1.750 1.750 5.100 290294 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 2 0 0 0 1 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 1 3 1 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 1 1 0 0 2 1 0 1 0 1 0 0 2 2 0 1 2 2 0 2 0 2 0 1 0 0 1 1 1 3 1 1 1 1 3 4 1 1 2 2 2 1 0 3 0 0 0 2 4 5 6 16 18 20 31 40 54 55 46 41 52 35 27 21 28 27 20 15 8 6 7 1 0 0 3 0 0 2 2 0 3 1 3 1 1 2 0 0 1 2 1 3 2 0 1 2 1 3 1 1 1 1 1 2 0 2 1 0 1 1 1 3 1 1 2 0 1 0 1 0 2 1 1 0 0 1 2 0 3 1 1 0 0 0 1 3 1 1 1 0 0 1 2 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0 2 0 1 0 0 0 2 1 0 2 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0.088000 1.800 1.800 5.200 312476 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 1 0 0 0 1 0 1 0 1 1 0 0 0 0 0 0 2 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 2 0 0 0 1 0 1 0 0 0 0 0 0 2 1 0 0 1 0 0 1 1 1 1 4 2 0 1 0 0 3 0 0 0 0 0 1 1 4 0 0 0 0 1 1 2 1 0 3 0 0 2 2 4 0 3 1 6 9 10 13 21 24 32 43 33 41 43 49 50 32 26 31 27 12 16 17 3 3 3 5 0 3 0 2 1 3 3 2 1 2 3 1 2 1 1 1 2 0 1 1 0 2 0 3 0 0 2 0 0 0 0 1 0 1 1 3 3 0 1 1 1 1 1 1 2 2 2 0 3 1 0 2 2 2 0 0 0 0 3 1 2 5 1 1 2 0 0 3 3 0 2 2 0 0 0 0 1 2 0 0 1 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0.090000 1.850 1.850 5.300 337348 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 2 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 2 0 1 1 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 2 0 0 0 1 3 2 0 0 2 2 3 3 2 2 2 0 0 1 1 3 1 3 0 0 0 0 0 0 1 2 1 2 1 2 2 2 0 1 1 0 4 2 2 7 6 15 22 21 39 37 50 31 51 30 33 34 34 26 21 14 13 10 9 4 3 3 4 2 2 0 1 2 3 3 0 1 3 2 5 3 2 2 4 0 2 3 0 4 2 1 2 2 2 4 2 1 3 1 3 2 1 3 1 2 4 1 1 1 1 2 4 1 3 3 3 1 0 4 1 0 1 1 1 1 2 3 0 3 0 0 4 1 1 1 0 2 2 2 1 2 2 0 1 1 0 0 0 2 0 1 0 1 0 0 1 0 0 0 1 3 0 0 1 0 0 1 1 1 0 0 1 0 0 0 0 0 0 0.092000 1.900 1.900 5.400 357303 3 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 1 3 1 0 1 0 0 0 0 1 0 0 1 0 0 1 1 2 2 0 0 2 2 1 1 1 1 1 1 0 1 0 0 1 1 1 3 1 1 1 1 1 0 1 4 0 1 1 1 3 0 1 1 2 2 2 0 2 3 2 2 2 2 1 2 1 3 8 22 14 32 36 46 39 42 39 29 36 38 26 24 26 18 16 19 10 9 3 6 5 0 3 2 1 1 1 2 0 2 1 1 0 1 1 3 1 0 2 4 2 2 1 4 1 2 2 1 1 0 1 2 0 2 2 2 4 2 1 1 0 2 1 3 1 2 3 4 2 3 2 3 0 1 2 1 0 0 0 4 1 1 1 2 1 3 1 0 5 1 0 0 0 0 0 0 1 0 2 0 1 2 1 0 1 0 0 0 0 0 1 1 0 1 0 1 4 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0.094000 1.950 1.950 5.500 383138 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 1 1 1 0 1 0 0 0 1 0 0 0 0 0 1 0 0 0 1 0 0 2 1 0 1 1 1 0 0 0 0 0 0 1 1 0 1 0 0 1 1 0 1 0 0 0 0 0 0 0 2 1 1 1 1 2 1 0 2 0 1 0 3 2 1 3 0 1 3 1 1 0 5 0 1 0 1 2 0 0 1 1 2 0 0 6 1 0 3 2 2 3 4 5 0 4 2 1 5 4 11 15 22 27 28 57 38 38 40 38 39 38 27 26 30 18 14 10 10 4 4 4 3 3 2 2 2 2 1 1 1 1 2 2 3 4 1 2 3 1 2 1 2 2 2 1 3 2 1 5 0 1 1 1 3 2 2 2 1 3 1 1 0 3 2 2 0 0 2 2 2 0 0 0 2 0 1 3 1 2 3 2 1 1 0 1 1 1 0 3 2 2 1 0 0 1 3 1 1 0 1 0 0 0 0 0 1 0 0 0 0 1 0 0 3 1 0 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0 0 0.096000 2.000 2.000 5.600 409868 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 1 0 1 0 1 0 2 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 2 0 1 0 0 2 0 2 0 0 0 0 1 0 0 2 1 2 2 2 1 2 1 1 1 1 1 2 0 0 1 1 0 1 0 2 1 2 0 2 0 3 1 2 1 3 1 5 0 2 2 1 2 4 1 2 0 3 1 4 7 5 9 13 22 19 31 27 28 41 34 39 37 22 23 21 22 17 23 15 8 9 3 8 0 3 1 2 2 2 3 1 0 4 2 4 2 2 2 2 4 2 1 1 0 2 0 3 0 3 2 2 1 2 2 1 4 1 2 2 1 1 5 2 1 2 1 2 2 1 0 2 4 3 2 1 2 2 3 2 3 1 2 1 1 1 1 2 1 1 2 2 1 2 3 2 1 1 0 2 2 4 0 1 1 1 1 1 0 0 1 1 3 0 0 0 0 0 1 0 0 2 0 1 2 0 1 1 1 0 1 0 1 0 0 0.098000 2.050 2.050 5.700 439102 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 1 1 0 0 1 0 1 0 1 0 0 0 0 1 1 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 1 2 0 1 1 0 0 0 0 1 1 1 0 4 0 0 0 2 1 1 0 3 4 0 1 2 2 1 0 3 0 3 2 0 0 2 0 1 0 0 1 0 1 3 1 3 5 0 2 2 3 5 2 2 2 0 3 2 3 6 5 16 21 19 23 28 29 35 42 42 44 39 33 23 30 18 25 24 15 13 5 4 2 2 0 3 3 0 0 1 3 0 1 1 3 2 4 3 4 2 1 1 1 3 1 0 0 2 2 4 2 2 1 4 2 4 2 2 2 1 2 2 1 2 0 4 2 2 3 1 2 1 1 2 2 1 2 4 2 1 4 1 2 2 2 2 0 2 0 3 0 1 0 2 1 0 4 2 1 3 2 1 0 2 1 1 1 1 0 1 1 2 1 1 1 2 0 1 0 2 1 1 0 0 1 0 0 1 0 0 0 0 0 0 0.100000 2.100 2.100 5.800 467340 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 0 0 1 2 0 0 0 0 0 1 0 2 0 0 2 0 0 1 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 1 0 1 0 0 0 0 1 2 0 2 2 4 1 0 1 1 2 3 4 1 4 1 5 1 2 1 0 2 2 2 1 5 4 1 5 4 0 1 2 4 2 2 0 2 1 2 5 4 1 1 1 2 5 7 9 16 23 31 15 22 36 36 44 42 29 31 28 28 18 35 12 10 13 8 4 3 2 2 5 1 2 3 3 1 3 3 5 2 0 3 4 1 2 2 3 0 0 5 2 3 6 2 1 2 5 3 4 3 1 1 1 1 2 2 4 0 2 3 1 2 1 2 4 5 4 3 5 2 1 2 0 5 0 2 2 4 1 0 4 1 0 2 1 2 0 0 1 3 2 4 3 0 2 3 3 3 4 2 2 0 0 0 0 1 1 0 3 2 0 1 2 0 4 2 1 1 1 2 0 0 0 0 0 0 0 0 0 0 0.102000 2.150 2.150 5.900 497495 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1 0 2 1 0 0 0 0 1 0 1 0 0 0 0 1 2 0 0 0 0 0 2 0 0 1 0 1 0 0 0 0 1 1 0 0 0 1 1 1 1 2 0 0 1 0 0 0 1 0 2 2 1 0 0 0 2 0 2 1 1 1 6 3 2 0 3 2 2 2 1 1 3 4 1 0 1 2 4 2 3 3 1 1 1 1 3 3 1 4 1 3 4 3 2 3 1 2 2 5 11 11 14 26 27 28 28 28 36 39 42 29 33 24 20 29 18 13 17 13 6 10 4 3 3 6 1 0 1 0 2 1 3 2 3 1 2 3 1 2 1 2 0 2 2 3 1 3 1 1 2 4 4 1 4 3 2 2 3 5 5 3 0 2 5 3 5 1 4 1 1 3 4 2 2 2 2 1 3 0 1 1 2 2 4 2 1 3 2 0 1 2 1 0 2 3 1 2 0 0 0 2 0 0 1 3 0 0 1 2 0 3 1 0 3 1 2 2 1 1 2 0 0 0 0 2 0 0 1 0 0 0 0 0 0.104000 2.200 2.200 6.000 529288 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 2 1 0 0 1 3 0 2 0 2 0 0 3 2 2 0 4 0 3 2 2 1 3 1 7 3 1 1 0 4 3 2 1 0 0 3 2 3 5 2 1 4 1 5 1 0 3 2 3 0 1 2 4 7 3 7 8 12 15 20 24 34 39 34 35 27 36 34 23 22 26 15 24 12 12 14 5 3 0 7 1 1 3 5 1 2 2 2 4 3 1 2 5 2 2 3 1 1 4 2 1 3 0 4 5 4 6 4 5 3 3 3 3 1 1 5 0 6 1 2 4 2 3 2 1 3 2 0 0 0 1 3 3 0 1 4 0 3 2 3 0 3 3 0 2 3 4 3 1 1 1 2 5 3 1 2 1 1 2 4 1 0 2 4 1 3 0 0 3 0 1 3 0 1 0 0 1 1 1 0 1 1 1 0 0 0 0 0 0 0 0.106000 2.250 2.250 6.100 560628 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 2 0 1 0 1 0 1 0 1 0 0 1 0 0 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 0 0 0 1 1 1 1 0 0 1 1 2 0 0 0 0 2 0 3 1 1 0 0 2 2 2 0 5 2 1 1 1 1 3 1 2 3 0 1 0 0 0 0 1 0 2 2 1 2 1 0 4 3 2 1 2 1 0 4 2 2 0 2 1 1 2 3 1 2 1 2 4 4 11 12 17 19 19 29 30 24 30 35 51 32 36 34 31 19 22 17 11 19 11 7 6 6 3 4 0 3 3 2 0 2 2 2 3 1 5 3 2 3 5 1 0 2 2 5 4 2 3 2 0 1 6 1 2 2 2 2 1 1 2 2 1 4 3 2 2 1 2 5 2 0 2 0 2 5 4 5 2 1 3 6 1 3 4 4 0 0 6 0 2 6 1 2 2 2 0 1 3 1 3 4 2 1 4 2 1 2 3 3 0 3 1 0 2 0 2 1 0 2 1 2 0 0 1 1 0 2 0 0 0 0 0 0 0 0.108000 2.300 2.300 6.200 593293 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 2 0 2 2 1 0 0 2 0 1 0 1 0 0 1 2 2 1 0 0 1 0 2 0 0 0 0 0 1 1 1 1 1 0 0 1 1 0 0 1 1 1 2 2 1 0 1 1 0 1 5 0 2 4 1 0 1 4 2 1 3 2 2 3 2 3 2 0 0 3 4 3 1 3 2 2 0 3 0 2 4 0 3 2 5 1 2 1 4 6 1 2 4 0 3 6 1 7 6 4 5 4 10 16 24 22 20 40 37 44 34 29 21 28 36 36 27 23 24 14 10 4 5 2 5 3 6 2 3 3 1 4 2 1 5 1 3 5 3 2 1 2 2 6 2 3 1 1 0 5 3 3 3 4 5 2 2 3 3 5 5 1 6 2 3 2 6 0 5 2 4 3 5 1 2 2 5 1 2 3 1 2 2 2 4 2 5 5 2 2 2 5 0 1 2 5 2 3 2 3 1 1 2 4 0 2 1 4 2 1 1 1 0 1 2 0 0 1 3 1 0 2 1 1 3 3 2 0 0 0 1 2 0 0 0 0 0.110000 2.350 2.350 6.300 636559 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 1 0 0 0 1 1 2 0 0 1 0 0 0 0 0 0 0 1 2 0 0 1 1 1 0 0 0 0 1 0 1 1 0 0 1 0 0 2 0 1 0 1 0 1 0 0 1 1 3 0 1 2 2 0 2 1 1 1 1 0 1 0 1 3 0 3 2 3 4 3 3 4 3 3 2 6 3 1 1 1 2 4 2 3 1 5 1 3 1 4 5 3 3 2 1 3 7 4 3 10 19 17 19 23 27 28 33 39 36 23 23 32 32 16 19 35 23 12 11 12 8 4 5 7 1 2 2 1 2 3 5 4 2 3 2 6 4 4 2 4 1 2 2 1 2 3 0 4 2 1 2 6 2 2 1 3 3 1 6 4 8 5 2 3 5 2 3 0 3 2 3 1 2 2 3 4 3 8 6 2 1 4 6 3 1 2 0 2 0 2 5 0 3 3 3 3 1 3 3 2 5 4 2 1 4 2 2 4 4 1 3 2 5 2 3 1 2 0 4 0 1 0 6 3 1 2 0 2 0 1 0 0 0 0 0.112000 2.400 2.400 6.400 670484 3 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 1 1 0 1 0 0 0 1 1 0 0 0 0 0 0 0 0 0 2 0 1 1 1 3 0 0 0 2 1 3 0 1 1 1 0 1 1 1 0 0 1 2 0 1 3 1 5 2 3 0 4 0 2 0 0 1 2 1 0 1 0 0 1 0 2 2 3 2 3 2 2 2 3 4 4 2 3 5 3 3 2 3 3 4 2 4 0 3 2 4 4 1 3 1 3 4 2 2 5 2 8 6 12 17 14 22 27 26 29 39 30 24 36 22 22 20 9 19 15 5 12 16 4 7 5 7 5 5 1 4 5 5 4 4 1 4 4 3 3 3 4 2 2 4 2 4 4 4 4 0 2 3 2 1 4 3 6 1 3 3 3 4 5 4 2 2 2 5 3 0 2 5 4 2 5 3 5 1 1 3 1 1 3 6 6 2 3 2 0 3 2 4 3 4 1 2 2 6 2 0 3 2 2 5 3 3 5 2 1 0 3 1 1 2 2 0 1 1 3 2 3 2 1 1 1 1 3 2 1 0 0 0 0 0 0 0 0.114000 2.450 2.450 6.500 711783 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 1 0 0 1 0 2 1 2 0 1 0 0 1 0 0 1 1 1 1 0 0 0 1 1 2 0 1 1 0 0 0 2 1 1 1 1 1 2 1 2 3 3 1 1 1 2 3 1 3 2 2 1 0 1 1 4 4 4 1 0 4 0 0 1 1 2 1 3 2 0 3 4 1 1 1 1 3 2 0 1 3 2 1 2 1 0 3 3 2 5 4 2 5 3 4 2 2 5 3 3 3 3 5 5 8 7 14 12 28 22 24 23 36 33 26 32 27 26 18 30 24 15 13 19 15 17 6 5 7 5 4 3 5 3 1 4 4 9 5 3 1 4 0 0 6 2 5 3 3 3 1 2 3 2 4 1 5 5 3 8 2 1 1 4 1 7 5 6 6 4 4 3 2 6 3 3 3 3 1 3 4 5 4 3 4 3 1 2 3 1 2 1 2 2 6 5 2 2 2 4 2 2 0 2 3 3 2 7 4 4 1 4 2 0 3 1 1 2 1 2 3 1 3 2 2 4 3 1 4 0 0 4 2 2 2 1 0 0 0 0 0.116000 2.500 2.500 6.600 745364 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 1 2 1 1 2 1 1 1 0 1 0 2 0 1 1 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 1 2 3 0 1 4 4 0 4 0 1 0 1 3 3 0 2 1 2 3 2 1 1 1 2 0 4 0 0 4 5 2 5 4 1 3 5 5 4 0 4 4 2 3 2 3 5 2 2 4 2 3 4 2 3 3 3 3 3 2 4 12 10 13 14 19 22 23 24 36 19 32 25 25 36 24 18 20 21 14 18 13 8 6 9 2 9 5 2 5 3 4 4 3 3 0 4 3 2 5 3 4 2 2 6 3 4 0 2 4 1 3 4 7 4 5 3 2 4 5 5 3 4 4 4 2 3 2 4 4 2 1 5 7 1 5 2 4 1 5 5 3 4 4 3 2 4 2 4 0 6 2 3 4 1 2 2 2 4 1 4 2 2 2 5 6 5 1 4 4 2 3 3 3 1 4 3 4 2 6 2 5 3 2 2 1 3 2 2 5 1 1 0 0 1 0 0 0 0.118000 2.550 2.550 6.700 791846 4 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 1 1 0 0 0 0 0 1 0 0 0 1 1 0 1 0 1 0 1 1 0 1 0 1 4 1 2 3 0 3 1 0 1 1 1 0 3 1 2 1 1 1 0 0 1 1 1 3 1 3 2 3 1 2 2 1 3 2 4 1 4 0 2 4 1 4 3 2 1 1 2 1 3 2 3 3 2 1 1 5 3 3 3 3 2 3 4 3 5 3 1 1 2 2 3 5 1 2 1 1 4 4 6 9 6 6 13 17 21 20 24 22 25 20 29 23 28 30 26 27 18 20 17 16 17 12 10 8 5 6 6 6 4 3 1 2 4 6 9 2 2 3 5 7 6 2 3 8 5 4 5 6 4 6 5 3 5 3 2 5 3 2 8 3 5 4 5 3 5 4 3 4 8 4 3 8 3 3 3 1 1 2 2 5 4 7 3 2 3 3 2 2 3 6 3 2 2 1 1 5 2 5 6 3 5 3 4 1 3 1 2 1 0 4 1 4 2 2 2 3 1 1 1 1 3 2 0 1 6 1 1 0 2 1 0 1 0 0 0 0 0.120000 2.600 2.600 6.800 833394 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 2 1 1 1 2 1 0 0 0 1 0 1 0 0 0 1 0 0 1 1 2 1 0 0 0 0 0 2 2 0 3 1 0 0 2 1 1 1 1 0 1 2 1 5 0 1 0 2 2 1 2 0 4 2 1 4 3 4 2 2 1 2 1 5 2 3 1 3 0 2 2 2 2 3 4 0 4 2 3 3 4 5 2 2 6 3 4 5 5 5 3 4 6 5 1 3 0 5 4 5 1 3 2 2 6 18 13 17 27 27 21 28 28 24 26 27 29 23 21 16 17 19 22 14 11 9 5 14 7 7 6 4 4 12 3 6 4 5 4 6 4 2 0 1 8 1 6 8 5 2 3 4 5 6 4 2 5 8 3 1 1 6 3 7 8 4 1 6 5 2 8 11 5 6 5 6 2 4 5 1 2 7 2 2 5 5 6 3 3 2 3 8 5 1 9 3 3 2 3 6 3 5 3 2 4 6 3 1 3 5 4 4 4 6 3 3 5 0 2 2 5 1 3 2 2 1 4 2 0 2 2 2 2 4 1 2 1 2 1 1 0 0.122000 2.650 2.650 6.900 876007 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 2 1 1 1 1 2 2 1 0 0 1 0 0 0 1 1 0 0 0 2 0 0 4 1 0 2 1 2 0 1 2 0 1 3 2 1 0 1 1 0 1 2 1 0 2 3 3 5 3 3 3 0 1 4 0 1 5 3 4 3 1 2 2 2 4 1 3 3 3 2 3 2 3 2 1 4 4 2 2 5 5 3 4 1 2 1 2 4 2 4 7 2 4 4 2 7 3 5 7 5 3 6 8 10 10 18 21 22 24 14 25 27 29 31 22 25 24 21 27 20 19 22 19 14 13 14 10 5 7 3 4 5 5 3 1 4 3 8 4 5 4 0 3 4 3 4 1 7 6 1 1 3 4 4 3 4 3 6 4 3 4 2 4 4 3 5 6 5 1 1 6 2 6 6 3 5 5 3 2 6 5 4 3 4 6 4 3 5 5 6 5 6 2 4 2 1 2 2 4 2 7 6 2 1 3 1 5 2 1 2 4 3 3 3 2 5 2 4 1 4 3 2 2 5 5 1 1 3 3 2 2 2 2 1 0 0 0 0 0 0.124000 2.700 2.700 7.000 925764 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 2 1 3 0 1 1 0 0 0 0 0 1 1 1 1 0 0 0 1 1 0 1 2 0 0 3 2 0 1 2 1 1 2 0 2 1 2 2 0 0 2 3 2 3 2 2 3 2 2 4 0 2 0 5 1 3 2 3 1 2 3 2 0 6 4 3 6 2 5 0 5 2 1 4 4 5 7 4 2 3 5 2 0 2 5 2 4 7 4 4 4 8 5 3 1 7 2 2 1 5 5 5 14 19 16 22 18 30 29 25 36 23 23 22 25 25 27 26 23 14 20 16 16 10 6 6 6 4 2 6 6 6 6 6 4 6 1 0 3 4 4 5 2 4 3 2 4 4 5 5 5 6 10 6 3 6 8 5 5 8 7 4 6 4 3 4 8 5 5 7 4 6 3 5 8 4 3 4 4 3 4 3 1 3 3 7 2 4 8 3 6 4 3 3 2 5 4 4 3 7 4 5 4 4 3 4 7 2 3 3 4 3 0 2 2 4 3 4 2 4 2 2 6 4 4 6 6 1 5 1 1 2 1 0 0 0 0 0 0.126000 2.750 2.750 7.100 969560 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 0 1 2 0 2 0 2 2 0 1 1 1 0 0 1 0 1 1 1 1 2 0 1 2 2 1 2 0 0 1 0 1 0 2 1 0 1 0 1 1 2 0 3 0 3 4 3 1 3 2 0 4 0 1 2 0 3 1 1 2 3 2 2 2 5 1 7 1 5 1 5 4 2 0 0 1 2 1 3 2 3 3 5 4 10 10 2 5 11 4 1 2 1 7 3 5 4 4 1 5 10 8 7 9 9 20 20 21 33 21 28 20 27 32 21 29 22 20 24 15 13 27 14 13 15 10 9 3 11 6 7 5 3 6 8 5 4 4 1 3 3 5 2 7 3 6 6 1 6 4 6 5 3 4 2 4 3 3 9 4 5 4 4 5 2 3 10 4 3 2 6 10 6 3 6 5 5 5 4 8 8 5 4 3 6 4 4 2 4 4 4 5 7 4 4 4 4 5 2 2 3 4 5 2 1 3 2 6 2 7 7 1 6 4 4 6 5 5 4 0 2 2 3 2 7 5 0 4 1 1 4 6 1 0 3 2 0 0 1 0.128000 2.800 2.800 7.200 1022713 5 0 0 0 0 0 0 0 0 0 0 0 0 1 0 2 0 0 0 1 0 1 1 0 0 1 1 1 0 0 0 2 1 0 0 4 0 0 1 2 3 1 1 0 1 0 1 0 3 1 1 1 2 2 1 1 1 3 1 0 2 4 2 1 2 1 2 0 3 1 3 2 1 5 2 1 3 1 2 1 5 3 2 1 2 5 3 8 2 3 2 5 5 4 3 6 4 4 4 3 2 3 8 4 3 4 5 4 5 4 7 6 5 3 3 3 5 2 9 10 7 9 12 11 13 17 15 22 19 33 24 28 30 26 21 24 22 27 20 26 16 10 10 9 20 10 7 4 5 7 7 2 7 5 3 5 1 6 1 5 7 5 6 3 1 5 1 1 3 4 8 6 3 9 5 5 3 6 7 4 6 7 6 4 2 4 6 2 3 6 5 6 7 6 4 4 9 6 8 6 9 7 1 2 6 2 7 5 4 4 4 4 5 5 4 4 3 6 3 5 3 6 4 3 6 6 2 5 2 8 4 5 3 6 5 4 5 8 4 3 5 6 5 5 2 8 1 2 2 5 4 1 3 0 0 0 0 0 0.130000 2.850 2.850 7.300 1081669 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 5 0 0 2 2 0 0 1 0 0 0 1 1 0 2 0 2 2 2 1 0 1 0 2 2 3 1 1 0 2 0 1 0 2 1 1 2 2 0 1 4 3 0 2 1 1 0 2 5 2 1 0 1 3 2 5 2 1 2 5 2 3 4 3 6 6 6 4 6 6 3 1 3 2 3 4 7 5 2 9 7 4 1 4 4 3 2 2 2 7 4 8 4 7 4 6 8 5 1 8 6 10 18 21 18 15 21 24 21 26 22 30 28 27 23 22 21 17 25 20 17 13 17 9 12 7 8 5 4 4 5 5 2 4 1 1 2 5 7 6 4 9 7 7 5 5 5 5 5 2 4 5 3 6 8 2 4 9 4 10 5 1 4 5 5 5 10 3 2 8 6 5 7 3 13 3 3 6 5 1 4 5 9 5 2 7 4 5 6 3 5 6 5 4 5 9 6 4 3 4 4 4 5 8 5 5 0 3 6 3 4 3 7 5 6 4 3 3 6 8 4 1 3 1 2 7 3 4 6 6 1 3 4 1 0 1 0 0 0.132000 2.900 2.900 7.400 1131887 3 0 0 0 0 0 0 0 0 0 1 0 0 1 2 1 1 0 0 0 1 2 2 1 1 0 2 1 1 0 1 1 1 0 2 2 3 1 0 1 0 1 0 2 0 2 0 1 4 0 1 2 2 0 0 0 2 3 0 1 2 3 0 1 2 3 5 6 2 2 3 1 4 4 8 4 3 3 3 7 2 2 5 7 4 1 2 4 8 1 5 2 7 3 4 2 9 6 5 5 6 2 2 3 6 2 5 6 7 7 2 8 3 3 3 3 6 6 5 3 10 15 15 17 19 13 29 20 23 22 34 28 28 33 20 20 22 17 22 18 15 19 14 11 9 13 6 6 13 4 2 9 8 8 7 6 5 6 4 4 9 6 2 8 9 7 2 6 3 7 3 6 3 7 4 4 5 4 5 6 4 7 5 4 10 2 6 6 8 3 6 6 9 5 8 8 7 6 4 8 5 7 5 5 7 3 5 5 5 10 7 3 8 7 5 7 2 4 4 6 4 10 7 6 4 4 4 4 3 2 4 2 6 5 9 7 3 2 6 2 5 1 5 6 2 2 1 9 2 5 2 5 1 0 0 0 1 1 0.134000 2.950 2.950 7.500 1185706 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 3 2 1 0 1 1 0 0 0 0 0 1 0 1 1 2 0 1 0 1 2 0 0 0 1 1 0 1 1 1 0 2 2 0 1 3 3 2 3 0 0 2 2 3 2 1 1 3 0 0 1 1 3 4 3 1 1 9 1 4 0 1 3 4 1 3 2 6 4 7 7 3 2 8 5 2 5 2 4 6 7 3 7 7 8 4 7 2 4 7 7 9 9 2 5 5 8 3 5 7 3 6 10 6 10 15 10 13 14 29 21 23 37 26 20 28 20 16 24 25 16 19 21 20 20 17 11 10 12 8 7 7 5 5 5 4 5 6 7 3 6 5 7 5 11 9 6 8 11 6 4 6 8 8 7 7 7 4 5 4 8 5 4 3 4 8 10 7 9 4 7 6 8 9 7 3 5 7 7 6 2 6 4 7 3 9 8 12 7 6 6 6 4 5 7 2 4 7 3 2 4 4 7 1 4 5 0 4 6 3 10 8 5 4 3 4 5 7 5 7 5 7 3 5 2 5 6 4 5 2 4 1 6 6 2 4 2 0 0 1 0 0.136000 3.000 3.000 7.600 1238426 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 2 4 0 2 0 2 2 0 1 1 1 0 2 1 1 2 1 0 1 1 0 3 1 0 0 1 0 1 0 0 2 1 1 0 4 0 2 6 3 3 4 0 3 1 2 4 0 4 4 0 1 5 2 2 5 1 3 4 3 3 5 2 4 4 6 2 5 3 4 5 4 5 6 7 5 6 2 8 3 4 7 2 4 4 3 7 6 5 1 4 8 3 7 10 3 3 6 1 5 3 8 11 5 7 15 11 15 17 21 23 21 24 28 16 21 29 15 22 27 28 20 13 19 13 7 15 10 11 9 6 8 8 4 7 5 4 6 5 10 6 7 8 9 3 5 5 9 5 9 4 4 4 3 5 7 4 10 6 8 4 9 8 4 6 7 9 11 6 8 3 5 8 12 3 6 9 7 11 9 6 7 4 7 7 7 2 5 4 5 0 2 9 5 5 5 10 7 5 6 3 9 4 4 13 2 7 5 7 4 7 2 0 4 5 4 4 6 8 1 2 5 6 4 7 3 11 4 3 3 5 5 4 4 3 1 4 2 2 1 1 0 0.138000 3.050 3.050 7.700 1299809 6 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 1 2 1 1 0 0 1 0 0 2 0 1 2 0 0 3 0 0 1 3 1 2 0 2 0 1 1 2 1 2 3 2 1 2 5 2 2 2 4 3 2 5 3 0 3 2 4 5 4 3 0 5 4 1 4 3 8 6 4 4 7 4 5 4 3 6 5 6 10 3 6 6 2 6 3 4 4 3 6 7 6 8 3 4 7 5 4 9 2 4 8 5 9 8 3 7 5 7 7 13 7 11 15 17 16 18 18 18 20 17 26 25 19 20 26 31 22 18 20 18 14 11 16 4 7 11 10 8 9 9 6 3 8 8 7 5 6 10 3 5 6 6 3 12 7 8 8 2 10 4 13 9 9 12 4 5 9 7 9 5 7 4 8 9 6 7 8 10 8 7 5 7 11 6 4 4 4 6 4 9 4 5 9 10 7 4 12 7 4 9 5 10 10 6 8 4 7 2 4 7 2 6 8 4 11 3 3 9 7 6 7 3 8 7 4 8 5 3 7 4 5 5 7 4 6 7 5 5 3 5 2 5 4 1 2 0 0 1 0.140000 3.100 3.100 7.800 1361810 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 3 2 1 0 0 0 1 1 1 2 0 0 0 0 1 0 2 2 2 1 0 0 3 3 0 2 0 6 2 3 1 0 3 3 1 2 2 5 3 5 3 3 2 2 7 3 2 2 3 4 2 3 4 4 1 3 7 4 5 4 2 3 5 4 2 1 3 6 3 4 3 8 7 6 5 3 5 11 5 5 3 3 7 3 6 4 4 2 4 4 4 1 5 5 9 6 6 9 3 10 8 6 8 3 10 8 16 16 13 18 23 29 25 19 19 20 27 19 22 27 24 21 15 18 11 20 21 17 12 5 18 6 12 7 9 11 7 12 11 4 8 8 4 8 7 7 2 6 4 4 9 6 9 3 4 7 7 7 4 10 4 11 5 8 8 8 5 4 4 8 6 4 9 8 12 12 8 5 8 3 10 8 7 5 3 5 6 8 5 6 10 7 2 11 2 5 5 6 8 10 2 7 5 5 14 2 7 3 9 3 5 2 8 2 3 4 4 7 9 5 4 7 6 7 5 6 3 5 4 7 6 7 7 9 3 0 2 1 1 1 0 0 0.142000 3.150 3.150 7.900 1429499 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 1 2 1 1 0 0 0 3 0 2 2 1 0 3 0 2 1 3 0 0 1 1 3 1 2 4 1 5 3 5 1 0 7 1 3 2 3 2 2 2 3 0 0 1 3 6 3 2 2 4 4 4 6 4 3 6 4 10 3 7 2 5 4 7 4 5 8 4 7 4 1 7 11 5 2 10 2 11 3 7 8 10 9 6 3 5 3 6 3 10 11 5 5 9 7 10 8 9 5 15 11 9 18 18 15 24 17 23 17 19 25 17 24 18 37 16 17 21 17 14 20 17 15 15 9 4 11 7 3 8 10 8 8 6 8 3 4 5 8 4 6 3 9 9 6 2 10 4 4 3 8 4 9 1 7 5 9 7 10 9 10 4 6 5 8 6 6 10 10 6 5 7 6 6 10 5 7 8 8 8 7 7 11 12 8 3 10 6 9 13 11 4 6 7 6 3 10 5 8 4 7 7 7 5 8 4 9 5 5 7 6 6 7 11 11 7 8 5 3 5 7 7 10 3 3 6 5 7 9 2 3 7 1 0 0 0 0 1 0.144000 3.200 3.200 8.000 1493946 3 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 2 3 0 0 1 2 1 1 1 4 1 0 1 0 1 2 1 3 1 1 1 1 2 1 1 3 2 6 0 4 0 1 4 2 4 5 2 1 3 0 2 2 4 2 3 2 4 3 5 4 4 4 1 5 1 3 4 5 6 4 7 2 8 8 8 5 3 6 0 7 3 2 2 5 7 5 7 5 8 9 6 4 3 6 8 6 10 2 5 6 3 3 6 6 6 6 17 5 10 6 6 11 11 13 12 21 26 18 24 21 24 23 30 18 22 20 24 19 13 17 25 22 17 15 8 13 7 10 8 9 6 7 9 8 7 8 9 7 7 6 12 5 9 9 12 9 12 6 9 7 10 7 7 4 9 7 4 2 7 4 5 8 8 9 7 6 7 5 9 4 8 13 6 5 4 7 9 6 7 7 9 4 4 5 8 10 9 10 6 6 7 9 12 11 8 8 9 11 5 8 7 5 5 8 5 9 10 5 5 11 11 6 8 8 4 8 5 5 5 4 7 4 5 6 5 6 6 7 7 4 2 6 3 2 1 0 0 0 0 0 0.146000 3.250 3.250 8.100 1562352 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 0 2 0 1 2 1 1 0 0 1 0 1 2 0 0 0 3 1 2 0 4 4 2 0 0 2 3 2 0 1 3 3 4 0 1 4 3 3 4 5 5 4 2 1 4 2 5 3 2 7 6 3 5 6 5 5 5 1 5 2 7 4 8 7 4 6 5 7 5 3 5 8 1 6 4 6 8 7 6 7 6 3 4 6 3 5 8 4 10 3 3 11 6 5 3 9 6 4 3 17 9 11 11 24 13 15 14 25 26 26 21 17 32 32 22 18 25 29 29 27 24 21 12 23 14 12 11 9 17 7 9 11 3 7 6 5 5 12 3 6 8 7 4 7 11 10 8 9 5 8 2 10 9 8 10 10 7 7 4 7 5 7 7 9 10 8 7 7 16 6 8 10 5 6 6 12 12 7 11 11 8 9 7 8 12 10 7 8 7 11 8 9 7 7 4 9 4 7 14 9 8 8 13 9 8 7 13 5 9 5 7 4 9 5 7 8 7 8 7 3 10 9 3 4 4 4 5 2 6 6 3 5 10 4 4 2 3 0 1 0 0 0.148000 3.300 3.300 8.200 1630559 3 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 4 2 1 1 1 2 1 2 0 2 1 5 0 1 1 4 0 2 1 4 5 3 0 1 1 1 2 1 3 3 3 1 1 1 1 1 3 4 6 6 8 8 4 3 2 7 2 2 1 7 4 4 5 1 10 6 4 4 4 3 3 3 6 11 6 4 5 4 8 5 5 9 4 5 5 7 6 4 13 12 3 6 7 5 2 7 9 7 8 8 4 7 6 4 10 6 8 9 9 9 13 15 17 23 25 13 16 24 22 26 21 27 24 24 21 21 21 15 17 22 25 21 22 17 14 11 8 12 5 9 7 8 5 11 10 6 6 5 9 13 10 9 8 8 8 6 4 9 10 9 9 7 8 7 5 7 8 14 13 5 14 5 12 11 8 9 6 5 4 9 13 7 10 13 11 11 8 5 9 10 8 7 6 7 13 3 13 8 7 13 17 5 8 5 10 7 12 7 6 6 9 7 8 8 11 8 11 9 11 11 8 5 6 10 4 9 3 10 8 7 10 8 7 8 10 10 7 4 11 5 7 8 2 4 3 0 0 1 0 1 0.150000 3.350 3.350 8.300 1707576 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 2 1 2 1 0 2 0 2 3 1 3 2 2 2 2 0 2 1 4 3 2 2 3 1 2 1 0 2 2 4 2 5 3 3 5 2 8 4 5 4 2 3 6 7 6 1 0 7 4 7 7 6 5 4 3 4 6 6 7 6 2 7 4 4 2 5 5 6 9 3 3 3 6 6 5 3 5 7 8 8 6 8 8 6 8 3 9 6 6 8 8 6 4 8 6 6 10 4 11 6 11 15 23 16 8 17 20 21 19 24 15 14 19 21 30 25 21 15 19 16 18 21 21 15 14 12 16 8 10 12 7 10 9 8 10 10 7 9 8 10 12 6 6 9 11 6 5 9 12 6 7 12 7 5 6 8 5 9 4 11 9 8 8 10 7 6 10 7 11 13 7 4 13 11 8 11 9 16 6 12 11 10 10 19 2 9 11 8 7 8 8 6 13 6 10 12 12 9 12 9 9 8 7 7 9 6 12 8 4 9 9 8 5 7 8 9 5 12 5 7 5 9 10 9 10 3 6 6 8 7 11 3 5 5 4 2 0 0 0 0 0.152000 3.400 3.400 8.400 1777231 3 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 1 1 0 0 1 1 3 1 0 3 4 2 3 3 3 3 3 2 1 1 1 1 3 3 0 1 8 0 0 5 3 7 4 4 4 4 4 3 5 2 2 5 3 6 1 7 6 1 2 2 5 2 1 6 6 8 7 7 5 10 4 1 6 9 3 4 5 3 5 8 4 9 8 11 8 3 2 7 7 9 10 9 10 8 6 8 6 8 7 10 8 7 3 8 4 10 7 6 8 9 6 5 16 9 19 24 23 17 23 24 22 30 21 15 23 27 20 20 20 18 20 23 18 17 15 19 17 18 13 9 4 4 7 12 7 10 4 8 6 10 5 6 13 2 3 8 7 8 7 3 11 8 7 9 7 19 7 8 9 6 14 8 8 11 10 11 13 14 10 16 8 9 13 8 9 9 12 7 12 11 6 9 15 5 9 9 9 11 11 13 6 10 6 4 12 9 9 12 11 8 6 9 16 10 10 10 8 10 10 6 7 4 1 15 6 8 4 9 13 11 8 10 11 9 8 3 3 6 6 7 9 4 6 8 7 4 2 1 2 2 1 0 0.154000 3.450 3.450 8.500 1849489 6 0 0 0 0 0 0 0 0 0 0 0 1 1 3 0 1 2 2 0 1 4 1 1 0 1 0 2 1 0 0 1 1 1 1 6 3 6 1 3 1 3 3 0 6 0 4 2 7 4 6 4 4 3 7 4 5 7 5 5 2 3 9 9 2 5 5 3 9 4 2 7 6 2 8 2 5 7 12 6 5 4 5 10 4 12 10 6 4 14 7 9 10 11 7 7 7 7 3 9 7 4 3 8 7 5 7 9 6 8 9 6 8 8 12 6 5 11 12 13 11 13 21 26 19 23 25 18 23 22 23 23 18 27 20 15 20 25 24 19 18 12 14 13 15 8 15 10 11 7 9 13 11 12 13 11 11 7 11 13 6 5 10 6 6 10 8 14 5 14 11 8 5 9 7 10 10 8 7 15 13 3 13 12 18 15 7 10 9 10 8 15 9 6 8 9 10 10 9 5 7 7 5 10 11 13 12 12 12 10 6 17 10 11 9 4 8 7 6 6 9 12 8 16 18 7 5 10 8 12 10 15 6 13 11 6 10 16 10 11 16 8 9 5 11 10 14 11 5 2 5 7 3 1 1 0 1 0 0.156000 3.500 3.500 8.600 1920727 4 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 2 1 2 0 3 0 1 1 0 1 0 3 0 4 4 1 3 1 2 3 3 4 3 1 2 3 9 5 2 3 7 3 3 6 5 2 6 1 4 3 2 3 6 5 1 8 3 8 5 3 7 6 13 11 9 5 8 7 7 5 8 7 4 8 6 4 10 4 6 5 6 9 9 12 6 7 10 9 9 8 8 3 8 9 8 8 2 12 11 13 8 13 7 8 6 6 9 6 8 16 13 14 16 16 22 20 21 21 17 20 18 19 22 20 11 20 22 21 14 19 15 23 17 15 12 14 19 16 10 11 14 11 9 11 9 12 8 16 14 9 6 18 10 11 7 10 11 17 10 13 8 10 12 9 12 7 7 10 10 11 11 9 8 8 14 10 10 9 14 9 14 13 9 19 16 17 4 11 8 12 11 10 21 6 10 8 9 12 9 7 7 12 7 16 14 10 13 6 13 8 9 10 6 10 8 7 10 4 6 11 19 12 6 7 5 8 11 10 12 13 9 6 10 5 11 11 4 14 10 7 2 6 5 1 2 5 1 1 0 0 0.158000 3.550 3.550 8.700 1999833 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 2 2 3 2 2 2 1 2 3 0 1 0 1 3 2 0 0 3 2 3 2 5 7 0 3 4 1 10 7 7 4 5 2 3 4 3 8 3 6 4 4 4 8 2 3 4 5 5 7 1 6 7 8 1 6 8 1 4 4 11 9 4 7 11 9 10 5 6 8 4 3 9 7 9 11 5 5 8 8 4 8 7 8 11 9 12 6 4 13 4 12 10 6 9 11 10 11 10 11 11 11 14 15 14 23 18 17 29 16 26 23 15 19 14 18 19 22 31 13 21 20 12 16 15 14 18 17 15 8 12 14 13 10 10 10 10 10 13 11 6 8 11 8 14 8 10 11 11 8 10 13 5 14 7 12 9 10 10 12 15 18 8 6 9 9 12 8 9 20 14 16 10 11 14 5 5 13 6 11 9 11 15 6 9 13 11 7 8 7 10 8 16 12 11 8 10 14 11 17 11 8 16 13 9 10 5 10 17 13 14 16 8 10 9 11 5 10 9 10 12 8 11 12 11 8 6 7 12 15 13 12 7 13 5 0 3 2 0 0 0 0 0.160000 3.600 3.600 8.800 2073149 3 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 2 1 2 1 2 2 1 0 2 2 1 0 3 6 4 5 5 2 2 2 5 5 3 6 4 6 4 5 2 4 4 3 2 4 6 3 3 6 5 7 4 5 7 5 3 5 6 13 5 3 10 5 9 7 4 5 6 5 10 6 5 5 6 6 4 14 7 6 11 6 9 10 9 8 5 3 8 10 10 6 6 8 9 5 6 14 7 11 10 9 9 11 13 8 4 5 10 12 6 16 8 8 7 19 20 23 10 16 27 25 23 19 26 21 16 20 21 24 18 25 8 11 13 16 18 13 22 18 9 16 4 16 10 12 13 9 7 9 8 17 11 10 13 10 14 4 9 12 16 8 9 16 17 13 11 14 8 8 13 9 11 15 10 11 14 8 6 4 9 11 18 9 9 8 9 15 11 11 11 9 6 13 13 10 7 8 10 15 14 9 7 4 10 12 17 10 14 13 10 10 12 20 9 7 6 11 15 11 10 8 9 6 10 13 17 6 8 9 6 13 13 16 10 15 5 11 14 11 12 6 5 12 9 4 9 2 4 1 1 0 0 0 0.162000 3.650 3.650 8.900 2156456 5 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 2 0 1 1 3 2 3 4 3 3 2 1 3 6 5 2 3 4 4 3 6 2 3 4 4 5 5 3 4 1 4 5 9 3 3 4 3 3 8 5 6 12 2 10 3 4 6 8 9 8 8 2 2 7 5 8 2 8 9 7 2 6 8 6 5 8 2 7 5 6 13 5 6 8 11 6 10 5 6 3 8 10 11 10 10 14 10 11 8 11 8 12 6 12 5 15 12 13 10 13 13 18 23 12 21 18 21 23 20 30 20 23 26 24 24 21 21 29 19 21 16 23 20 13 19 13 16 11 15 13 13 11 8 11 14 14 13 4 16 15 18 13 9 19 8 11 6 9 14 8 13 12 13 10 13 10 14 11 13 11 8 10 13 11 11 14 11 8 14 11 10 9 14 12 14 18 8 12 7 13 12 10 14 14 8 12 17 11 13 9 12 12 15 7 9 13 17 11 11 11 12 17 12 11 16 15 8 9 12 7 13 15 11 16 7 10 7 14 5 18 10 10 8 8 6 6 13 14 6 9 11 9 9 3 5 1 1 3 0 0 0.164000 3.700 3.700 9.000 2234753 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 4 1 4 2 1 3 1 1 3 2 3 3 1 3 6 2 4 4 3 3 3 6 5 2 6 4 1 3 3 7 1 4 4 6 12 4 5 2 6 4 9 3 1 8 11 5 2 7 6 3 8 4 7 3 8 3 9 6 7 8 9 2 7 6 9 6 15 6 9 5 9 4 9 17 15 10 2 10 6 8 12 12 11 12 10 9 7 11 8 7 5 11 10 14 16 7 7 7 13 15 10 16 17 21 19 14 18 24 19 27 27 24 20 22 24 21 20 14 24 17 17 18 32 15 12 13 15 12 8 14 11 11 19 11 14 15 18 10 5 12 11 11 9 15 9 7 9 16 12 9 12 10 15 9 18 7 11 12 14 7 20 8 10 13 14 11 6 6 9 11 8 10 16 8 17 13 17 9 16 11 10 9 13 20 17 14 12 10 13 11 9 9 17 20 10 16 8 14 13 14 18 15 15 8 10 12 11 22 12 13 9 12 9 11 14 19 12 12 8 8 12 11 19 11 11 12 15 11 15 13 9 9 10 9 4 9 4 2 1 0 0 0.166000 3.750 3.750 9.100 2327990 3 0 0 0 0 0 0 0 0 0 0 0 0 0 3 2 2 0 1 2 2 1 1 0 0 3 1 4 2 6 4 2 4 3 2 5 5 2 3 1 3 1 2 10 2 7 4 3 4 3 3 4 3 10 6 9 6 3 8 5 5 3 4 4 6 8 4 4 7 5 5 11 14 5 3 6 8 8 7 10 11 7 17 7 11 10 8 7 8 12 13 11 12 6 13 9 7 7 6 5 8 13 10 10 14 11 11 8 12 15 14 9 13 10 9 18 13 18 12 23 14 17 24 15 23 25 31 19 17 29 19 19 19 26 25 19 17 22 19 19 19 11 11 12 22 21 8 10 18 10 14 19 17 13 14 10 6 9 10 15 11 5 13 13 11 11 17 16 9 7 14 7 19 6 10 13 7 12 18 14 7 12 15 13 13 9 13 13 13 12 12 14 12 19 10 16 18 18 12 8 10 10 9 7 14 9 11 13 12 8 15 12 11 10 12 11 17 15 19 14 14 12 7 7 12 11 15 16 12 11 12 10 19 19 12 14 12 15 11 20 13 7 18 9 15 19 16 11 5 9 8 6 2 4 0 2 0 1 0.168000 3.800 3.800 9.200 2406866 3 0 0 0 0 0 0 0 0 0 0 1 0 2 0 1 0 2 3 2 3 1 2 1 2 2 5 2 1 2 3 2 2 2 5 3 5 3 3 1 3 6 8 6 1 3 9 6 3 6 10 5 5 7 4 5 7 12 9 5 7 5 6 6 8 3 5 4 7 8 5 6 5 8 13 4 10 2 10 9 7 7 16 9 10 9 13 8 12 9 13 15 9 15 9 10 11 6 6 6 7 7 6 8 15 9 8 9 6 12 12 11 14 12 11 13 8 17 18 18 11 14 19 14 25 21 15 10 15 19 27 23 22 24 17 19 18 12 16 22 21 25 9 25 15 19 15 21 15 8 11 13 12 10 12 7 13 11 17 11 13 10 16 19 14 23 11 8 12 13 10 9 17 4 14 10 7 10 17 14 11 11 20 18 13 8 12 6 8 13 12 23 15 14 15 16 9 14 9 13 14 17 11 17 11 10 15 17 11 6 12 12 14 15 17 12 16 16 8 17 15 15 10 15 11 10 15 12 13 9 12 9 12 15 12 6 18 7 15 14 12 21 18 11 10 18 11 19 11 7 11 3 2 5 4 0 1 1 0.170000 3.850 3.850 9.300 2508471 7 0 0 0 0 0 0 0 0 0 0 0 0 0 1 3 1 2 1 4 3 3 1 2 7 0 3 2 2 2 2 5 2 3 2 3 3 4 3 7 3 5 3 4 4 6 2 3 10 4 11 3 13 7 7 5 6 3 8 10 6 6 4 10 11 4 12 7 8 9 7 7 8 4 6 7 9 9 5 9 11 5 14 9 10 7 9 8 8 5 6 11 13 14 10 10 10 10 8 9 9 9 9 14 14 13 11 8 18 9 10 9 16 12 13 15 13 10 17 16 20 14 22 20 26 29 29 27 24 20 37 21 24 13 18 13 28 24 22 25 21 13 14 15 9 11 18 8 16 17 16 13 12 16 11 11 17 15 11 15 10 11 12 13 12 12 20 15 14 15 16 12 17 15 15 12 10 14 14 17 15 19 15 13 13 11 12 16 14 17 16 8 16 12 8 14 13 13 10 10 9 12 11 19 20 13 11 4 15 11 14 11 20 18 18 13 20 12 20 21 15 15 12 13 18 18 11 16 9 14 9 18 11 10 11 20 11 13 17 13 13 12 14 16 10 12 12 23 12 11 12 8 8 1 0 1 2 0 0.172000 3.900 3.900 9.400 2591210 3 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 4 4 3 2 1 3 3 2 3 0 3 6 1 3 1 5 5 4 3 9 9 0 4 7 5 3 5 5 8 7 3 3 5 5 8 5 11 10 8 10 3 6 6 6 7 7 8 8 12 9 6 10 8 7 10 8 8 10 4 6 12 20 4 6 11 7 9 10 7 5 10 6 12 11 7 13 13 16 12 6 8 14 13 9 7 5 14 17 17 10 12 11 6 13 11 17 3 23 13 21 12 21 28 11 23 30 28 23 24 26 26 17 21 15 27 23 33 16 22 25 11 20 22 23 21 20 7 21 13 16 12 16 16 13 18 18 9 13 16 15 9 20 13 19 15 8 9 11 14 13 10 9 10 16 15 14 17 15 19 16 12 14 12 14 14 16 19 19 4 24 8 12 15 16 11 15 14 20 14 13 13 14 16 19 14 13 19 14 18 23 15 15 4 14 17 14 8 10 15 20 11 15 19 12 9 13 12 11 16 12 16 13 14 16 13 16 16 19 19 12 11 10 19 15 15 14 12 5 11 18 17 10 13 12 9 6 2 0 0 1 0 0.174000 3.950 3.950 9.500 2675515 3 0 0 0 0 0 0 0 0 0 0 0 2 0 1 1 0 2 1 2 3 3 1 3 1 3 7 5 3 6 4 3 9 4 5 2 5 3 3 3 6 9 5 5 2 6 8 5 8 4 8 5 6 5 6 4 6 3 7 11 6 9 9 3 6 6 7 6 8 7 9 12 18 6 9 8 11 11 8 14 15 15 11 15 13 9 19 10 15 14 9 4 18 5 8 10 8 10 13 9 12 11 8 8 12 6 15 8 9 9 18 7 17 21 9 13 18 14 21 24 18 22 17 26 15 21 23 25 19 26 23 20 27 17 27 20 26 15 22 15 19 15 16 24 12 15 24 13 13 17 11 7 10 21 15 15 16 13 20 22 12 16 12 16 15 14 18 11 12 14 14 24 10 13 16 19 8 11 18 19 15 15 23 16 16 11 12 18 11 13 14 16 10 14 13 18 12 15 15 14 8 11 17 12 22 13 12 14 15 10 11 15 19 15 12 17 8 21 23 13 19 11 8 12 15 11 14 15 19 15 10 17 9 16 14 18 14 16 14 14 23 14 14 13 16 12 14 15 14 9 14 7 5 2 3 1 1 1 0.176000 4.000 4.000 9.600 2779386 5 0 0 0 0 0 0 0 0 0 0 0 0 2 2 3 0 1 3 0 6 2 6 3 1 5 0 4 1 6 5 1 6 3 6 5 6 2 5 4 5 3 9 8 5 7 5 8 4 12 8 12 6 8 5 7 5 7 10 5 5 6 7 9 7 10 7 10 10 8 12 10 6 13 10 11 12 11 10 10 16 9 6 12 9 11 17 10 11 10 14 11 16 7 11 13 12 10 17 14 11 13 12 10 13 16 16 17 17 15 14 11 8 15 13 27 22 14 19 17 22 22 27 18 28 19 27 32 24 33 21 17 23 12 27 25 20 20 17 22 14 15 22 21 14 9 16 12 19 16 17 16 16 20 14 18 15 14 18 10 12 9 16 12 12 10 13 19 12 12 15 14 15 22 12 11 15 18 19 18 10 6 11 14 10 23 17 14 16 19 10 10 16 19 17 23 16 18 19 18 16 12 14 14 14 13 11 10 24 21 22 26 18 18 18 14 17 5 13 17 11 13 16 14 18 16 9 15 15 18 16 14 21 13 22 17 9 8 16 17 16 16 19 7 20 19 18 16 10 6 10 6 3 5 1 0 0 2 0.178000 4.050 4.050 9.700 2869617 3 0 0 0 0 0 0 0 0 0 0 0 2 2 2 0 1 4 1 3 2 2 1 2 3 2 2 4 4 7 5 6 5 3 6 6 5 7 8 1 5 2 3 5 5 8 10 7 6 10 9 6 8 9 7 8 10 15 4 10 5 8 8 6 11 8 8 11 7 5 8 14 5 11 7 13 10 9 7 8 9 14 12 10 9 11 6 14 15 14 13 11 9 18 18 10 14 14 10 12 16 12 9 8 14 15 6 11 11 12 10 14 12 11 18 13 13 27 16 23 23 20 21 32 20 18 25 22 24 32 25 34 19 23 21 25 22 25 19 23 19 21 16 19 16 18 9 18 6 13 12 13 18 12 8 19 14 14 11 16 13 15 14 21 11 14 14 13 11 20 14 14 26 10 22 16 18 15 20 24 18 19 19 16 14 14 14 21 13 19 18 20 13 17 11 17 14 22 17 15 15 20 8 21 15 16 16 23 17 13 19 21 20 12 15 18 15 19 15 18 17 20 15 13 14 24 18 15 15 14 18 20 19 17 19 20 21 21 15 19 19 17 11 16 16 11 23 10 20 13 10 5 10 2 3 1 1 0 0.180000 4.100 4.100 9.800 2975040 3 0 0 0 0 0 0 0 0 0 1 0 0 1 2 2 4 4 2 4 4 1 2 5 0 3 3 5 2 5 5 4 9 2 7 8 4 8 3 11 6 10 4 7 8 6 6 5 8 8 7 11 4 4 11 12 7 11 7 10 11 7 11 11 10 9 7 13 12 18 8 14 12 14 12 8 8 16 10 10 14 16 10 6 8 15 15 15 22 13 19 18 12 6 11 10 7 12 12 24 15 17 9 17 21 10 17 18 14 14 14 9 22 11 23 17 15 23 32 20 11 12 20 15 23 30 20 25 19 26 29 19 27 23 15 19 11 30 16 21 24 18 18 14 8 6 25 13 21 13 13 19 13 21 25 23 18 14 14 13 20 12 14 8 10 25 14 15 20 15 10 15 16 21 8 15 20 21 20 13 16 15 20 11 18 17 17 9 12 24 19 13 18 17 20 14 15 20 10 23 19 25 8 7 13 14 11 15 18 13 10 12 10 17 11 24 16 17 11 12 13 16 20 14 26 12 17 13 14 16 16 6 20 16 23 22 11 17 16 14 25 19 17 21 22 19 13 19 16 18 10 11 7 4 6 0 0 2 0.182000 4.150 4.150 9.900 3083416 6 0 0 0 0 0 0 0 0 0 0 0 2 1 1 4 1 3 4 3 5 6 2 1 4 2 3 5 6 6 7 2 4 1 11 7 5 2 6 6 8 9 8 12 7 11 9 6 12 7 8 9 6 6 8 11 6 6 8 11 8 11 12 11 13 9 10 7 9 6 11 9 13 12 12 8 14 15 8 9 8 8 11 22 16 6 11 16 15 9 13 12 12 13 11 15 9 9 16 14 14 12 21 12 12 12 16 19 10 15 18 8 16 14 16 16 21 30 22 9 25 19 19 26 23 33 25 22 21 19 21 20 20 21 20 26 20 29 27 25 25 21 20 25 21 21 18 14 19 15 6 20 18 16 20 16 13 13 15 15 15 15 22 16 15 15 11 21 19 11 19 13 14 15 17 21 12 18 12 22 18 21 18 13 23 15 18 9 21 11 14 23 18 21 25 18 22 15 21 23 15 15 16 19 21 18 19 21 17 13 24 23 22 19 14 20 22 15 14 14 20 20 23 13 18 15 18 20 20 24 9 12 17 21 21 12 16 17 16 16 21 26 19 15 21 22 24 15 11 13 13 6 8 1 4 0 1 0 0.184000 4.200 4.200 10.00 3174897 3 0 0 0 0 0 0 0 0 0 0 0 1 1 2 3 0 5 4 3 3 0 7 3 2 4 2 8 6 4 5 9 3 8 6 4 2 7 6 8 7 9 3 5 8 5 9 7 7 6 11 14 7 12 9 9 5 15 12 14 15 12 9 11 5 8 13 11 12 10 9 17 12 11 8 17 11 19 11 15 9 11 7 15 14 16 16 16 7 12 10 14 13 13 16 16 11 15 13 14 12 16 11 12 13 17 10 13 19 11 17 11 13 14 13 10 19 19 23 24 22 24 24 31 19 23 22 28 21 25 29 17 23 17 21 30 22 19 25 27 27 22 23 23 17 25 17 20 17 12 23 21 9 17 20 16 19 16 17 20 9 16 11 22 16 15 12 15 17 23 24 16 16 18 26 11 16 20 18 10 14 17 26 19 17 15 17 19 12 21 20 24 17 27 13 16 18 19 23 14 19 14 10 11 18 19 6 15 21 23 25 17 17 18 21 27 20 17 18 20 25 22 20 18 22 18 17 15 24 16 15 22 18 22 14 20 20 22 18 22 25 19 26 12 19 19 13 12 16 19 14 9 7 5 4 2 0 2 0.186000 4.250 4.250 10.10 3283256 3 0 0 0 0 0 0 0 0 1 0 0 1 1 4 1 5 2 5 5 3 4 6 3 2 4 7 8 2 6 6 4 10 7 8 7 5 4 4 9 8 18 10 7 6 6 13 12 10 13 10 7 15 4 7 10 13 12 8 8 13 5 14 6 9 14 9 10 16 12 13 11 8 12 11 10 13 9 11 15 17 23 18 13 10 12 11 12 14 14 14 10 12 12 16 13 15 13 13 14 18 10 13 17 14 14 14 12 12 8 18 14 23 20 16 19 16 16 16 27 18 21 19 20 19 37 22 21 22 28 24 26 18 21 28 21 22 21 21 22 16 15 13 22 22 27 22 11 13 20 10 17 16 19 20 30 18 25 8 7 22 18 17 14 23 16 17 11 16 24 19 18 22 15 15 23 16 13 15 22 14 8 12 18 13 15 22 17 15 15 17 27 21 19 21 24 17 10 12 14 19 17 22 18 19 17 28 19 15 14 16 28 17 20 15 11 22 18 19 16 21 17 24 19 22 22 20 10 20 18 18 18 21 18 23 18 32 26 21 21 22 20 22 16 17 20 22 21 17 13 13 11 9 5 0 1 1 1 0.188000 4.300 4.300 10.20 3396610 5 0 0 0 0 0 0 0 0 0 0 0 1 2 3 0 2 5 5 4 3 3 5 1 2 3 6 9 3 3 3 8 7 2 9 5 7 5 11 8 9 7 6 9 6 4 5 8 6 10 9 14 10 15 6 7 13 15 10 13 7 15 10 10 11 14 14 6 7 17 13 19 3 13 9 6 13 13 14 10 11 12 16 17 13 10 15 15 19 19 11 11 15 11 13 9 13 20 8 18 14 18 23 23 23 15 19 20 14 11 7 18 16 15 22 28 20 24 22 25 17 20 39 24 26 25 25 33 25 25 25 33 15 29 18 29 18 12 18 23 17 24 28 22 16 20 33 23 18 23 26 23 15 24 16 16 16 16 17 15 15 16 14 11 9 23 17 13 13 18 12 19 20 30 20 20 15 21 19 16 18 20 23 19 15 10 11 15 19 13 22 22 18 19 16 19 23 16 10 25 23 20 21 20 31 19 19 18 15 22 18 14 13 21 18 19 22 19 16 17 21 14 20 26 18 26 22 19 26 19 20 22 15 13 24 23 15 21 21 21 27 18 22 19 24 17 22 16 18 23 10 12 3 5 3 3 0 0 0.190000 4.350 4.350 10.30 3502025 3 0 0 0 0 0 0 0 0 0 0 0 0 3 0 3 2 3 4 4 3 4 5 10 7 6 6 4 5 12 10 6 6 13 10 6 7 14 9 6 13 10 12 16 3 9 9 7 5 6 13 11 10 8 11 19 12 14 13 16 13 14 9 12 14 13 14 16 10 14 7 16 18 16 9 15 11 20 15 10 14 14 11 14 17 10 6 16 10 15 12 17 17 20 15 7 12 23 15 8 13 12 8 16 15 20 16 16 20 14 11 20 24 23 20 16 18 27 25 31 27 27 25 21 31 27 20 23 24 32 17 21 34 27 17 19 19 25 30 27 21 24 28 30 19 26 21 14 16 21 23 27 8 17 21 17 11 23 15 22 15 18 10 17 20 23 18 18 17 19 22 15 22 21 19 23 18 18 26 17 18 26 18 24 15 22 23 23 19 23 25 23 24 26 10 21 16 32 23 18 19 24 21 28 26 22 19 19 14 30 21 24 23 22 21 13 27 20 27 24 15 20 22 22 13 25 14 19 32 21 18 18 23 22 22 14 18 20 24 14 19 20 18 17 24 29 27 20 12 18 17 11 9 2 3 2 1 0 0.192000 4.400 4.400 10.40 3593938 3 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 2 3 4 7 8 1 5 6 8 3 7 5 4 9 8 8 7 7 9 7 9 9 15 5 7 8 15 14 9 9 13 8 8 15 10 7 10 9 10 14 7 8 18 16 17 11 14 15 13 8 15 8 15 18 16 16 22 12 8 16 13 10 13 13 10 21 11 10 16 16 13 13 17 16 20 23 13 22 16 14 15 22 19 22 15 22 24 16 16 16 19 12 15 16 17 20 18 19 26 17 23 18 32 20 28 36 22 25 30 29 31 36 24 24 21 29 24 32 29 30 23 34 19 33 34 25 20 31 27 24 16 14 21 20 13 24 17 28 13 24 16 26 15 26 21 11 15 20 13 20 18 25 23 18 24 26 22 16 22 14 13 16 20 24 25 19 29 20 15 20 16 25 26 21 22 17 24 22 21 17 23 23 15 19 30 23 17 21 19 18 21 26 14 29 24 20 33 19 15 20 23 28 19 23 25 15 19 17 31 23 18 29 26 25 14 24 25 18 19 19 24 35 31 23 23 14 15 19 11 20 19 24 17 16 9 10 12 3 2 2 0 1 0.194000 4.450 4.450 10.50 3712573 7 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 5 3 5 4 3 11 3 10 4 6 7 8 5 5 5 8 9 12 7 7 11 8 6 7 9 10 13 10 6 13 9 9 9 11 14 14 12 13 10 6 13 13 15 12 13 19 8 14 13 16 11 13 14 15 9 15 16 13 16 17 17 17 23 18 16 19 10 13 18 16 10 9 21 11 22 14 20 14 18 13 15 12 13 14 16 14 15 20 29 17 14 18 8 15 21 15 19 15 22 20 17 15 23 26 16 26 24 23 23 23 23 30 24 29 28 26 35 33 31 22 23 22 20 37 22 27 33 26 27 26 17 16 18 27 22 21 24 18 18 18 17 15 18 14 19 24 22 15 20 21 15 19 25 15 16 26 19 22 29 20 16 13 15 16 32 24 23 13 33 17 22 18 18 23 24 22 21 20 26 21 16 22 18 18 16 15 26 26 17 22 21 13 25 24 13 23 18 18 25 32 20 24 21 17 19 24 24 23 33 19 19 21 32 18 22 23 19 23 32 18 31 22 25 23 23 31 29 21 16 20 20 15 22 14 12 5 10 9 2 1 0 1 0.196000 4.500 4.500 10.60 3829518 3 0 0 0 0 0 0 0 0 0 0 1 2 2 1 6 2 6 5 9 3 5 6 8 6 3 8 10 7 11 9 4 8 9 5 11 10 13 9 16 13 10 9 5 12 9 15 10 13 9 12 18 14 19 9 13 14 12 13 21 17 17 18 16 13 12 16 14 18 10 15 15 16 11 15 22 17 19 17 11 12 26 12 17 19 18 21 20 27 17 18 19 21 14 19 16 12 16 21 20 18 8 17 17 13 13 18 15 19 15 19 20 28 21 29 27 27 34 24 26 31 25 24 16 17 23 23 30 28 18 28 32 28 37 18 26 18 16 33 21 31 21 20 22 19 20 25 18 18 20 11 17 20 22 23 14 14 17 18 20 25 20 19 20 22 19 16 33 25 21 21 24 18 16 22 29 22 16 27 26 28 21 20 22 17 25 23 20 23 18 16 19 26 22 21 22 23 15 20 19 17 23 19 20 15 22 18 22 26 23 23 31 17 29 18 13 15 19 18 24 22 28 22 17 23 24 26 21 23 25 24 29 26 18 41 24 29 22 27 23 28 16 30 24 18 23 19 17 18 21 17 14 8 2 5 2 0 0 0.198000 4.550 4.550 10.70 3950740 3 0 0 0 0 0 0 0 0 0 1 1 1 2 1 3 7 5 6 7 7 7 4 5 6 4 1 8 9 10 9 8 10 8 12 6 10 8 10 8 11 9 10 15 7 11 8 13 11 13 15 15 17 12 10 8 17 12 9 14 12 14 11 14 21 14 15 20 18 16 8 15 22 24 14 10 18 14 15 16 12 10 16 21 16 25 17 20 17 17 20 15 24 15 17 22 25 17 13 22 18 20 19 11 21 22 21 16 21 24 16 22 17 21 17 24 22 24 35 27 24 28 24 32 37 34 25 24 29 37 37 25 28 21 23 24 22 21 20 25 22 32 19 21 22 24 20 21 20 22 18 27 17 14 20 22 22 22 14 19 20 20 21 23 22 14 20 21 23 20 18 23 20 25 31 24 18 22 14 23 22 21 23 27 27 20 21 18 22 23 24 23 21 18 22 17 22 21 35 15 24 24 12 27 30 27 28 22 31 24 24 19 27 24 28 23 25 26 35 27 22 29 21 24 18 19 26 33 29 31 23 25 19 24 26 21 10 23 24 26 28 20 27 26 17 29 22 18 14 22 8 10 11 4 4 1 2 0 0.200000 4.600 4.600 10.80 4068161 5 0 0 0 0 0 0 0 0 0 0 1 1 0 1 5 5 2 9 3 11 6 9 8 7 7 8 3 3 13 10 8 7 5 8 13 8 7 14 12 10 7 15 13 13 11 12 12 14 12 13 12 10 15 11 14 7 16 15 8 15 13 15 13 18 13 17 21 15 12 13 13 17 18 18 18 16 19 20 17 14 17 24 13 12 18 19 19 13 21 18 26 21 23 16 14 18 19 13 33 13 19 20 14 20 23 14 26 19 22 21 21 16 27 30 25 28 22 32 21 30 27 31 21 30 22 27 27 31 27 21 17 38 41 17 21 20 19 30 24 27 20 20 21 30 20 19 19 31 25 24 13 21 23 19 24 33 24 17 20 17 12 25 23 18 24 11 24 25 22 33 20 11 22 31 21 20 26 27 21 26 24 14 23 23 20 20 26 28 10 20 27 24 22 17 27 28 20 23 23 33 20 24 26 32 33 29 21 25 24 17 18 19 27 26 20 24 26 24 24 26 21 19 24 21 36 32 18 33 33 20 23 25 33 19 27 25 27 24 27 21 21 23 28 18 27 25 19 24 15 17 12 15 7 2 1 0 0 ", "%f ", Inf); %! assert (rows (x) == n); +## Test input validation +%!error sscanf () +%!error sscanf (1, "2") +%!error