changeset 27261:dccdc3b001a2

eliminate static functions from octave_link class * octave-link.h, octave-link. (class octave_link): Convert all static data and functions to normal data members and member functions. Change all uses. * interpreter-private.h, interpreter-private.cc (__get_octave_link__): New function. * interpreter.h, interpreter.cc (interpreter::m_octave_link): New data member. (interpreter::get_octave_link): New function.
author John W. Eaton <jwe@octave.org>
date Wed, 17 Jul 2019 14:09:20 -0400
parents 5ac60319575b
children d67f369b3074
files libgui/graphics/Canvas.cc libgui/graphics/GLCanvas.cc libgui/src/interpreter-qobject.cc libgui/src/m-editor/file-editor-tab.cc libgui/src/main-window.cc libgui/src/octave-qobject.cc libgui/src/octave-qt-link.cc libgui/src/variable-editor-model.cc libinterp/corefcn/dirfns.cc libinterp/corefcn/input.cc libinterp/corefcn/interpreter-private.cc libinterp/corefcn/interpreter-private.h libinterp/corefcn/interpreter.cc libinterp/corefcn/interpreter.h libinterp/corefcn/oct-hist.cc libinterp/corefcn/octave-link.cc libinterp/corefcn/octave-link.h libinterp/corefcn/syscalls.cc libinterp/corefcn/variables.cc libinterp/octave-value/ov-usr-fcn.cc libinterp/parse-tree/bp-table.cc libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-stmt.cc libinterp/parse-tree/pt-stmt.h
diffstat 24 files changed, 457 insertions(+), 276 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/graphics/Canvas.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/graphics/Canvas.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -875,7 +875,10 @@
                     props = anno_dlg.get_properties ();
                     props.prepend (figObj.get_handle ().as_octave_value ());
 
-                    octave_link::post_event
+                    octave_link& olnk
+                      = octave::__get_octave_link__ ("Canvas::canvasMouseReleaseEvent");
+
+                    olnk.post_event
                       ([this, props] (void)
                        {
                          octave::interpreter& interp
--- a/libgui/graphics/GLCanvas.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/graphics/GLCanvas.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -27,6 +27,7 @@
 #include "gl-render.h"
 #include "gl2ps-print.h"
 #include "graphics.h"
+#include "interpreter-private.h"
 #include "octave-link.h"
 
 #include "GLCanvas.h"
@@ -173,7 +174,10 @@
           }
         catch (octave::execution_exception& e)
           {
-            octave_link::post_exception (std::current_exception ());
+            octave_link& olnk
+              = octave::__get_octave_link__ ("GLCanvas::do_print");
+
+            olnk.post_exception (std::current_exception ());
           }
 
         end_rendering ();
--- a/libgui/src/interpreter-qobject.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/interpreter-qobject.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -38,8 +38,19 @@
   interpreter_qobject::interpreter_qobject (base_qobject *oct_qobj)
     : QObject (), m_octave_qobject (oct_qobj),
       m_qt_link (new octave_qt_link_events ())
+  { }
+
+  void interpreter_qobject::execute (void)
   {
-    octave_link::connect_link (m_qt_link);
+    // The Octave application context owns the interpreter.
+
+    qt_application& app_context = m_octave_qobject->app_context ();
+
+    interpreter& interp = app_context.create_interpreter ();
+
+    octave_link& olnk = interp.get_octave_link ();
+
+    olnk.connect_link (m_qt_link);
 
     connect (m_qt_link, SIGNAL (confirm_shutdown_signal (void)),
              m_octave_qobject, SLOT (confirm_shutdown_octave (void)));
@@ -48,15 +59,6 @@
              SIGNAL (copy_image_to_clipboard_signal (const QString&, bool)),
              m_octave_qobject,
              SLOT (copy_image_to_clipboard (const QString&, bool)));
-  }
-
-  void interpreter_qobject::execute (void)
-  {
-    // The Octave application context owns the interpreter.
-
-    qt_application& app_context = m_octave_qobject->app_context ();
-
-    interpreter& interp = app_context.create_interpreter ();
 
     int exit_status = 0;
 
--- a/libgui/src/m-editor/file-editor-tab.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/m-editor/file-editor-tab.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -382,6 +382,9 @@
           cond = '(' + cond + ") || (" + _edit_area->selectedText () + ')';
       }
 
+    interpreter& interp
+      = __get_interpreter__ ("handle_context_menu_break_condition");
+
     bool valid = false;
     std::string prompt = "dbstop if";
     bool ok;
@@ -393,9 +396,6 @@
                                    &ok);
         if (ok)     // If cancel, don't change breakpoint condition.
           {
-            interpreter& interp
-              = __get_interpreter__ ("handle_context_menu_break_condition");
-
             error_system& es = interp.get_error_system ();
 
             try
@@ -1107,7 +1107,10 @@
   {
     bp_info info (_file_name, line);
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("file_editor_tab::handle_request_remove_breakpoint");
+
+    olnk.post_event
       ([info] (void)
        {
          bp_table::intmap line_info;
@@ -1190,7 +1193,10 @@
 
     bp_info info (_file_name);
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("file_editor_tab::remove_all_breakpoints");
+
+    olnk.post_event
       ([info] (void)
        {
          if (octave_qt_link_events::file_in_path (info.file, info.dir))
@@ -1319,7 +1325,10 @@
 
   void file_editor_tab::add_breakpoint_event (const bp_info& info)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("file_editor_tab::add_breakpoint_event");
+
+    olnk.post_event
       ([this, info] (void)
        {
          bp_table::intmap line_info;
@@ -2046,7 +2055,10 @@
 
     // Create and queue the command object.
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("file_editor_tab::update_breakpoints");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER THREAD
--- a/libgui/src/main-window.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/main-window.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -336,7 +336,10 @@
 
     if (! file.isEmpty ())
       {
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::handle_save_workspace_request");
+
+        olnk.post_event
           ([file] (void)
            {
              // INTERPRETER THREAD
@@ -365,7 +368,10 @@
 
     if (! file.isEmpty ())
       {
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::handle_load_workspace_request");
+
+        olnk.post_event
           ([file] (void)
            {
              // INTERPRETER THREAD
@@ -377,7 +383,9 @@
 
              tree_evaluator& tw = interp.get_evaluator ();
 
-             octave_link::set_workspace (true, tw.get_symbol_info ());
+             octave_link& xolnk = interp.get_octave_link ();
+
+             xolnk.set_workspace (true, tw.get_symbol_info ());
            });
       }
   }
@@ -388,26 +396,36 @@
       {
         std::string file = file_arg.toStdString ();
 
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::handle_open_any_request");
+
+        olnk.post_event
           ([file] (void)
            {
              // INTERPRETER THREAD
 
+             interpreter& interp
+               = __get_interpreter__ ("main_window::handle_open_any_request");
+
              feval ("open", ovl (file));
 
              // Update the workspace since open.m may have loaded new
              // variables.
-             tree_evaluator& tw
-               = __get_evaluator__ ("main_window::handle_open_any_request");
-
-             octave_link::set_workspace (true, tw.get_symbol_info ());
+             tree_evaluator& tw = interp.get_evaluator ();
+
+             octave_link& xolnk = interp.get_octave_link ();
+
+             xolnk.set_workspace (true, tw.get_symbol_info ());
            });
       }
   }
 
   void main_window::handle_clear_workspace_request (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_clear_workspace_request");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
@@ -421,7 +439,10 @@
 
   void main_window::handle_clear_command_window_request (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_clear_command_window_request");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
@@ -433,7 +454,10 @@
 
   void main_window::handle_clear_history_request (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_clear_history_request");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
@@ -449,7 +473,10 @@
   {
     if (command_window_has_focus ())
       {
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::handle_undo_request");
+
+        olnk.post_event
           ([] (void)
            {
              // INTERPRETER THREAD
@@ -469,22 +496,28 @@
     std::string old_name = old_name_arg.toStdString ();
     std::string new_name = new_name_arg.toStdString ();
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_rename_variable_request");
+
+    olnk.post_event
       ([old_name, new_name] (void)
        {
          // INTERPRETER THREAD
 
-         symbol_scope scope
-           = __get_current_scope__ ("main_window::rename_variable_request");
+         interpreter& interp
+           = __get_interpreter__ ("main_window::rename_variable_request");
+
+         symbol_scope scope = interp.get_current_scope ();
 
          if (scope)
            {
              scope.rename (old_name, new_name);
 
-             tree_evaluator& tw
-               = __get_evaluator__ ("main_window::rename_variable_request");
-
-             octave_link::set_workspace (true, tw.get_symbol_info ());
+             tree_evaluator& tw = interp.get_evaluator ();
+
+             octave_link& xolnk = interp.get_octave_link ();
+
+             xolnk.set_workspace (true, tw.get_symbol_info ());
            }
 
          // FIXME: if this action fails, do we need a way to display that info
@@ -853,7 +886,10 @@
       {
         m_default_encoding = new_default_encoding;
 
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::notice_settings");
+
+        olnk.post_event
           ([this] (void)
            {
              // INTERPRETER THREAD
@@ -974,7 +1010,10 @@
 
     if (fileInfo.exists () && fileInfo.isDir ())
       {
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::set_current_working_directory");
+
+        olnk.post_event
           ([xdir] (void)
            {
              // INTERPRETER THREAD
@@ -1009,7 +1048,10 @@
 
   void main_window::execute_command_in_terminal (const QString& command)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::execute_command_in_terminal");
+
+    olnk.post_event
       ([command] (void)
        {
          // INTERPRETER THREAD
@@ -1028,7 +1070,10 @@
 
   void main_window::run_file_in_terminal (const QFileInfo& info)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::run_file_in_terminal");
+
+    olnk.post_event
       ([info] (void)
        {
          // INTERPRETER THREAD
@@ -1074,7 +1119,10 @@
 
   void main_window::handle_new_figure_request (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_new_figure_request");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
@@ -1119,7 +1167,10 @@
 
   void main_window::debug_continue (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::debug_continue");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER THREAD
@@ -1136,7 +1187,10 @@
 
   void main_window::debug_step_into (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::debug_step_into");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER THREAD
@@ -1157,7 +1211,10 @@
       {
         // We are in debug mode, just call dbstep.
 
-        octave_link::post_event
+        octave_link& olnk
+          = __get_octave_link__ ("main_window::debug_step_over");
+
+        olnk.post_event
           ([this] (void)
            {
              // INTERPRETER THREAD
@@ -1180,7 +1237,9 @@
 
   void main_window::debug_step_out (void)
   {
-    octave_link::post_event
+    octave_link& olnk = __get_octave_link__ ("main_window::debug_step_out");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER THREAD
@@ -1197,7 +1256,9 @@
 
   void main_window::debug_quit (void)
   {
-    octave_link::post_event
+    octave_link& olnk = __get_octave_link__ ("main_window::debug_quit");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER THREAD
@@ -1744,7 +1805,9 @@
 
   void main_window::set_screen_size (int ht, int wd)
   {
-    octave_link::post_event
+    octave_link& olnk = __get_octave_link__ ("main_window::set_screen_size");
+
+    olnk.post_event
       ([ht, wd] (void)
        {
          // INTERPRETER THREAD
@@ -1830,15 +1893,22 @@
     // interpreter.  That will eventually cause the workspace view in the
     // GUI to be updated.
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("main_window::handle_variable_editor_update");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
 
-         tree_evaluator& tw
-           = __get_evaluator__ ("main_window::handle_variable_editor_update");
-
-         octave_link::set_workspace (true, tw.get_symbol_info (), false);
+         interpreter& interp
+           = __get_interpreter__ ("main_window::handle_variable_editor_update");
+
+         tree_evaluator& tw = interp.get_evaluator ();
+
+         octave_link& xolnk = interp.get_octave_link ();
+
+         xolnk.set_workspace (true, tw.get_symbol_info (), false);
        });
   }
 
@@ -1846,12 +1916,16 @@
   {
     e->ignore ();
 
-    octave_link::post_event
+    octave_link& olnk = __get_octave_link__ ("main_window::closeEvent");
+
+    olnk.post_event
       ([] (void)
        {
          // INTERPRETER THREAD
 
-         Fquit ();
+         interpreter& interp = __get_interpreter__ ("main_window::closeEvent");
+
+         Fquit (interp);
        });
   }
 
@@ -2054,14 +2128,6 @@
              SIGNAL (file_remove_signal (const QString&, const QString&)),
              this, SLOT (file_remove_proxy (const QString&, const QString&)));
 
-    octave_link::post_event
-      ([] (void)
-       {
-         // INTERPRETER THREAD
-
-         command_editor::resize_terminal ();
-       });
-
     configure_shortcuts ();
   }
 
--- a/libgui/src/octave-qobject.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/octave-qobject.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -42,6 +42,7 @@
 #include "qt-application.h"
 #include "resource-manager.h"
 
+#include "interpreter-private.h"
 #include "ovl.h"
 #include "oct-env.h"
 #include "version.h"
@@ -69,7 +70,9 @@
       }
     catch (execution_exception&)
       {
-        octave_link::post_exception (std::current_exception ());
+        octave_link& olnk = __get_octave_link__ ("octave_qapplication::notify");
+
+        olnk.post_exception (std::current_exception ());
       }
 
    return false;
--- a/libgui/src/octave-qt-link.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/octave-qt-link.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -608,7 +608,11 @@
 
     if (! ok)
       {
-        int action = octave_link::debug_cd_or_addpath_error (file, dir, addpath_option);
+        octave_link& olnk
+          = __get_octave_link__ ("octave_qt_link_events::file_in_path");
+
+        int action = olnk.debug_cd_or_addpath_error (file, dir, addpath_option);
+
         switch (action)
           {
           case 1:
--- a/libgui/src/variable-editor-model.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libgui/src/variable-editor-model.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -1012,7 +1012,9 @@
 
     std::string expr = os.str ();
 
-    octave_link::post_event
+    octave_link& olnk = __get_octave_link__ ("variable_editor_model::setData");
+
+    olnk.post_event
       ([this, nm, expr, idx] (void)
        {
          // INTERPRETER THREAD
@@ -1164,7 +1166,10 @@
   {
     std::string expr = expr_arg.toStdString ();
 
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("variable_editor_model::eval_expr_event");
+
+    olnk.post_event
       ([this, expr] (void)
        {
          // INTERPRETER THREAD
@@ -1235,7 +1240,10 @@
   void
   variable_editor_model::update_data_cache (void)
   {
-    octave_link::post_event
+    octave_link& olnk
+      = __get_octave_link__ ("variable_editor_model::update_data_cache");
+
+    olnk.post_event
       ([this] (void)
        {
          // INTERPRETER_THREAD
--- a/libinterp/corefcn/dirfns.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/dirfns.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -83,12 +83,16 @@
   // FIXME: should these actions be handled as a list of functions
   // to call so users can add their own chdir handlers?
 
-  octave::load_path& lp =
-    octave::__get_load_path__ ("octave_change_to_directory");
+  octave::interpreter& interp
+    = octave::__get_interpreter__ ("octave_change_to_directory");
+
+  octave::load_path& lp = interp.get_load_path ();
 
   lp.update ();
 
-  octave_link::change_directory (octave::sys::env::get_current_directory ());
+  octave_link& olnk = interp.get_octave_link ();
+
+  olnk.change_directory (octave::sys::env::get_current_directory ());
 
   return cd_ok;
 }
@@ -280,6 +284,8 @@
   int status = -1;
   std::string msg;
 
+  octave_link& olnk = interp.get_octave_link ();
+
   if (nargin == 2)
     {
       if (args(1).string_value () != "s")
@@ -300,17 +306,17 @@
 
       if (doit)
         {
-          octave_link::file_remove (fulldir, "");
+          olnk.file_remove (fulldir, "");
           status = octave::sys::recursive_rmdir (fulldir, msg);
         }
     }
   else
     {
-      octave_link::file_remove (fulldir, "");
+      olnk.file_remove (fulldir, "");
       status = octave::sys::rmdir (fulldir, msg);
     }
 
-  octave_link::file_renamed (status >= 0);
+  olnk.file_renamed (status >= 0);
 
   if (status < 0)
     return ovl (false, msg, "rmdir");
@@ -410,8 +416,8 @@
     return ovl (result, status, "");
 }
 
-DEFUNX ("rename", Frename, args, ,
-        doc: /* -*- texinfo -*-
+DEFMETHODX ("rename", Frename, interp, args, ,
+            doc: /* -*- texinfo -*-
 @deftypefn  {} {} rename @var{old} @var{new}
 @deftypefnx {} {[@var{err}, @var{msg}] =} rename (@var{old}, @var{new})
 Change the name of file @var{old} to @var{new}.
@@ -433,18 +439,20 @@
 
   std::string msg;
 
-  octave_link::file_remove (from, to);
+  octave_link& olnk = interp.get_octave_link ();
+
+  olnk.file_remove (from, to);
 
   int status = octave::sys::rename (from, to, msg);
 
   if (status < 0)
     {
-      octave_link::file_renamed (false);
+      olnk.file_renamed (false);
       return ovl (-1.0, msg);
     }
   else
     {
-      octave_link::file_renamed (true);
+      olnk.file_renamed (true);
       return ovl (status, "");
     }
 }
--- a/libinterp/corefcn/input.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/input.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -706,14 +706,16 @@
 
     tree_evaluator& tw = interp.get_evaluator ();
 
+    octave_link& olnk = interp.get_octave_link ();
+
     if (application::interactive ())
       {
         if (! tw.in_debug_repl ())
-          octave_link::exit_debugger_event ();
+          olnk.exit_debugger_event ();
 
-        octave_link::pre_input_event ();
+        olnk.pre_input_event ();
 
-        octave_link::set_workspace ();
+        olnk.set_workspace ();
       }
 
     bool history_skip_auto_repeated_debugging_command = false;
@@ -759,7 +761,7 @@
         if (! history_skip_auto_repeated_debugging_command)
           {
             if (command_history::add (retval))
-              octave_link::append_history (retval);
+              olnk.append_history (retval);
           }
 
         octave_diary << retval;
@@ -774,7 +776,7 @@
     // list has been updated.
 
     if (application::interactive ())
-      octave_link::post_input_event ();
+      olnk.post_input_event ();
 
     return retval;
   }
--- a/libinterp/corefcn/interpreter-private.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/interpreter-private.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -39,6 +39,7 @@
 #include "load-path.h"
 #include "load-save.h"
 #include "oct-hist.h"
+#include "octave-link.h"
 #include "ov.h"
 #include "ov-fcn-inline.h"
 #include "pager.h"
@@ -115,6 +116,13 @@
     return interp.get_load_save_system ();
   }
 
+  octave_link& __get_octave_link__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_octave_link ();
+  }
+
   type_info& __get_type_info__ (const std::string& who)
   {
     interpreter& interp = __get_interpreter__ (who);
--- a/libinterp/corefcn/interpreter-private.h	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/interpreter-private.h	Wed Jul 17 14:09:20 2019 -0400
@@ -30,6 +30,8 @@
 
 #include "symtab.h"
 
+class octave_link;
+
 namespace octave
 {
   class bp_table;
@@ -64,6 +66,8 @@
 
   extern load_save_system& __get_load_save_system__ (const std::string& who);
 
+  extern octave_link& __get_octave_link__ (const std::string& who);
+
   extern output_system& __get_output_system__ (const std::string& who);
 
   extern type_info& __get_type_info__ (const std::string& who);
--- a/libinterp/corefcn/interpreter.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/interpreter.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -129,8 +129,8 @@
   return retval;
 }
 
-DEFUN (quit, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (quit, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} exit
 @deftypefnx {} {} exit (@var{status})
 @deftypefnx {} {} quit
@@ -150,7 +150,10 @@
   // Confirm OK to shutdown.  Note: A dynamic function installation similar
   // to overriding polymorphism for which the GUI can install its own "quit"
   // yet call this base "quit" could be nice.  No link would be needed here.
-  if (! octave_link::confirm_shutdown ())
+
+  octave_link& olnk = interp.get_octave_link ();
+
+  if (! olnk.confirm_shutdown ())
     return ovl ();
 
   if (! quit_allowed)
@@ -377,6 +380,7 @@
       m_url_handle_manager (),
       m_cdef_manager (*this),
       m_gtk_manager (),
+      m_octave_link (),
       m_interactive (false),
       m_read_site_files (true),
       m_read_init_files (m_app_context != nullptr),
@@ -1017,8 +1021,8 @@
     // If we are attached to a GUI, process pending events and
     // disconnect the link.
 
-    octave_link::process_events (true);
-    octave_link::disconnect_link ();
+    m_octave_link.process_events (true);
+    m_octave_link.disconnect_link ();
 
     OCTAVE_SAFE_CALL (m_input_system.clear_input_event_hooks, ());
 
--- a/libinterp/corefcn/interpreter.h	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/interpreter.h	Wed Jul 17 14:09:20 2019 -0400
@@ -43,6 +43,7 @@
 #include "load-save.h"
 #include "oct-hist.h"
 #include "oct-stream.h"
+#include "octave-link.h"
 #include "ov-typeinfo.h"
 #include "pager.h"
 #include "pt-eval.h"
@@ -237,6 +238,11 @@
       return m_gtk_manager;
     }
 
+    octave_link& get_octave_link (void)
+    {
+      return m_octave_link;
+    }
+
     void mlock (void);
 
     void munlock (const std::string& nm);
@@ -449,6 +455,8 @@
 
     gtk_manager m_gtk_manager;
 
+    octave_link m_octave_link;
+
     // TRUE means this is an interactive interpreter (forced or not).
     bool m_interactive;
 
--- a/libinterp/corefcn/oct-hist.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/oct-hist.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -61,6 +61,7 @@
 #include "sighandlers.h"
 #include "sysdep.h"
 #include "interpreter.h"
+#include "interpreter-private.h"
 #include "unwind-prot.h"
 #include "utils.h"
 #include "variables.h"
@@ -134,8 +135,15 @@
           tmp.resize (len - 1);
 
         if (! tmp.empty ())
-          if (command_history::add (tmp))
-            octave_link::append_history (tmp);
+          {
+            if (command_history::add (tmp))
+              {
+                octave_link& olnk
+                  = __get_octave_link__ ("edit_history_add_hist");
+
+                olnk.append_history (tmp);
+              }
+          }
       }
   }
 
@@ -266,7 +274,9 @@
                                  default_size (),
                                  sys::env::getenv ("OCTAVE_HISTCONTROL"));
 
-    octave_link::set_history (command_history::list ());
+    octave_link& olnk = m_interpreter.get_octave_link ();
+
+    olnk.set_history (command_history::list ());
   }
 
   void history_system::write_timestamp (void)
@@ -276,8 +286,14 @@
     std::string timestamp = now.strftime (m_timestamp_format_string);
 
     if (! timestamp.empty ())
-      if (command_history::add (timestamp))
-        octave_link::append_history (timestamp);
+      {
+        if (command_history::add (timestamp))
+          {
+            octave_link& olnk = m_interpreter.get_octave_link ();
+
+            olnk.append_history (timestamp);
+          }
+      }
   }
 
   octave_value
@@ -336,6 +352,8 @@
         else
           err_wrong_type_arg ("history", arg);
 
+        octave_link& olnk = m_interpreter.get_octave_link ();
+
         if (option == "-r" || option == "-w" || option == "-a"
             || option == "-n")
           {
@@ -362,14 +380,14 @@
               {
                 // Read entire file.
                 command_history::read ();
-                octave_link::set_history (command_history::list ());
+                olnk.set_history (command_history::list ());
               }
 
             else if (option == "-n")
               {
                 // Read 'new' history from file.
                 command_history::read_range ();
-                octave_link::set_history (command_history::list ());
+                olnk.set_history (command_history::list ());
               }
 
             else
@@ -380,7 +398,7 @@
         else if (option == "-c")
           {
             command_history::clear ();
-            octave_link::clear_history ();
+            olnk.clear_history ();
           }
         else if (option == "-q")
           numbered_output = false;
--- a/libinterp/corefcn/octave-link.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/octave-link.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -41,23 +41,19 @@
 static int
 octave_readline_hook (void)
 {
-  octave_link::process_events ();
+  octave_link& olnk = octave::__get_octave_link__ ("octave_readline_hook");
+
+  olnk.process_events ();
 
   return 0;
 }
 
-octave_link_events *octave_link::instance = nullptr;
-
-octave::mutex *octave_link::event_queue_mutex = new octave::mutex ();
-
-octave::event_queue octave_link::gui_event_queue;
-
-bool octave_link::debugging = false;
-
-bool octave_link::link_enabled = true;
-
 octave_link::octave_link (void)
-{ }
+  : instance (nullptr), event_queue_mutex (new octave::mutex ()),
+    gui_event_queue (), debugging (false), link_enabled (true)
+{
+  octave::command_editor::add_event_hook (octave_readline_hook);
+}
 
 octave_link::~octave_link (void)
 {
@@ -75,8 +71,6 @@
     error ("octave_link is already linked!");
 
   instance = obj;
-
-  octave::command_editor::add_event_hook (octave_readline_hook);
 }
 
 octave_link_events *
@@ -138,30 +132,34 @@
     }
 }
 
-DEFUN (__octave_link_enabled__, , ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_enabled__, interp, , ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_enabled__ ()
 Undocumented internal function.
 @end deftypefn */)
 {
-  return ovl (octave_link::enabled ());
+  octave_link& olnk = interp.get_octave_link ();
+
+  return ovl (olnk.enabled ());
 }
 
-DEFUN (__octave_link_edit_file__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_edit_file__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_edit_file__ (@var{file})
 Undocumented internal function.
 @end deftypefn */)
 {
   octave_value retval;
 
+  octave_link& olnk = interp.get_octave_link ();
+
   if (args.length () == 1)
     {
       std::string file = args(0).xstring_value ("first argument must be filename");
 
       octave::flush_stdout ();
 
-      retval = octave_link::edit_file (file);
+      retval = olnk.edit_file (file);
     }
   else if (args.length () == 2)
     {
@@ -169,14 +167,14 @@
 
       octave::flush_stdout ();
 
-      retval = octave_link::prompt_new_edit_file (file);
+      retval = olnk.prompt_new_edit_file (file);
     }
 
   return retval;
 }
 
-DEFUN (__octave_link_question_dialog__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_question_dialog__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_question_dialog__ (@var{msg}, @var{title}, @var{btn1}, @var{btn2}, @var{btn3}, @var{default})
 Undocumented internal function.
 @end deftypefn */)
@@ -194,15 +192,16 @@
 
       octave::flush_stdout ();
 
-      retval = octave_link::question_dialog (msg, title, btn1, btn2, btn3,
-                                             btndef);
+      octave_link& olnk = interp.get_octave_link ();
+
+      retval = olnk.question_dialog (msg, title, btn1, btn2, btn3, btndef);
     }
 
   return retval;
 }
 
-DEFUN (__octave_link_file_dialog__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_file_dialog__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_file_dialog__ (@var{filterlist}, @var{title}, @var{filename}, @var{size} @var{multiselect}, @var{pathname})
 Undocumented internal function.
 @end deftypefn */)
@@ -220,6 +219,7 @@
   std::string pathname = args(5).string_value ();
 
   octave_idx_type nel;
+
   octave_link::filter_list filter_lst;
 
   for (octave_idx_type i = 0; i < flist.rows (); i++)
@@ -229,9 +229,10 @@
 
   octave::flush_stdout ();
 
+  octave_link& olnk = interp.get_octave_link ();
+
   std::list<std::string> items_lst
-    = octave_link::file_dialog (filter_lst, title, filename, pathname,
-                                multi_on);
+    = olnk.file_dialog (filter_lst, title, filename, pathname, multi_on);
 
   nel = items_lst.size ();
 
@@ -269,8 +270,8 @@
   return retval;
 }
 
-DEFUN (__octave_link_list_dialog__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_list_dialog__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{initial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})
 Undocumented internal function.
 @end deftypefn */)
@@ -309,10 +310,11 @@
 
   octave::flush_stdout ();
 
+  octave_link& olnk = interp.get_octave_link ();
+
   std::pair<std::list<int>, int> result
-    = octave_link::list_dialog (list_lst, mode, width, height,
-                                initial_lst, name, prompt_lst,
-                                ok_string, cancel_string);
+    = olnk.list_dialog (list_lst, mode, width, height, initial_lst,
+                        name, prompt_lst, ok_string, cancel_string);
 
   std::list<int> items_lst = result.first;
   nel = items_lst.size ();
@@ -324,8 +326,8 @@
   return ovl (items, result.second);
 }
 
-DEFUN (__octave_link_input_dialog__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_input_dialog__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_input_dialog__ (@var{prompt}, @var{title}, @var{rowscols}, @var{defaults})
 Undocumented internal function.
 @end deftypefn */)
@@ -361,9 +363,10 @@
 
   octave::flush_stdout ();
 
+  octave_link& olnk = interp.get_octave_link ();
+
   std::list<std::string> items_lst
-    = octave_link::input_dialog (prompt_lst, title, nr, nc,
-                                 defaults_lst);
+    = olnk.input_dialog (prompt_lst, title, nr, nc, defaults_lst);
 
   nel = items_lst.size ();
   Cell items (dim_vector (nel, 1));
@@ -375,8 +378,8 @@
 }
 
 
-DEFUN (__octave_link_named_icon__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_named_icon__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_dialog_icons__ (@var{icon_name})
 Undocumented internal function.
 @end deftypefn */)
@@ -387,23 +390,27 @@
     {
       std::string icon_name = args(0).xstring_value ("invalid arguments");
 
-      retval = octave_link::get_named_icon (icon_name);
+      octave_link& olnk = interp.get_octave_link ();
+
+      retval = olnk.get_named_icon (icon_name);
     }
 
   return ovl (retval);
 }
 
-DEFUN (__octave_link_show_preferences__, , ,
+DEFMETHOD (__octave_link_show_preferences__, interp, , ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_show_preferences__ ()
 Undocumented internal function.
 @end deftypefn */)
 {
-  return ovl (octave_link::show_preferences ());
+  octave_link& olnk = interp.get_octave_link ();
+
+  return ovl (olnk.show_preferences ());
 }
 
-DEFUN (__octave_link_gui_preference__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_gui_preference__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_gui_preference__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -421,13 +428,17 @@
     value = args(1).string_value();
 
   if (octave::application::is_gui_running ())
-    return ovl (octave_link::gui_preference (key, value));
+    {
+      octave_link& olnk = interp.get_octave_link ();
+
+      return ovl (olnk.gui_preference (key, value));
+    }
   else
     return ovl (value);
 }
 
-DEFUN (__octave_link_file_remove__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_file_remove__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_file_remove__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -443,13 +454,15 @@
     error ("__octave_link_file_remove__: "
            "old and new name expected as arguments");
 
-  octave_link::file_remove (old_name, new_name);
+  octave_link& olnk = interp.get_octave_link ();
+
+  olnk.file_remove (old_name, new_name);
 
   return ovl ();
 }
 
-DEFUN (__octave_link_file_renamed__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_file_renamed__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_file_renamed__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -462,7 +475,9 @@
     error ("__octave_link_file_renamed__: "
            "first argument must be boolean for reload new named file");
 
-  octave_link::file_renamed (load_new);
+  octave_link& olnk = interp.get_octave_link ();
+
+  olnk.file_renamed (load_new);
 
   return ovl ();
 }
@@ -490,7 +505,9 @@
       if (val.is_undefined ())
         error ("openvar: '%s' is not a variable", name.c_str ());
 
-      octave_link::edit_variable (name, val);
+      octave_link& olnk = interp.get_octave_link ();
+
+      olnk.edit_variable (name, val);
     }
 
   return ovl ();
@@ -502,8 +519,8 @@
 %!error <NAME must be a string> openvar (1:10)
 */
 
-DEFUN (__octave_link_show_doc__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_show_doc__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_show_doc__ (@var{filename})
 Undocumented internal function.
 @end deftypefn */)
@@ -513,11 +530,13 @@
   if (args.length () >= 1)
     file = args(0).string_value();
 
-  return ovl (octave_link::show_doc (file));
+  octave_link& olnk = interp.get_octave_link ();
+
+  return ovl (olnk.show_doc (file));
 }
 
-DEFUN (__octave_link_register_doc__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_register_doc__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_register_doc__ (@var{filename})
 Undocumented internal function.
 @end deftypefn */)
@@ -527,11 +546,13 @@
   if (args.length () >= 1)
     file = args(0).string_value();
 
-  return ovl (octave_link::register_doc (file));
+  octave_link& olnk = interp.get_octave_link ();
+
+  return ovl (olnk.register_doc (file));
 }
 
-DEFUN (__octave_link_unregister_doc__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__octave_link_unregister_doc__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __octave_link_unregister_doc__ (@var{filename})
 Undocumented internal function.
 @end deftypefn */)
@@ -541,5 +562,7 @@
   if (args.length () >= 1)
     file = args(0).string_value();
 
-  return ovl (octave_link::unregister_doc (file));
+  octave_link& olnk = interp.get_octave_link ();
+
+  return ovl (olnk.unregister_doc (file));
 }
--- a/libinterp/corefcn/octave-link.h	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/octave-link.h	Wed Jul 17 14:09:20 2019 -0400
@@ -200,12 +200,10 @@
 OCTINTERP_API
 octave_link
 {
-protected:
+public:
 
   octave_link (void);
 
-public:
-
   // No copying!
 
   octave_link (const octave_link&) = delete;
@@ -214,25 +212,25 @@
 
   virtual ~octave_link (void);
 
-  static void connect_link (octave_link_events *obj);
+  void connect_link (octave_link_events *obj);
 
-  static octave_link_events * disconnect_link (bool delete_instance = true);
+  octave_link_events * disconnect_link (bool delete_instance = true);
 
-  static bool enable (void)
+  bool enable (void)
   {
     bool retval = link_enabled;
     link_enabled = true;
     return retval;
   }
 
-  static bool disable (void)
+  bool disable (void)
   {
     bool retval = link_enabled;
     link_enabled = false;
     return retval;
   }
 
-  static bool enabled (void)
+  bool enabled (void) const
   {
     return link_enabled;
   }
@@ -240,11 +238,11 @@
   // If disable is TRUE, then no additional events will be processed
   // other than exit.
 
-  static void process_events (bool disable_arg = false);
+  void process_events (bool disable = false);
 
-  static void discard_events (void);
+  void discard_events (void);
 
-  static bool confirm_shutdown (void)
+  bool confirm_shutdown (void)
   {
     bool retval = true;
 
@@ -255,47 +253,41 @@
   }
 
   template <typename F, typename... Args>
-  static void
-  post_event (F&& fcn, Args&&... args)
+  void post_event (F&& fcn, Args&&... args)
   {
     if (enabled ())
       gui_event_queue.add (fcn, std::forward<Args> (args)...);
   }
 
   template <typename T, typename... Params, typename... Args>
-  static void
-  post_event (T *obj, void (T::*method) (Params...), Args&&... args)
+  void post_event (T *obj, void (T::*method) (Params...), Args&&... args)
   {
     if (enabled ())
       gui_event_queue.add_method (obj, method, std::forward<Args> (args)...);
   }
 
-  static void
-  post_exception (const std::exception_ptr &p)
+  void post_exception (const std::exception_ptr& p)
   {
     if (enabled ())
-      post_event (&octave_link::rethrow_exception_callback, p);
+      post_event (this, &octave_link::rethrow_exception_callback, p);
   }
 
-  static bool
-  copy_image_to_clipboard (const std::string& file)
+  bool copy_image_to_clipboard (const std::string& file)
   {
     return enabled () ? instance->do_copy_image_to_clipboard (file) : false;
   }
 
-  static bool
-  edit_file (const std::string& file)
+  bool edit_file (const std::string& file)
   {
     return enabled () ? instance->do_edit_file (file) : false;
   }
 
-  static bool
-  prompt_new_edit_file (const std::string& file)
+  bool prompt_new_edit_file (const std::string& file)
   {
     return enabled () ? instance->do_prompt_new_edit_file (file) : false;
   }
 
-  static std::string
+  std::string
   question_dialog (const std::string& msg, const std::string& title,
                    const std::string& btn1, const std::string& btn2,
                    const std::string& btn3, const std::string& btndef)
@@ -304,7 +296,7 @@
                                                       btn2, btn3, btndef) : "";
   }
 
-  static std::pair<std::list<int>, int>
+  std::pair<std::list<int>, int>
   list_dialog (const std::list<std::string>& list,
                const std::string& mode,
                int width, int height,
@@ -314,129 +306,125 @@
                const std::string& ok_string,
                const std::string& cancel_string)
   {
-    return enabled ()
-           ? instance->do_list_dialog (list, mode, width, height,
-                                       initial_value, name, prompt,
-                                       ok_string, cancel_string)
-           : std::pair<std::list<int>, int> ();
+    return (enabled ()
+            ? instance->do_list_dialog (list, mode, width, height,
+                                        initial_value, name, prompt,
+                                        ok_string, cancel_string)
+            : std::pair<std::list<int>, int> ());
   }
 
-  static std::list<std::string>
+  std::list<std::string>
   input_dialog (const std::list<std::string>& prompt,
                 const std::string& title,
                 const std::list<float>& nr,
                 const std::list<float>& nc,
                 const std::list<std::string>& defaults)
   {
-    return enabled ()
-           ? instance->do_input_dialog (prompt, title, nr, nc, defaults)
-           : std::list<std::string> ();
+    return (enabled ()
+            ? instance->do_input_dialog (prompt, title, nr, nc, defaults)
+            : std::list<std::string> ());
   }
 
   typedef std::list<std::pair<std::string, std::string>> filter_list;
 
-  static std::list<std::string>
+  std::list<std::string>
   file_dialog (const filter_list& filter, const std::string& title,
                const std::string& filename, const std::string& dirname,
                const std::string& multimode)
   {
-    return enabled ()
-           ? instance->do_file_dialog (filter, title, filename, dirname,
-                                       multimode)
-           : std::list<std::string> ();
+    return (enabled ()
+            ? instance->do_file_dialog (filter, title, filename, dirname,
+                                        multimode)
+            : std::list<std::string> ());
   }
 
-  static int debug_cd_or_addpath_error (const std::string& file,
-                                        const std::string& dir,
-                                        bool addpath_option)
+  int debug_cd_or_addpath_error (const std::string& file,
+                                 const std::string& dir, bool addpath_option)
   {
-    return enabled ()
-           ? instance->do_debug_cd_or_addpath_error (file, dir, addpath_option)
-           : 0;
+    return (enabled ()
+            ? instance->do_debug_cd_or_addpath_error (file, dir, addpath_option)
+            : 0);
   }
 
-  static void change_directory (const std::string& dir)
+  void change_directory (const std::string& dir)
   {
     if (enabled ())
       instance->do_change_directory (dir);
   }
 
   // Methods for removing/renaming files which might be open in editor
-  static void file_remove (const std::string& old_name,
-                           const std::string& new_name)
+  void file_remove (const std::string& old_name, const std::string& new_name)
   {
     if (octave::application::is_gui_running () && enabled ())
       instance->do_file_remove (old_name, new_name);
   }
 
-  static void file_renamed (bool load_new)
+  void file_renamed (bool load_new)
   {
     if (octave::application::is_gui_running () && enabled ())
       instance->do_file_renamed (load_new);
   }
 
   // Preserves pending input.
-  static void execute_command_in_terminal (const std::string& command)
+  void execute_command_in_terminal (const std::string& command)
   {
     if (enabled ())
       instance->do_execute_command_in_terminal (command);
   }
 
-  static uint8NDArray
-  get_named_icon (const std::string& icon_name)
+  uint8NDArray get_named_icon (const std::string& icon_name)
   {
     return (enabled () ?
             instance->do_get_named_icon (icon_name) : uint8NDArray ());
   }
 
-  static void set_workspace (void);
+  void set_workspace (void);
 
-  static void set_workspace (bool top_level,
-                             const octave::symbol_info_list& syminfo,
-                             bool update_variable_editor = true)
+  void set_workspace (bool top_level, const octave::symbol_info_list& syminfo,
+                      bool update_variable_editor = true)
   {
     if (enabled ())
       instance->do_set_workspace (top_level, debugging, syminfo,
                                   update_variable_editor);
   }
 
-  static void clear_workspace (void)
+  void clear_workspace (void)
   {
     if (enabled ())
       instance->do_clear_workspace ();
   }
 
-  static void set_history (const string_vector& hist)
+  void set_history (const string_vector& hist)
   {
     if (enabled ())
       instance->do_set_history (hist);
   }
 
-  static void append_history (const std::string& hist_entry)
+  void append_history (const std::string& hist_entry)
   {
     if (enabled ())
       instance->do_append_history (hist_entry);
   }
 
-  static void clear_history (void)
+  void clear_history (void)
   {
     if (enabled ())
       instance->do_clear_history ();
   }
 
-  static void pre_input_event (void)
+  void pre_input_event (void)
   {
     if (enabled ())
       instance->do_pre_input_event ();
   }
 
-  static void post_input_event (void)
+  void post_input_event (void)
   {
     if (enabled ())
       instance->do_post_input_event ();
   }
 
-  static void enter_debugger_event (const std::string& file, int line)
+  void enter_debugger_event (const std::string& file, int line)
   {
     if (enabled ())
       {
@@ -446,13 +434,13 @@
       }
   }
 
-  static void execute_in_debugger_event (const std::string& file, int line)
+  void execute_in_debugger_event (const std::string& file, int line)
   {
     if (enabled ())
       instance->do_execute_in_debugger_event (file, line);
   }
 
-  static void exit_debugger_event (void)
+  void exit_debugger_event (void)
   {
     if (enabled () && debugging)
       {
@@ -462,16 +450,14 @@
       }
   }
 
-  static void
-  update_breakpoint (bool insert, const std::string& file, int line,
-                     const std::string& cond = "")
+  void update_breakpoint (bool insert, const std::string& file,
+                          int line, const std::string& cond = "")
   {
     if (enabled ())
       instance->do_update_breakpoint (insert, file, line, cond);
   }
 
-  static bool
-  show_preferences ()
+  bool show_preferences (void)
   {
     if (enabled ())
       {
@@ -482,9 +468,7 @@
       return false;
   }
 
-  static std::string
-  gui_preference (const std::string& key,
-                  const std::string& value)
+  std::string gui_preference (const std::string& key, const std::string& value)
   {
     if (enabled ())
       {
@@ -494,8 +478,7 @@
       return "";
   }
 
-  static bool
-  show_doc (const std::string & file)
+  bool show_doc (const std::string& file)
   {
     if (enabled ())
       {
@@ -506,8 +489,7 @@
       return false;
   }
 
-  static bool
-  register_doc (const std::string & file)
+  bool register_doc (const std::string& file)
   {
     if (enabled ())
       {
@@ -518,8 +500,7 @@
       return false;
   }
 
-  static bool
-  unregister_doc (const std::string & file)
+  bool unregister_doc (const std::string& file)
   {
     if (enabled ())
       {
@@ -531,8 +512,7 @@
 
   }
 
-  static bool
-  edit_variable (const std::string &name, const octave_value& val)
+  bool edit_variable (const std::string& name, const octave_value& val)
   {
     if (enabled ())
       {
@@ -545,22 +525,22 @@
 
 private:
 
-  static octave_link_events *instance;
+  octave_link_events *instance;
 
-  static bool instance_ok (void) { return instance != nullptr; }
+  bool instance_ok (void) { return instance != nullptr; }
 
 protected:
 
   // Semaphore to lock access to the event queue.
-  static octave::mutex *event_queue_mutex;
+  octave::mutex *event_queue_mutex;
 
   // Event Queue.
-  static octave::event_queue gui_event_queue;
+  octave::event_queue gui_event_queue;
 
-  static bool debugging;
-  static bool link_enabled;
+  bool debugging;
+  bool link_enabled;
 
-  static void rethrow_exception_callback (const std::exception_ptr &p)
+  void rethrow_exception_callback (const std::exception_ptr& p)
   {
     std::rethrow_exception (p);
   }
--- a/libinterp/corefcn/syscalls.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/syscalls.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -1070,8 +1070,8 @@
 %! endif
 */
 
-DEFUNX ("unlink", Funlink, args, ,
-        doc: /* -*- texinfo -*-
+DEFMETHODX ("unlink", Funlink, interp, args, ,
+            doc: /* -*- texinfo -*-
 @deftypefn {} {[@var{err}, @var{msg}] =} unlink (@var{file})
 Delete the file named @var{file}.
 
@@ -1088,11 +1088,13 @@
 
   std::string msg;
 
-  octave_link::file_remove (name, "");
+  octave_link& olnk = interp.get_octave_link ();
+
+  olnk.file_remove (name, "");
 
   int status = octave::sys::unlink (name, msg);
 
-  octave_link::file_renamed (status == 0);
+  olnk.file_renamed (status == 0);
 
   return ovl (status, msg);
 }
--- a/libinterp/corefcn/variables.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/corefcn/variables.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -1229,7 +1229,9 @@
     {
       do_clear_variables (interp, argv, argc, true);
 
-      octave_link::clear_workspace ();
+      octave_link& olnk = interp.get_octave_link ();
+
+      olnk.clear_workspace ();
     }
   else
     {
--- a/libinterp/octave-value/ov-usr-fcn.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/octave-value/ov-usr-fcn.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -71,7 +71,12 @@
 
   // FIXME: shouldn't this happen automatically when deleting cmd_list?
   if (cmd_list)
-    cmd_list->remove_all_breakpoints (file_name);
+    {
+      octave_link& olnk
+        = octave::__get_octave_link__ ("octave_user_code::~octave_user_code");
+
+      cmd_list->remove_all_breakpoints (olnk, file_name);
+    }
 
   delete cmd_list;
   delete m_file_info;
--- a/libinterp/parse-tree/bp-table.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/parse-tree/bp-table.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -184,7 +184,11 @@
 
     if (cmds)
       {
-        retval = cmds->add_breakpoint (file, line, condition);
+        interpreter& interp = m_evaluator.get_interpreter ();
+
+        octave_link& olnk = interp.get_octave_link ();
+
+        retval = cmds->add_breakpoint (olnk, file, line, condition);
 
         for (auto& idx_line_p : retval)
           {
@@ -660,6 +664,10 @@
 
         if (results.length () > 0)
           {
+            interpreter& interp = m_evaluator.get_interpreter ();
+
+            octave_link& olnk = interp.get_octave_link ();
+
             octave_idx_type len = line.size ();
 
             for (int i = 0; i < len; i++)
@@ -673,7 +681,7 @@
                     cmds->delete_breakpoint (lineno);
 
                     if (! file.empty ())
-                      octave_link::update_breakpoint (false, file, lineno);
+                      olnk.update_breakpoint (false, file, lineno);
                   }
               }
 
@@ -756,7 +764,11 @@
 
         if (cmds)
           {
-            retval = cmds->remove_all_breakpoints (file);
+            interpreter& interp = m_evaluator.get_interpreter ();
+
+            octave_link& olnk = interp.get_octave_link ();
+
+            retval = cmds->remove_all_breakpoints (olnk, file);
 
             auto it = m_bp_set.find (fname);
             if (it != m_bp_set.end ())
--- a/libinterp/parse-tree/pt-eval.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -119,12 +119,6 @@
     bool m_abort_debug_repl;
   };
 
-  static void
-  execute_in_debugger_handler (const std::pair<std::string, int>& arg)
-  {
-    octave_link::execute_in_debugger_event (arg.first, arg.second);
-  }
-
   void debugger::repl (const std::string& prompt)
   {
     unwind_protect frame;
@@ -180,12 +174,15 @@
                 frm->display_stopped_in_message (buf);
               }
 
-            octave_link::enter_debugger_event (nm, curr_debug_line);
-
-            octave_link::set_workspace ();
-
-            frame.add_fcn (execute_in_debugger_handler,
-                           std::pair<std::string, int> (nm, curr_debug_line));
+            octave_link& olnk = m_interpreter.get_octave_link ();
+
+            olnk.enter_debugger_event (nm, curr_debug_line);
+
+            olnk.set_workspace ();
+
+            frame.add ([nm, curr_debug_line] (octave_link& ol) {
+                         ol.execute_in_debugger_event (nm, curr_debug_line);
+                       }, std::ref (olnk));
 
             if (! silent)
               {
--- a/libinterp/parse-tree/pt-stmt.cc	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/parse-tree/pt-stmt.cc	Wed Jul 17 14:09:20 2019 -0400
@@ -247,7 +247,8 @@
   // FIXME: COME BACK TO ME.
 
   bp_table::intmap
-  tree_statement_list::add_breakpoint (const std::string& file,
+  tree_statement_list::add_breakpoint (octave_link& olnk,
+                                       const std::string& file,
                                        const bp_table::intmap& line,
                                        const std::string& condition)
   {
@@ -266,7 +267,7 @@
             retval[i] = set_breakpoint (lineno, condition);
 
             if (retval[i] != 0 && ! file.empty ())
-              octave_link::update_breakpoint (true, file, retval[i], condition);
+              olnk.update_breakpoint (true, file, retval[i], condition);
           }
       }
 
@@ -274,7 +275,8 @@
   }
 
   bp_table::intmap
-  tree_statement_list::remove_all_breakpoints (const std::string& file)
+  tree_statement_list::remove_all_breakpoints (octave_link& olnk,
+                                               const std::string& file)
   {
     bp_table::intmap retval;
 
@@ -289,7 +291,7 @@
         retval[i] = lineno;
 
         if (! file.empty ())
-          octave_link::update_breakpoint (false, file, lineno);
+          olnk.update_breakpoint (false, file, lineno);
       }
 
     return retval;
--- a/libinterp/parse-tree/pt-stmt.h	Thu Jul 18 01:15:21 2019 -0400
+++ b/libinterp/parse-tree/pt-stmt.h	Wed Jul 17 14:09:20 2019 -0400
@@ -34,6 +34,8 @@
 #include "pt.h"
 #include "pt-walk.h"
 
+class octave_link;
+
 namespace octave
 {
   class comment_list;
@@ -183,11 +185,13 @@
 
     std::list<bp_type> breakpoints_and_conds (void);
 
-    bp_table::intmap add_breakpoint (const std::string& file,
+    bp_table::intmap add_breakpoint (octave_link& olnk,
+                                     const std::string& file,
                                      const bp_table::intmap& line,
                                      const std::string& condition);
 
-    bp_table::intmap remove_all_breakpoints (const std::string& file);
+    bp_table::intmap remove_all_breakpoints (octave_link& olnk,
+                                             const std::string& file);
 
     void accept (tree_walker& tw)
     {