changeset 23438:d24d01273bd0

eliminate load-path singleton * load-path.h, load-path.cc (class load_path): Don't use singleton idiom. * interpreter-private.h, interpreter-private.cc: New files. * interpreter.cc, interpreter.h (interpreter::m_load_path): New data member. Manage initialization of load_path in interpreter class. (interpreter::get_load_path): New method. Change all uses of static load_path methods to use global load_path object instead.
author John W. Eaton <jwe@octave.org>
date Thu, 20 Apr 2017 00:20:59 -0400
parents 442fe5b5afb5
children 054605b58513
files libgui/src/octave-qt-link.cc libinterp/corefcn/dirfns.cc libinterp/corefcn/help.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/load-path.cc libinterp/corefcn/load-path.h libinterp/corefcn/ls-mat5.cc libinterp/corefcn/module.mk libinterp/corefcn/symtab.cc libinterp/corefcn/utils.cc libinterp/corefcn/variables.cc libinterp/octave-value/ov-class.cc libinterp/octave-value/ov-classdef.cc libinterp/octave-value/ov-fcn-handle.cc libinterp/parse-tree/oct-parse.in.yy
diffstat 19 files changed, 1898 insertions(+), 1860 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/octave-qt-link.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libgui/src/octave-qt-link.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -37,6 +37,7 @@
 #include "builtin-defun-decls.h"
 #include "dialog.h"
 #include "error.h"
+#include "interpreter-private.h"
 #include "load-path.h"
 #include "utils.h"
 
@@ -563,14 +564,16 @@
     ok = true;
   else
     {
-      bool dir_in_load_path = load_path::contains_canonical (dir);
+      load_path& lp = octave::__get_load_path__ ("octave_qt_link::file_in_path");
+
+      bool dir_in_load_path = lp.contains_canonical (dir);
 
       // get base name, allowing "@class/method.m" (bug #41514)
       std::string base_file = (file.length () > dir.length ())
                               ? file.substr (dir.length () + 1)
                               : octave::sys::env::base_pathname (file);
 
-      std::string lp_file = load_path::find_file (base_file);
+      std::string lp_file = lp.find_file (base_file);
 
       if (dir_in_load_path)
         {
@@ -606,8 +609,12 @@
           break;
 
         case 2:
-          load_path::prepend (dir);
-          ok = true;
+          {
+            load_path& lp = octave::__get_load_path__ ("octave_qt_link::file_in_path");
+
+            lp.prepend (dir);
+            ok = true;
+          }
           break;
 
         default:
--- a/libinterp/corefcn/dirfns.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/dirfns.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -55,6 +55,7 @@
 #include "pager.h"
 #include "procstream.h"
 #include "sysdep.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -82,7 +83,9 @@
   // FIXME: should these actions be handled as a list of functions
   // to call so users can add their own chdir handlers?
 
-  load_path::update ();
+  load_path& lp = octave::__get_load_path__ ("octave_change_to_directory");
+
+  lp.update ();
 
   octave_link::change_directory (octave::sys::env::get_current_directory ());
 
--- a/libinterp/corefcn/help.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/help.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -50,6 +50,7 @@
 #include "errwarn.h"
 #include "help.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "ov-fcn-handle.h"
@@ -192,7 +193,9 @@
   const string_vector lcl = symbol_table::variable_names ();
   const int lcl_len = lcl.numel ();
 
-  const string_vector ffl = load_path::fcn_names ();
+  load_path& lp = octave::__get_load_path__ ("make_name_list");
+
+  const string_vector ffl = lp.fcn_names ();
   const int ffl_len = ffl.numel ();
 
   const string_vector afl = octave::autoloaded_functions ();
@@ -731,18 +734,22 @@
         {
           // We might find a file that contains only a doc string.
 
-          file = load_path::find_fcn_file (name);
+          load_path& lp = octave::__get_load_path__ ("do_which");
+
+          file = lp.find_fcn_file (name);
         }
     }
   else
     {
       // File query.
 
+      load_path& lp = octave::__get_load_path__ ("do_which");
+
       // For compatibility: "file." queries "file".
       if (name.size () > 1 && name[name.size () - 1] == '.')
-        file = load_path::find_file (name.substr (0, name.size () - 1));
+        file = lp.find_file (name.substr (0, name.size () - 1));
       else
-        file = load_path::find_file (name);
+        file = lp.find_file (name);
 
       file = octave::sys::env::make_absolute (file);
     }
@@ -837,10 +844,12 @@
 {
   octave_value retval;
 
+  load_path& lp = octave::__get_load_path__ ("__list_functions__");
+
   if (args.length () == 0)
     {
       // Get list of all functions
-      string_vector ffl = load_path::fcn_names ();
+      string_vector ffl = lp.fcn_names ();
       string_vector afl = octave::autoloaded_functions ();
 
       retval = Cell (ffl.append (afl));
@@ -849,7 +858,7 @@
     {
       std::string dir = args(0).xstring_value ("__list_functions__: DIRECTORY argument must be a string");
 
-      string_vector fl = load_path::files (dir, true);
+      string_vector fl = lp.files (dir, true);
 
       // Return a sorted list with unique entries (in case of .m and .oct
       // versions of the same function in a given directory, for example).
--- a/libinterp/corefcn/input.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/input.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -50,6 +50,7 @@
 #include "help.h"
 #include "hook-fcn.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
@@ -280,7 +281,9 @@
     if (retval != "\n"
         && retval.find_first_not_of (" \t\n\r") != std::string::npos)
       {
-        load_path::update ();
+        load_path& lp = octave::__get_load_path__ ("base_reader::octave_gets");
+
+        lp.update ();
 
         if (Vdebugging)
           last_debugging_command = retval;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/interpreter-private.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -0,0 +1,51 @@
+/*
+
+Copyright (C) 2017 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <string>
+
+#include "error.h"
+#include "interpreter-private.h"
+#include "octave.h"
+
+namespace octave
+{
+  interpreter& __get_interpreter__ (const std::string& who)
+  {
+    interpreter *interp = octave::application::the_interpreter ();
+
+    if (! interp)
+      error ("%s: interpreter context missing", who.c_str ());
+
+    return *interp;
+  }
+
+  load_path& __get_load_path__ (const std::string& who)
+  {
+    interpreter& interp = __get_interpreter__ (who);
+
+    return interp.get_load_path ();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/interpreter-private.h	Thu Apr 20 00:20:59 2017 -0400
@@ -0,0 +1,40 @@
+/*
+
+Copyright (C) 2017 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_interpreter_private_h)
+#define octave_interpreter_private_h 1
+
+#include "octave-config.h"
+
+#include <string>
+
+#include "interpreter.h"
+
+namespace octave
+{
+  // Expect these functions to change without warning.
+  extern interpreter& __get_interpreter__ (const std::string& who);
+
+  extern load_path& __get_load_path__ (const std::string& who);
+}
+
+#endif
--- a/libinterp/corefcn/interpreter.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/interpreter.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -47,6 +47,7 @@
 #include "error.h"
 #include "file-io.h"
 #include "graphics.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "load-save.h"
@@ -342,9 +343,11 @@
 {
   std::string file_name = octave::sys::file_ops::concat (dir, "PKG_ADD");
 
+  load_path& lp = octave::__get_load_path__ ("execute_pkg_add");
+
   try
     {
-      load_path::execute_pkg_add (dir);
+      lp.execute_pkg_add (dir);
     }
   catch (const octave::interrupt_exception&)
     {
@@ -366,7 +369,7 @@
 
   interpreter::interpreter (application *app_context)
     : m_app_context (app_context), m_evaluator (new tree_evaluator (this)),
-      m_interactive (false), m_read_site_files (true),
+      m_load_path (), m_interactive (false), m_read_site_files (true),
       m_read_init_files (m_app_context != 0), m_verbose (false),
       m_inhibit_startup_message (false), m_load_path_initialized (false),
       m_history_initialized (false), m_initialized (false)
@@ -446,7 +449,7 @@
         std::list<std::string> command_line_path = options.command_line_path ();
 
         for (const auto& pth : command_line_path)
-          load_path::set_command_line_path (pth);
+          m_load_path.set_command_line_path (pth);
 
         std::string exec_path = options.exec_path ();
         if (! exec_path.empty ())
@@ -561,11 +564,12 @@
 
         octave::unwind_protect frame;
 
-        frame.add_fcn (load_path::set_add_hook, load_path::get_add_hook ());
+        frame.add_method (m_load_path, &load_path::set_add_hook,
+                          m_load_path.get_add_hook ());
 
-        load_path::set_add_hook (execute_pkg_add);
+        m_load_path.set_add_hook (execute_pkg_add);
 
-        load_path::initialize (set_initial_path);
+        m_load_path.initialize (set_initial_path);
 
         m_load_path_initialized = true;
       }
--- a/libinterp/corefcn/interpreter.h	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/interpreter.h	Thu Apr 20 00:20:59 2017 -0400
@@ -30,6 +30,8 @@
 #include "quit.h"
 #include "str-vec.h"
 
+#include "load-path.h"
+
 extern OCTINTERP_API bool quit_allowed;
 
 // TRUE means we are ready to interpret commands, but not everything
@@ -130,6 +132,11 @@
       return m_initialized;
     }
 
+    load_path& get_load_path (void)
+    {
+      return m_load_path;
+    }
+
     static void recover_from_exception (void);
 
     static void add_atexit_function (const std::string& fname);
@@ -156,6 +163,8 @@
 
     tree_evaluator *m_evaluator;
 
+    load_path m_load_path;
+
     // TRUE means this is an interactive interpreter (forced or not).
     bool m_interactive;
 
--- a/libinterp/corefcn/load-path.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/load-path.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -1,23 +1,23 @@
 /*
 
-Copyright (C) 2006-2017 John W. Eaton
-Copyright (C) 2010 VZLU Prague
-
-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
-<http://www.gnu.org/licenses/>.
+  Copyright (C) 2006-2017 John W. Eaton
+  Copyright (C) 2010 VZLU Prague
+
+  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
+  <http://www.gnu.org/licenses/>.
 
 */
 
@@ -32,11 +32,11 @@
 #include "file-stat.h"
 #include "oct-env.h"
 #include "pathsearch.h"
-#include "singleton-cleanup.h"
 
 #include "defaults.h"
 #include "defun.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "ov-usr-fcn.h"
@@ -45,13 +45,1070 @@
 #include "unwind-prot.h"
 #include "utils.h"
 
-load_path *load_path::instance = 0;
-load_path::hook_fcn_ptr load_path::add_hook = load_path::execute_pkg_add;
-load_path::hook_fcn_ptr load_path::remove_hook = load_path::execute_pkg_del;
-std::string load_path::command_line_path;
 std::string load_path::sys_path;
 load_path::abs_dir_cache_type load_path::abs_dir_cache;
 
+static void
+maybe_add_path_elts (std::string& path, const std::string& dir)
+{
+  std::string tpath = genpath (dir);
+
+  if (! tpath.empty ())
+    {
+      if (path.empty ())
+        path = tpath;
+      else
+        path += octave::directory_path::path_sep_str () + tpath;
+    }
+}
+
+static std::list<std::string>
+split_path (const std::string& p)
+{
+  std::list<std::string> retval;
+
+  size_t beg = 0;
+  size_t end = p.find (octave::directory_path::path_sep_char ());
+
+  size_t len = p.length ();
+
+  while (end != std::string::npos)
+    {
+      std::string elt = p.substr (beg, end-beg);
+
+      if (! elt.empty ())
+        retval.push_back (elt);
+
+      beg = end + 1;
+
+      if (beg == len)
+        break;
+
+      end = p.find (octave::directory_path::path_sep_char (), beg);
+    }
+
+  std::string elt = p.substr (beg);
+
+  if (! elt.empty ())
+    retval.push_back (elt);
+
+  return retval;
+}
+
+// Strip trailing directory separators.
+
+static std::string
+strip_trailing_separators (const std::string& dir_arg)
+{
+  std::string dir = dir_arg;
+
+  size_t k = dir.length ();
+
+  while (k > 1 && octave::sys::file_ops::is_dir_sep (dir[k-1]))
+    k--;
+
+  if (k < dir.length ())
+    dir.resize (k);
+
+  return dir;
+}
+
+// Should we cache all files in private directories, or is it OK to just
+// look them up each time as needed?
+
+static std::string
+find_private_file (const std::string& fname)
+{
+  std::string retval;
+
+  // Look in private directory corresponding to current function (if
+  // any).
+
+  octave_user_function *curr_fcn = symbol_table::get_curr_fcn ();
+
+  if (curr_fcn)
+    {
+      // Even for private functions, dir_name doesn't contain the
+      // "private" directory component so we append it here in all
+      // cases.
+
+      std::string dir_name = curr_fcn->dir_name ();
+
+      if (! dir_name.empty ())
+        {
+          std::string pfname = dir_name + octave::sys::file_ops::dir_sep_str ()
+                               + "private" + octave::sys::file_ops::dir_sep_str () + fname;
+
+          octave::sys::file_stat fs (pfname);
+
+          if (fs.exists () && fs.is_reg ())
+            retval = pfname;
+        }
+    }
+
+  return retval;
+}
+
+static void
+execute_pkg_add_or_del (const std::string& dir,
+                        const std::string& script_file)
+{
+  if (! octave_interpreter_ready)
+    return;
+
+  octave::unwind_protect frame;
+
+  std::string file = octave::sys::file_ops::concat (dir, script_file);
+
+  octave::sys::file_stat fs (file);
+
+  if (fs.exists ())
+    octave::source_file (file, "base");
+}
+
+// True if a path is contained in a path list separated by path_sep_char
+
+static bool
+in_path_list (const std::string& path_list, const std::string& path)
+{
+  size_t ps = path.size ();
+  size_t pls = path_list.size ();
+  size_t pos = path_list.find (path);
+  char psc = octave::directory_path::path_sep_char ();
+  while (pos != std::string::npos)
+    {
+      if ((pos == 0 || path_list[pos-1] == psc)
+          && (pos + ps == pls || path_list[pos + ps] == psc))
+        return true;
+      else
+        pos = path_list.find (path, pos + 1);
+    }
+
+  return false;
+}
+
+static void
+rehash_internal (void)
+{
+  load_path& lp = octave::__get_load_path__ ("rehash_internal");
+
+  lp.update ();
+
+  // FIXME: maybe we should rename this variable since it is being
+  // used for more than keeping track of the prompt time.
+
+  // This will force updated functions to be found.
+  Vlast_prompt_time.stamp ();
+}
+
+void
+load_path::initialize (bool set_initial_path)
+{
+  sys_path = "";
+
+  if (set_initial_path)
+    {
+      maybe_add_path_elts (sys_path, Vlocal_ver_oct_file_dir);
+      maybe_add_path_elts (sys_path, Vlocal_api_oct_file_dir);
+      maybe_add_path_elts (sys_path, Vlocal_oct_file_dir);
+      maybe_add_path_elts (sys_path, Vlocal_ver_fcn_file_dir);
+      maybe_add_path_elts (sys_path, Vlocal_api_fcn_file_dir);
+      maybe_add_path_elts (sys_path, Vlocal_fcn_file_dir);
+      maybe_add_path_elts (sys_path, Voct_file_dir);
+      maybe_add_path_elts (sys_path, Vfcn_file_dir);
+      maybe_add_path_elts (sys_path, Voct_data_dir);
+    }
+
+  std::string tpath = load_path::m_command_line_path;
+
+  if (tpath.empty ())
+    tpath = octave::sys::env::getenv ("OCTAVE_PATH");
+
+  std::string xpath;
+
+  if (! tpath.empty ())
+    {
+      xpath = tpath;
+
+      if (! sys_path.empty ())
+        xpath += octave::directory_path::path_sep_str () + sys_path;
+    }
+  else
+    xpath = sys_path;
+
+  set (xpath, false, true);
+}
+
+void
+load_path::clear (void)
+{
+  dir_info_list.clear ();
+
+  top_level_package.clear ();
+
+  package_map.clear ();
+}
+
+void
+load_path::set (const std::string& p, bool warn, bool is_init)
+{
+  // Use a list when we need to preserve order.
+  std::list<std::string> elts = split_path (p);
+
+  // Use a set when we need to search and order is not important.
+  std::set<std::string> elts_set (elts.begin (), elts.end ());
+
+  if (is_init)
+    init_dirs = elts_set;
+  else
+    {
+      for (const auto& init_dir : init_dirs)
+        {
+          if (elts_set.find (init_dir) == elts_set.end ())
+            {
+              warning_with_id ("Octave:remove-init-dir",
+                               "default load path altered.  Some built-in functions may not be found.  Try restoredefaultpath() to recover it.");
+              break;
+            }
+        }
+    }
+
+  // Temporarily disable add hook.
+
+  octave::unwind_protect frame;
+  frame.protect_var (add_hook);
+
+  add_hook = 0;
+
+  clear ();
+
+  for (const auto& elt : elts)
+    append (elt, warn);
+
+  // Restore add hook and execute for all newly added directories.
+  frame.run_first ();
+
+  // FIXME: Shouldn't the test for add_hook be outside the for loop?
+  //        Why not use const here?  Does add_hook change dir_info_list?
+  for (auto& di : dir_info_list)
+    {
+      if (add_hook)
+        add_hook (di.dir_name);
+    }
+
+  // Always prepend current directory.
+  prepend (".", warn);
+}
+
+void
+load_path::append (const std::string& dir, bool warn)
+{
+  if (! dir.empty ())
+    add (dir, true, warn);
+}
+
+void
+load_path::prepend (const std::string& dir, bool warn)
+{
+  if (! dir.empty ())
+    add (dir, false, warn);
+}
+
+bool
+load_path::remove (const std::string& dir_arg)
+{
+  bool retval = false;
+
+  if (! dir_arg.empty ())
+    {
+      if (dir_arg == ".")
+        {
+          warning ("rmpath: can't remove \".\" from path");
+
+          // Avoid additional warnings.
+          retval = true;
+        }
+      else
+        {
+          std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
+
+          dir = strip_trailing_separators (dir);
+
+          dir_info_list_iterator i = find_dir_info (dir);
+
+          if (i != dir_info_list.end ())
+            {
+              retval = true;
+
+              if (remove_hook)
+                remove_hook (dir);
+
+              dir_info& di = *i;
+
+              remove (di);
+
+              dir_info_list.erase (i);
+            }
+        }
+    }
+
+  return retval;
+}
+
+void
+load_path::update (void) const
+{
+  // I don't see a better way to do this because we need to
+  // preserve the correct directory ordering for new files that
+  // have appeared.
+
+  top_level_package.clear ();
+
+  package_map.clear ();
+
+  for (auto& di : dir_info_list)
+    {
+      di.update ();
+
+      add (di, true, "", true);
+    }
+}
+
+bool
+load_path::contains_canonical (const std::string& dir) const
+{
+  bool retval = false;
+
+  for (const auto& d : dir_info_list)
+    {
+      if (same_file (dir, d.dir_name))
+        {
+          retval = true;
+          break;
+        }
+    }
+
+  return retval;
+}
+
+std::list<std::string>
+load_path::overloads (const std::string& meth) const
+{
+  std::list<std::string> retval;
+
+  //  update ();
+
+  top_level_package.overloads (meth, retval);
+
+  for (const auto& nm_ldr : package_map)
+    nm_ldr.second.overloads (meth, retval);
+
+  return retval;
+}
+
+std::list<std::string>
+load_path::get_all_package_names (bool only_top_level) const
+{
+  std::list<std::string> retval;
+
+  for (const auto& dir_ldr : package_map)
+    {
+      if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos)
+        retval.push_back (dir_ldr.first);
+    }
+
+  return retval;
+}
+
+std::string
+load_path::find_file (const std::string& file) const
+{
+  std::string retval;
+
+  if (octave::sys::env::absolute_pathname (file)
+      || octave::sys::env::rooted_relative_pathname (file))
+    {
+      octave::sys::file_stat fs (file);
+
+      return fs.exists () ? file : retval;
+    }
+  else
+    {
+      std::string tfile = find_private_file (file);
+
+      if (! tfile.empty ())
+        return tfile;
+    }
+
+  if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
+      != std::string::npos)
+    {
+      // Given name has a directory separator, so append it to each
+      // element of the load path in turn.
+      for (const auto& di : dir_info_list)
+        {
+          std::string tfile = octave::sys::file_ops::concat (di.dir_name, file);
+
+          octave::sys::file_stat fs (tfile);
+
+          if (fs.exists ())
+            return tfile;
+        }
+    }
+  else
+    {
+      // Look in cache.
+      for (const auto & di : dir_info_list)
+        {
+          string_vector all_files = di.all_files;
+
+          octave_idx_type len = all_files.numel ();
+
+          for (octave_idx_type i = 0; i < len; i++)
+            {
+              if (all_files[i] == file)
+                return octave::sys::file_ops::concat (di.dir_name, file);
+            }
+        }
+    }
+
+  return retval;
+}
+
+std::string
+load_path::find_dir (const std::string& dir) const
+{
+  std::string retval;
+
+  if (dir.find_first_of (octave::sys::file_ops::dir_sep_chars ()) != std::string::npos
+      && (octave::sys::env::absolute_pathname (dir)
+          || octave::sys::env::rooted_relative_pathname (dir)))
+    {
+      octave::sys::file_stat fs (dir);
+
+      if (fs.exists () && fs.is_dir ())
+        return dir;
+    }
+  else
+    {
+      for (const auto& di : dir_info_list)
+        {
+          std::string dname = octave::sys::env::make_absolute (di.dir_name);
+
+          size_t dname_len = dname.length ();
+
+          if (dname.substr (dname_len - 1)
+              == octave::sys::file_ops::dir_sep_str ())
+            {
+              dname = dname.substr (0, dname_len - 1);
+              dname_len--;
+            }
+
+          size_t dir_len = dir.length ();
+
+          if (dname_len > dir_len
+              && octave::sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
+              && dir == dname.substr (dname_len - dir_len))
+            {
+              octave::sys::file_stat fs (di.dir_name);
+
+              if (fs.exists () && fs.is_dir ())
+                return di.dir_name;
+            }
+        }
+    }
+
+  return retval;
+}
+
+string_vector
+load_path::find_matching_dirs (const std::string& dir) const
+{
+  std::list<std::string> retlist;
+
+  if (dir.find_first_of (octave::sys::file_ops::dir_sep_chars ()) != std::string::npos
+      && (octave::sys::env::absolute_pathname (dir)
+          || octave::sys::env::rooted_relative_pathname (dir)))
+    {
+      octave::sys::file_stat fs (dir);
+
+      if (fs.exists () && fs.is_dir ())
+        retlist.push_back (dir);
+    }
+  else
+    {
+      for (const auto& di : dir_info_list)
+        {
+          std::string dname = octave::sys::env::make_absolute (di.dir_name);
+
+          size_t dname_len = dname.length ();
+
+          if (dname.substr (dname_len - 1)
+              == octave::sys::file_ops::dir_sep_str ())
+            {
+              dname = dname.substr (0, dname_len - 1);
+              dname_len--;
+            }
+
+          size_t dir_len = dir.length ();
+
+          if (dname_len > dir_len
+              && octave::sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
+              && dir == dname.substr (dname_len - dir_len))
+            {
+              octave::sys::file_stat fs (di.dir_name);
+
+              if (fs.exists () && fs.is_dir ())
+                retlist.push_back (di.dir_name);
+            }
+        }
+    }
+
+  return retlist;
+}
+
+std::string
+load_path::find_first_of (const string_vector& flist) const
+{
+  std::string retval;
+
+  std::string dir_name;
+  std::string file_name;
+
+  octave_idx_type flen = flist.numel ();
+  octave_idx_type rel_flen = 0;
+
+  string_vector rel_flist (flen);
+
+  for (octave_idx_type i = 0; i < flen; i++)
+    {
+      std::string file = flist[i];
+
+      if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
+          != std::string::npos)
+        {
+          if (octave::sys::env::absolute_pathname (file)
+              || octave::sys::env::rooted_relative_pathname (file))
+            {
+              octave::sys::file_stat fs (file);
+
+              if (fs.exists ())
+                return file;
+            }
+          else
+            {
+              for (const auto& di : dir_info_list)
+                {
+                  std::string tfile;
+                  tfile = octave::sys::file_ops::concat (di.dir_name, file);
+
+                  octave::sys::file_stat fs (tfile);
+
+                  if (fs.exists ())
+                    return tfile;
+                }
+            }
+        }
+      else
+        rel_flist[rel_flen++] = file;
+    }
+
+  rel_flist.resize (rel_flen);
+
+  for (const auto& di : dir_info_list)
+    {
+      string_vector all_files = di.all_files;
+
+      octave_idx_type len = all_files.numel ();
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          for (octave_idx_type j = 0; j < rel_flen; j++)
+            {
+              if (all_files[i] == rel_flist[j])
+                {
+                  dir_name = di.dir_name;
+                  file_name = rel_flist[j];
+
+                  goto done;
+                }
+            }
+        }
+    }
+
+ done:
+
+  if (! dir_name.empty ())
+    retval = octave::sys::file_ops::concat (dir_name, file_name);
+
+  return retval;
+}
+
+string_vector
+load_path::find_all_first_of (const string_vector& flist) const
+{
+  std::list<std::string> retlist;
+
+  std::string dir_name;
+  std::string file_name;
+
+  octave_idx_type flen = flist.numel ();
+  octave_idx_type rel_flen = 0;
+
+  string_vector rel_flist (flen);
+
+  for (octave_idx_type i = 0; i < flen; i++)
+    {
+      std::string file = flist[i];
+
+      if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
+          != std::string::npos)
+        {
+          if (octave::sys::env::absolute_pathname (file)
+              || octave::sys::env::rooted_relative_pathname (file))
+            {
+              octave::sys::file_stat fs (file);
+
+              if (fs.exists ())
+                retlist.push_back (file);
+            }
+          else
+            {
+              for (const auto& di : dir_info_list)
+                {
+                  std::string tfile;
+                  tfile = octave::sys::file_ops::concat (di.dir_name, file);
+
+                  octave::sys::file_stat fs (tfile);
+
+                  if (fs.exists ())
+                    retlist.push_back (tfile);
+                }
+            }
+        }
+      else
+        rel_flist[rel_flen++] = file;
+    }
+
+  rel_flist.resize (rel_flen);
+
+  for (const auto& di : dir_info_list)
+    {
+      string_vector all_files = di.all_files;
+
+      octave_idx_type len = all_files.numel ();
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          for (octave_idx_type j = 0; j < rel_flen; j++)
+            {
+              if (all_files[i] == rel_flist[j])
+                retlist.push_back (octave::sys::file_ops::concat (di.dir_name,
+                                                                  rel_flist[j]));
+            }
+        }
+    }
+
+  return retlist;
+}
+
+string_vector
+load_path::dirs (void) const
+{
+  size_t len = dir_info_list.size ();
+
+  string_vector retval (len);
+
+  octave_idx_type k = 0;
+
+  for (const auto& di : dir_info_list)
+    retval[k++] = di.dir_name;
+
+  return retval;
+}
+
+std::list<std::string>
+load_path::dir_list (void) const
+{
+  std::list<std::string> retval;
+
+  for (const auto& di : dir_info_list)
+    retval.push_back (di.dir_name);
+
+  return retval;
+}
+
+string_vector
+load_path::files (const std::string& dir, bool omit_exts) const
+{
+  string_vector retval;
+
+  const_dir_info_list_iterator p = find_dir_info (dir);
+
+  if (p != dir_info_list.end ())
+    retval = p->fcn_files;
+
+  if (omit_exts)
+    {
+      octave_idx_type len = retval.numel ();
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          std::string fname = retval[i];
+
+          size_t pos = fname.rfind ('.');
+
+          if (pos != std::string::npos)
+            retval[i] = fname.substr (0, pos);
+        }
+    }
+
+  return retval;
+}
+
+string_vector
+load_path::fcn_names (void) const
+{
+  return top_level_package.fcn_names ();
+}
+
+std::string
+load_path::path (void) const
+{
+  std::string xpath;
+
+  string_vector xdirs = load_path::dirs ();
+
+  octave_idx_type len = xdirs.numel ();
+
+  if (len > 0)
+    xpath = xdirs[0];
+
+  for (octave_idx_type i = 1; i < len; i++)
+    xpath += octave::directory_path::path_sep_str () + xdirs[i];
+
+  return xpath;
+}
+
+void
+load_path::display (std::ostream& os) const
+{
+  for (const auto& di : dir_info_list)
+    {
+      string_vector fcn_files = di.fcn_files;
+
+      if (! fcn_files.empty ())
+        {
+          os << "\n*** function files in " << di.dir_name << ":\n\n";
+
+          fcn_files.list_in_columns (os);
+        }
+
+      const dir_info::method_file_map_type& method_file_map
+        = di.method_file_map;
+
+      if (! method_file_map.empty ())
+        {
+          for (const auto& cls_ci : method_file_map)
+            {
+              os << "\n*** methods in " << di.dir_name
+                 << "/@" << cls_ci.first << ":\n\n";
+
+              const dir_info::class_info& ci = cls_ci.second;
+
+              string_vector method_files = get_file_list (ci.method_file_map);
+
+              method_files.list_in_columns (os);
+            }
+        }
+    }
+
+  top_level_package.display (os);
+
+  for (const auto& nm_ldr : package_map)
+    nm_ldr.second.display (os);
+}
+
+void
+load_path::execute_pkg_add (const std::string& dir)
+{
+  execute_pkg_add_or_del (dir, "PKG_ADD");
+}
+
+void
+load_path::execute_pkg_del (const std::string& dir)
+{
+  execute_pkg_add_or_del (dir, "PKG_DEL");
+}
+
+// FIXME: maybe we should also maintain a map to speed up this method of access.
+
+load_path::const_dir_info_list_iterator
+load_path::find_dir_info (const std::string& dir_arg) const
+{
+  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
+
+  const_dir_info_list_iterator retval = dir_info_list.begin ();
+
+  while (retval != dir_info_list.end ())
+    {
+      if (retval->dir_name == dir)
+        break;
+
+      retval++;
+    }
+
+  return retval;
+}
+
+load_path::dir_info_list_iterator
+load_path::find_dir_info (const std::string& dir_arg)
+{
+  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
+
+  dir_info_list_iterator retval = dir_info_list.begin ();
+
+  while (retval != dir_info_list.end ())
+    {
+      if (retval->dir_name == dir)
+        break;
+
+      retval++;
+    }
+
+  return retval;
+}
+
+bool
+load_path::contains (const std::string& dir) const
+{
+  return find_dir_info (dir) != dir_info_list.end ();
+}
+
+void
+load_path::move (dir_info_list_iterator i, bool at_end)
+{
+  if (dir_info_list.size () > 1)
+    {
+      dir_info di = *i;
+
+      dir_info_list.erase (i);
+
+      if (at_end)
+        dir_info_list.push_back (di);
+      else
+        dir_info_list.push_front (di);
+
+      move (di, at_end);
+    }
+}
+
+void
+load_path::move (const dir_info& di, bool at_end, const std::string& pname)
+{
+  package_info& l = get_package (pname);
+
+  l.move (di, at_end);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (const auto& pkg_di : package_dir_map)
+    {
+      std::string full_name = pkg_di.first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      move (pkg_di.second, at_end, full_name);
+    }
+}
+
+void
+load_path::add (const std::string& dir_arg, bool at_end, bool warn)
+{
+  size_t len = dir_arg.length ();
+
+  if (len > 1 && dir_arg.substr (len-2) == "//")
+    warning_with_id ("Octave:recursive-path-search",
+                     "trailing '//' is no longer special in search path elements");
+
+  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
+
+  dir = strip_trailing_separators (dir);
+
+  dir_info_list_iterator i = find_dir_info (dir);
+
+  if (i != dir_info_list.end ())
+    move (i, at_end);
+  else
+    {
+      octave::sys::file_stat fs (dir);
+
+      if (fs)
+        {
+          if (fs.is_dir ())
+            {
+              dir_info di (dir);
+
+              if (at_end)
+                dir_info_list.push_back (di);
+              else
+                dir_info_list.push_front (di);
+
+              add (di, at_end);
+
+              if (add_hook)
+                add_hook (dir);
+            }
+          else if (warn)
+            warning ("addpath: %s: not a directory", dir_arg.c_str ());
+        }
+      else if (warn)
+        {
+          std::string msg = fs.error ();
+          warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
+        }
+    }
+
+  // FIXME: is there a better way to do this?
+
+  i = find_dir_info (".");
+
+  if (i != dir_info_list.end ())
+    move (i, false);
+}
+
+void
+load_path::remove (const dir_info& di, const std::string& pname)
+{
+  package_info& l = get_package (pname);
+
+  l.remove (di);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (const auto& pkg_di : package_dir_map)
+    {
+      std::string full_name = pkg_di.first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      remove (pkg_di.second, full_name);
+    }
+}
+
+bool
+load_path::is_package (const std::string& name) const
+{
+  for (const auto& di : dir_info_list)
+    {
+      if (di.is_package (name))
+        return true;
+    }
+
+  return false;
+}
+
+void
+load_path::add (const dir_info& di, bool at_end,
+                const std::string& pname, bool updating) const
+{
+  package_info& l = get_package (pname);
+
+  l.add (di, at_end, updating);
+
+  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
+
+  for (const auto& pkg_di : package_dir_map)
+    {
+      std::string full_name = pkg_di.first;
+
+      if (! pname.empty ())
+        full_name = pname + "." + full_name;
+
+      add (pkg_di.second, at_end, full_name);
+    }
+}
+
+string_vector
+load_path::get_file_list (const load_path::dir_info::fcn_file_map_type& lst) const
+{
+  octave_idx_type n = lst.size ();
+
+  string_vector retval (n);
+
+  octave_idx_type count = 0;
+
+  for (const auto& nm_typ : lst)
+    {
+      std::string nm = nm_typ.first;
+
+      int types = nm_typ.second;
+
+      if (types & load_path::OCT_FILE)
+        nm += ".oct";
+      else if (types & load_path::MEX_FILE)
+        nm += ".mex";
+      else
+        nm += ".m";
+
+      retval[count++] = nm;
+    }
+
+  return retval;
+}
+
+load_path::dir_info::fcn_file_map_type
+get_fcn_files (const std::string& d)
+{
+  load_path::dir_info::fcn_file_map_type retval;
+
+  octave::sys::dir_entry dir (d);
+
+  if (dir)
+    {
+      string_vector flist = dir.read ();
+
+      octave_idx_type len = flist.numel ();
+
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          std::string fname = flist[i];
+
+          size_t pos = fname.rfind ('.');
+
+          if (pos != std::string::npos)
+            {
+              std::string base = fname.substr (0, pos);
+              std::string ext = fname.substr (pos);
+
+              if (valid_identifier (base))
+                {
+                  int t = 0;
+
+                  if (ext == ".m")
+                    t = load_path::M_FILE;
+                  else if (ext == ".oct")
+                    t = load_path::OCT_FILE;
+                  else if (ext == ".mex")
+                    t = load_path::MEX_FILE;
+
+                  if (t)
+                    retval[base] = t;
+                }
+            }
+        }
+    }
+  else
+    {
+      std::string msg = dir.error ();
+      warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
+    }
+
+  return retval;
+}
+
 void
 load_path::dir_info::update (void)
 {
@@ -70,7 +1127,7 @@
             {
               std::string abs_name = octave::sys::env::make_absolute (dir_name);
 
-              abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
+              const_abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
 
               if (p != abs_dir_cache.end ())
                 {
@@ -250,56 +1307,6 @@
     }
 }
 
-load_path::dir_info::fcn_file_map_type
-get_fcn_files (const std::string& d)
-{
-  load_path::dir_info::fcn_file_map_type retval;
-
-  octave::sys::dir_entry dir (d);
-
-  if (dir)
-    {
-      string_vector flist = dir.read ();
-
-      octave_idx_type len = flist.numel ();
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string fname = flist[i];
-
-          size_t pos = fname.rfind ('.');
-
-          if (pos != std::string::npos)
-            {
-              std::string base = fname.substr (0, pos);
-              std::string ext = fname.substr (pos);
-
-              if (valid_identifier (base))
-                {
-                  int t = 0;
-
-                  if (ext == ".m")
-                    t = load_path::M_FILE;
-                  else if (ext == ".oct")
-                    t = load_path::OCT_FILE;
-                  else if (ext == ".mex")
-                    t = load_path::MEX_FILE;
-
-                  if (t)
-                    retval[base] = t;
-                }
-            }
-        }
-    }
-  else
-    {
-      std::string msg = dir.error ();
-      warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
-    }
-
-  return retval;
-}
-
 void
 load_path::dir_info::get_private_file_map (const std::string& d)
 {
@@ -327,215 +1334,6 @@
   package_dir_map[package_name] = dir_info (d);
 }
 
-bool
-load_path::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new load_path ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    error ("unable to create load path object!");
-
-  return retval;
-}
-
-// FIXME: maybe we should also maintain a map to speed up this method of access.
-
-load_path::const_dir_info_list_iterator
-load_path::find_dir_info (const std::string& dir_arg) const
-{
-  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
-
-  const_dir_info_list_iterator retval = dir_info_list.begin ();
-
-  while (retval != dir_info_list.end ())
-    {
-      if (retval->dir_name == dir)
-        break;
-
-      retval++;
-    }
-
-  return retval;
-}
-
-load_path::dir_info_list_iterator
-load_path::find_dir_info (const std::string& dir_arg)
-{
-  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
-
-  dir_info_list_iterator retval = dir_info_list.begin ();
-
-  while (retval != dir_info_list.end ())
-    {
-      if (retval->dir_name == dir)
-        break;
-
-      retval++;
-    }
-
-  return retval;
-}
-
-bool
-load_path::contains (const std::string& dir) const
-{
-  return find_dir_info (dir) != dir_info_list.end ();
-}
-
-bool
-load_path::do_contains_canonical (const std::string& dir) const
-{
-  bool retval = false;
-
-  for (const auto& d : dir_info_list)
-    {
-      if (same_file (dir, d.dir_name))
-        {
-          retval = true;
-          break;
-        }
-    }
-
-  return retval;
-}
-
-void
-load_path::package_info::move_fcn_map (const std::string& dir_name,
-                                 const string_vector& fcn_files, bool at_end)
-{
-  octave_idx_type len = fcn_files.numel ();
-
-  for (octave_idx_type k = 0; k < len; k++)
-    {
-      std::string fname = fcn_files[k];
-
-      std::string ext;
-      std::string base = fname;
-
-      size_t pos = fname.rfind ('.');
-
-      if (pos != std::string::npos)
-        {
-          base = fname.substr (0, pos);
-          ext = fname.substr (pos);
-        }
-
-      file_info_list_type& file_info_list = fcn_map[base];
-
-      if (file_info_list.size () == 1)
-        continue;
-      else
-        {
-          for (auto fi_it = file_info_list.begin ();
-               fi_it != file_info_list.end ();
-               fi_it++)
-            {
-              if (fi_it->dir_name == dir_name)
-                {
-                  file_info fi_tmp = *fi_it;
-
-                  file_info_list.erase (fi_it);
-
-                  if (at_end)
-                    file_info_list.push_back (fi_tmp);
-                  else
-                    file_info_list.push_front (fi_tmp);
-
-                  break;
-                }
-            }
-        }
-    }
-}
-
-void
-load_path::package_info::move_method_map (const std::string& dir_name, bool at_end)
-{
-  for (auto& cls_fnmap : method_map)
-    {
-      std::string class_name = cls_fnmap.first;
-
-      fcn_map_type& fn_map = cls_fnmap.second;
-
-      std::string full_dir_name
-        = octave::sys::file_ops::concat (dir_name, "@" + class_name);
-
-      for (auto& nm_filst : fn_map)
-        {
-          file_info_list_type& file_info_list = nm_filst.second;
-
-          if (file_info_list.size () == 1)
-            continue;
-          else
-            {
-              for (auto fi_it = file_info_list.begin ();
-                   fi_it != file_info_list.end (); fi_it++)
-                {
-                  if (fi_it->dir_name == full_dir_name)
-                    {
-                      file_info fi_tmp = *fi_it;
-
-                      file_info_list.erase (fi_it);
-
-                      if (at_end)
-                        file_info_list.push_back (fi_tmp);
-                      else
-                        file_info_list.push_front (fi_tmp);
-
-                      break;
-                    }
-                }
-            }
-        }
-    }
-}
-
-void
-load_path::do_move (dir_info_list_iterator i, bool at_end)
-{
-  if (dir_info_list.size () > 1)
-    {
-      dir_info di = *i;
-
-      dir_info_list.erase (i);
-
-      if (at_end)
-        dir_info_list.push_back (di);
-      else
-        dir_info_list.push_front (di);
-
-      move (di, at_end);
-    }
-}
-
-void
-load_path::move (const dir_info& di, bool at_end, const std::string& pname)
-{
-  package_info& pkg = get_package (pname);
-
-  pkg.move (di, at_end);
-
-  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
-
-  for (const auto& pkg_di : package_dir_map)
-    {
-      std::string full_name = pkg_di.first;
-
-      if (! pname.empty ())
-        full_name = pname + "." + full_name;
-
-      move (pkg_di.second, at_end, full_name);
-    }
-}
-
 void
 load_path::package_info::move (const dir_info& di, bool at_end)
 {
@@ -561,387 +1359,6 @@
   move_method_map (dir_name, at_end);
 }
 
-static void
-maybe_add_path_elts (std::string& path, const std::string& dir)
-{
-  std::string tpath = genpath (dir);
-
-  if (! tpath.empty ())
-    {
-      if (path.empty ())
-        path = tpath;
-      else
-        path += octave::directory_path::path_sep_str () + tpath;
-    }
-}
-
-void
-load_path::do_initialize (bool set_initial_path)
-{
-  sys_path = "";
-
-  if (set_initial_path)
-    {
-      maybe_add_path_elts (sys_path, Vlocal_ver_oct_file_dir);
-      maybe_add_path_elts (sys_path, Vlocal_api_oct_file_dir);
-      maybe_add_path_elts (sys_path, Vlocal_oct_file_dir);
-      maybe_add_path_elts (sys_path, Vlocal_ver_fcn_file_dir);
-      maybe_add_path_elts (sys_path, Vlocal_api_fcn_file_dir);
-      maybe_add_path_elts (sys_path, Vlocal_fcn_file_dir);
-      maybe_add_path_elts (sys_path, Voct_file_dir);
-      maybe_add_path_elts (sys_path, Vfcn_file_dir);
-      maybe_add_path_elts (sys_path, Voct_data_dir);
-    }
-
-  std::string tpath = load_path::command_line_path;
-
-  if (tpath.empty ())
-    tpath = octave::sys::env::getenv ("OCTAVE_PATH");
-
-  std::string xpath;
-
-  if (! tpath.empty ())
-    {
-      xpath = tpath;
-
-      if (! sys_path.empty ())
-        xpath += octave::directory_path::path_sep_str () + sys_path;
-    }
-  else
-    xpath = sys_path;
-
-  do_set (xpath, false, true);
-}
-
-void
-load_path::do_clear (void)
-{
-  dir_info_list.clear ();
-
-  top_level_package.clear ();
-
-  package_map.clear ();
-}
-
-static std::list<std::string>
-split_path (const std::string& p)
-{
-  std::list<std::string> retval;
-
-  size_t beg = 0;
-  size_t end = p.find (octave::directory_path::path_sep_char ());
-
-  size_t len = p.length ();
-
-  while (end != std::string::npos)
-    {
-      std::string elt = p.substr (beg, end-beg);
-
-      if (! elt.empty ())
-        retval.push_back (elt);
-
-      beg = end + 1;
-
-      if (beg == len)
-        break;
-
-      end = p.find (octave::directory_path::path_sep_char (), beg);
-    }
-
-  std::string elt = p.substr (beg);
-
-  if (! elt.empty ())
-    retval.push_back (elt);
-
-  return retval;
-}
-
-void
-load_path::do_set (const std::string& p, bool warn, bool is_init)
-{
-  // Use a list when we need to preserve order.
-  std::list<std::string> elts = split_path (p);
-
-  // Use a set when we need to search and order is not important.
-  std::set<std::string> elts_set (elts.begin (), elts.end ());
-
-  if (is_init)
-    init_dirs = elts_set;
-  else
-    {
-      for (const auto& init_dir : init_dirs)
-        {
-          if (elts_set.find (init_dir) == elts_set.end ())
-            {
-              warning_with_id ("Octave:remove-init-dir",
-                               "default load path altered.  Some built-in functions may not be found.  Try restoredefaultpath() to recover it.");
-              break;
-            }
-        }
-    }
-
-  // Temporarily disable add hook.
-
-  octave::unwind_protect frame;
-  frame.protect_var (add_hook);
-
-  add_hook = 0;
-
-  do_clear ();
-
-  for (const auto& elt : elts)
-    do_append (elt, warn);
-
-  // Restore add hook and execute for all newly added directories.
-  frame.run_first ();
-
-  // FIXME: Shouldn't the test for add_hook be outside the for loop?
-  //        Why not use const here?  Does add_hook change dir_info_list?
-  for (auto& di : dir_info_list)
-    {
-      if (add_hook)
-        add_hook (di.dir_name);
-    }
-
-  // Always prepend current directory.
-  do_prepend (".", warn);
-}
-
-void
-load_path::do_append (const std::string& dir, bool warn)
-{
-  if (! dir.empty ())
-    do_add (dir, true, warn);
-}
-
-void
-load_path::do_prepend (const std::string& dir, bool warn)
-{
-  if (! dir.empty ())
-    do_add (dir, false, warn);
-}
-
-// Strip trailing directory separators.
-
-static std::string
-strip_trailing_separators (const std::string& dir_arg)
-{
-  std::string dir = dir_arg;
-
-  size_t k = dir.length ();
-
-  while (k > 1 && octave::sys::file_ops::is_dir_sep (dir[k-1]))
-    k--;
-
-  if (k < dir.length ())
-    dir.resize (k);
-
-  return dir;
-}
-
-void
-load_path::do_add (const std::string& dir_arg, bool at_end, bool warn)
-{
-  size_t len = dir_arg.length ();
-
-  if (len > 1 && dir_arg.substr (len-2) == "//")
-    warning_with_id ("Octave:recursive-path-search",
-                     "trailing '//' is no longer special in search path elements");
-
-  std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
-
-  dir = strip_trailing_separators (dir);
-
-  dir_info_list_iterator i = find_dir_info (dir);
-
-  if (i != dir_info_list.end ())
-    do_move (i, at_end);
-  else
-    {
-      octave::sys::file_stat fs (dir);
-
-      if (fs)
-        {
-          if (fs.is_dir ())
-            {
-              dir_info di (dir);
-
-              if (at_end)
-                dir_info_list.push_back (di);
-              else
-                dir_info_list.push_front (di);
-
-              add (di, at_end);
-
-              if (add_hook)
-                add_hook (dir);
-            }
-          else if (warn)
-            warning ("addpath: %s: not a directory", dir_arg.c_str ());
-        }
-      else if (warn)
-        {
-          std::string msg = fs.error ();
-          warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
-        }
-    }
-
-  // FIXME: is there a better way to do this?
-
-  i = find_dir_info (".");
-
-  if (i != dir_info_list.end ())
-    do_move (i, false);
-}
-
-void
-load_path::package_info::remove_fcn_map (const std::string& dir,
-                                   const string_vector& fcn_files)
-{
-  octave_idx_type len = fcn_files.numel ();
-
-  for (octave_idx_type k = 0; k < len; k++)
-    {
-      std::string fname = fcn_files[k];
-
-      std::string ext;
-      std::string base = fname;
-
-      size_t pos = fname.rfind ('.');
-
-      if (pos != std::string::npos)
-        {
-          base = fname.substr (0, pos);
-          ext = fname.substr (pos);
-        }
-
-      file_info_list_type& file_info_list = fcn_map[base];
-
-      for (auto fi_it = file_info_list.begin ();
-           fi_it != file_info_list.end ();
-           fi_it++)
-        {
-          if (fi_it->dir_name == dir)
-            {
-              file_info_list.erase (fi_it);
-
-              if (file_info_list.empty ())
-                fcn_map.erase (fname);
-
-              break;
-            }
-        }
-    }
-}
-
-void
-load_path::package_info::remove_private_fcn_map (const std::string& dir)
-{
-  private_fcn_map_iterator p = private_fcn_map.find (dir);
-
-  if (p != private_fcn_map.end ())
-    private_fcn_map.erase (p);
-}
-
-void
-load_path::package_info::remove_method_map (const std::string& dir)
-{
-  for (auto& cls_fnmap : method_map)
-    {
-      std::string class_name = cls_fnmap.first;
-
-      fcn_map_type& fn_map = cls_fnmap.second;
-
-      std::string full_dir_name
-        = octave::sys::file_ops::concat (dir, "@" + class_name);
-
-      for (auto& nm_filst : fn_map)
-        {
-          file_info_list_type& file_info_list = nm_filst.second;
-
-          if (file_info_list.size () == 1)
-            continue;
-          else
-            {
-              for (auto fi_it = file_info_list.begin ();
-                   fi_it != file_info_list.end (); fi_it++)
-                {
-                  if (fi_it->dir_name == full_dir_name)
-                    {
-                      file_info_list.erase (fi_it);
-                      // FIXME: if there are no other elements, we
-                      // should remove this element of fn_map but calling
-                      // erase here would invalidate the iterator fi_it.
-
-                      break;
-                    }
-                }
-            }
-        }
-    }
-}
-
-bool
-load_path::do_remove (const std::string& dir_arg)
-{
-  bool retval = false;
-
-  if (! dir_arg.empty ())
-    {
-      if (dir_arg == ".")
-        {
-          warning ("rmpath: can't remove \".\" from path");
-
-          // Avoid additional warnings.
-          retval = true;
-        }
-      else
-        {
-          std::string dir = octave::sys::file_ops::tilde_expand (dir_arg);
-
-          dir = strip_trailing_separators (dir);
-
-          dir_info_list_iterator i = find_dir_info (dir);
-
-          if (i != dir_info_list.end ())
-            {
-              retval = true;
-
-              if (remove_hook)
-                remove_hook (dir);
-
-              dir_info& di = *i;
-
-              remove (di);
-
-              dir_info_list.erase (i);
-            }
-        }
-    }
-
-  return retval;
-}
-
-void
-load_path::remove (const dir_info& di, const std::string& pname)
-{
-  package_info& pkg = get_package (pname);
-
-  pkg.remove (di);
-
-  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
-
-  for (const auto& pkg_di : package_dir_map)
-    {
-      std::string full_name = pkg_di.first;
-
-      if (! pname.empty ())
-        full_name = pname + "." + full_name;
-
-      remove (pkg_di.second, full_name);
-    }
-}
-
 void
 load_path::package_info::remove (const dir_info& di)
 {
@@ -959,121 +1376,74 @@
 }
 
 void
-load_path::do_update (void) const
-{
-  // I don't see a better way to do this because we need to
-  // preserve the correct directory ordering for new files that
-  // have appeared.
-
-  top_level_package.clear ();
-
-  package_map.clear ();
-
-  for (auto& di : dir_info_list)
-    {
-      di.update ();
-
-      add (di, true, "", true);
-    }
-}
-
-bool
-load_path::check_file_type (std::string& fname, int type, int possible_types,
-                            const std::string& fcn, const char *who)
+load_path::package_info::display (std::ostream& os) const
 {
-  bool retval = false;
-
-  if (type == load_path::OCT_FILE)
-    {
-      if ((type & possible_types) == load_path::OCT_FILE)
-        {
-          fname += ".oct";
-          retval = true;
-        }
-    }
-  else if (type == load_path::M_FILE)
+  os << "*** package_info: "
+     << (m_package_name.empty () ? "<top-level>" : m_package_name)
+     << "\n\n";
+
+  for (const auto& dir : dir_list)
+    os << dir << "\n";
+  os << "\n";
+
+  for (const auto& dir_fnlst : private_fcn_map)
     {
-      if ((type & possible_types) == load_path::M_FILE)
-        {
-          fname += ".m";
-          retval = true;
-        }
+      os << "\n*** private functions in "
+         << octave::sys::file_ops::concat (dir_fnlst.first, "private")
+         << ":\n\n";
+
+      print_fcn_list (os, dir_fnlst.second);
     }
-  else if (type == load_path::MEX_FILE)
+
+#if defined (DEBUG_LOAD_PATH)
+
+  for (const auto& nm_filst : fcn_map)
     {
-      if ((type & possible_types) == load_path::MEX_FILE)
+      os << nm_filst.first << ":\n";
+
+      const file_info_list_type& file_info_list = nm_filst.second;
+
+      for (const auto& finfo : file_info_list)
         {
-          fname += ".mex";
-          retval = true;
+          os << "  " << finfo.dir_name << " (";
+
+          print_types (os, finfo.types);
+
+          os << ")\n";
         }
     }
-  else if (type == (load_path::M_FILE | load_path::OCT_FILE))
+
+  for (const auto& cls_fnmap : method_map)
     {
-      if (possible_types & load_path::OCT_FILE)
-        {
-          fname += ".oct";
-          retval = true;
-        }
-      else if (possible_types & load_path::M_FILE)
+      os << "CLASS " << cls_fnmap.first << ":\n";
+
+      const fcn_map_type& fm = cls_fnmap.second;
+
+      for (const auto& nm_fnlst : fcn_map)
         {
-          fname += ".m";
-          retval = true;
-        }
-    }
-  else if (type == (load_path::M_FILE | load_path::MEX_FILE))
-    {
-      if (possible_types & load_path::MEX_FILE)
-        {
-          fname += ".mex";
-          retval = true;
-        }
-      else if (possible_types & load_path::M_FILE)
-        {
-          fname += ".m";
-          retval = true;
+          os << "  " << nm_fnlst.first << ":\n";
+
+          const file_info_list_type& file_info_list = nm_fnlst.second;
+
+          for (const auto& finfo : file_info_list)
+            {
+              os << "  " << finfo.dir_name << " (";
+
+              print_types (os, finfo.types);
+
+              os << ")\n";
+            }
         }
     }
-  else if (type == (load_path::OCT_FILE | load_path::MEX_FILE))
-    {
-      if (possible_types & load_path::OCT_FILE)
-        {
-          fname += ".oct";
-          retval = true;
-        }
-      else if (possible_types & load_path::MEX_FILE)
-        {
-          fname += ".mex";
-          retval = true;
-        }
-    }
-  else if (type == (load_path::M_FILE | load_path::OCT_FILE
-                    | load_path::MEX_FILE))
-    {
-      if (possible_types & load_path::OCT_FILE)
-        {
-          fname += ".oct";
-          retval = true;
-        }
-      else if (possible_types & load_path::MEX_FILE)
-        {
-          fname += ".mex";
-          retval = true;
-        }
-      else if (possible_types & load_path::M_FILE)
-        {
-          fname += ".m";
-          retval = true;
-        }
-    }
-  else
-    error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type);
-
-  return retval;
+
+  os << "\n";
+
+#endif
 }
 
 std::string
 load_path::package_info::find_fcn (const std::string& fcn, std::string& dir_name,
-                             int type) const
+                                   int type) const
 {
   std::string retval;
 
@@ -1108,7 +1478,7 @@
               retval = octave::sys::file_ops::concat (fi.dir_name, fcn);
 
               if (check_file_type (retval, type, fi.types,
-                                   fcn, "load_path::do_find_fcn"))
+                                   fcn, "load_path::find_fcn"))
                 {
                   dir_name = fi.dir_name;
                   break;
@@ -1124,7 +1494,7 @@
 
 std::string
 load_path::package_info::find_private_fcn (const std::string& dir,
-                                     const std::string& fcn, int type) const
+                                           const std::string& fcn, int type) const
 {
   std::string retval;
 
@@ -1154,8 +1524,8 @@
 
 std::string
 load_path::package_info::find_method (const std::string& class_name,
-                                const std::string& meth,
-                                std::string& dir_name, int type) const
+                                      const std::string& meth,
+                                      std::string& dir_name, int type) const
 {
   std::string retval;
 
@@ -1180,7 +1550,7 @@
               retval = octave::sys::file_ops::concat (fi.dir_name, meth);
 
               bool found = check_file_type (retval, type, fi.types,
-                                            meth, "load_path::do_find_method");
+                                            meth, "load_path::find_method");
 
               if (found)
                 {
@@ -1217,36 +1587,9 @@
   return retval;
 }
 
-bool
-load_path::is_package (const std::string& name) const
-{
-  for (const auto& di : dir_info_list)
-    {
-      if (di.is_package (name))
-        return true;
-    }
-
-  return false;
-}
-
-std::list<std::string>
-load_path::do_overloads (const std::string& meth) const
-{
-  std::list<std::string> retval;
-
-  //  update ();
-
-  top_level_package.overloads (meth, retval);
-
-  for (const auto& nm_ldr : package_map)
-    nm_ldr.second.overloads (meth, retval);
-
-  return retval;
-}
-
 void
 load_path::package_info::overloads (const std::string& meth,
-                              std::list<std::string>& l) const
+                                    std::list<std::string>& l) const
 {
   for (const auto& cls_fnmap : method_map)
     {
@@ -1264,394 +1607,6 @@
     }
 }
 
-// Should we cache all files in private directories, or is it OK to just
-// look them up each time as needed?
-
-std::string
-find_private_file (const std::string& fname)
-{
-  std::string retval;
-
-  // Look in private directory corresponding to current function (if
-  // any).
-
-  octave_user_function *curr_fcn = symbol_table::get_curr_fcn ();
-
-  if (curr_fcn)
-    {
-      // Even for private functions, dir_name doesn't contain the
-      // "private" directory component so we append it here in all
-      // cases.
-
-      std::string dir_name = curr_fcn->dir_name ();
-
-      if (! dir_name.empty ())
-        {
-          std::string pfname = dir_name + octave::sys::file_ops::dir_sep_str ()
-                               + "private" + octave::sys::file_ops::dir_sep_str () + fname;
-
-          octave::sys::file_stat fs (pfname);
-
-          if (fs.exists () && fs.is_reg ())
-            retval = pfname;
-        }
-    }
-
-  return retval;
-}
-
-std::string
-load_path::do_find_file (const std::string& file) const
-{
-  std::string retval;
-
-  if (octave::sys::env::absolute_pathname (file)
-      || octave::sys::env::rooted_relative_pathname (file))
-    {
-      octave::sys::file_stat fs (file);
-
-      return fs.exists () ? file : retval;
-    }
-  else
-    {
-      std::string tfile = find_private_file (file);
-
-      if (! tfile.empty ())
-        return tfile;
-    }
-
-  if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
-      != std::string::npos)
-    {
-      // Given name has a directory separator, so append it to each
-      // element of the load path in turn.
-      for (const auto& di : dir_info_list)
-        {
-          std::string tfile = octave::sys::file_ops::concat (di.dir_name, file);
-
-          octave::sys::file_stat fs (tfile);
-
-          if (fs.exists ())
-            return tfile;
-        }
-    }
-  else
-    {
-      // Look in cache.
-      for (const auto & di : dir_info_list)
-        {
-          string_vector all_files = di.all_files;
-
-          octave_idx_type len = all_files.numel ();
-
-          for (octave_idx_type i = 0; i < len; i++)
-            {
-              if (all_files[i] == file)
-                return octave::sys::file_ops::concat (di.dir_name, file);
-            }
-        }
-    }
-
-  return retval;
-}
-
-std::string
-load_path::do_find_dir (const std::string& dir) const
-{
-  std::string retval;
-
-  if (dir.find_first_of (octave::sys::file_ops::dir_sep_chars ()) != std::string::npos
-      && (octave::sys::env::absolute_pathname (dir)
-          || octave::sys::env::rooted_relative_pathname (dir)))
-    {
-      octave::sys::file_stat fs (dir);
-
-      if (fs.exists () && fs.is_dir ())
-        return dir;
-    }
-  else
-    {
-      for (const auto& di : dir_info_list)
-        {
-          std::string dname = octave::sys::env::make_absolute (di.dir_name);
-
-          size_t dname_len = dname.length ();
-
-          if (dname.substr (dname_len - 1)
-              == octave::sys::file_ops::dir_sep_str ())
-            {
-              dname = dname.substr (0, dname_len - 1);
-              dname_len--;
-            }
-
-          size_t dir_len = dir.length ();
-
-          if (dname_len > dir_len
-              && octave::sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-              && dir == dname.substr (dname_len - dir_len))
-            {
-              octave::sys::file_stat fs (di.dir_name);
-
-              if (fs.exists () && fs.is_dir ())
-                return di.dir_name;
-            }
-        }
-    }
-
-  return retval;
-}
-
-string_vector
-load_path::do_find_matching_dirs (const std::string& dir) const
-{
-  std::list<std::string> retlist;
-
-  if (dir.find_first_of (octave::sys::file_ops::dir_sep_chars ()) != std::string::npos
-      && (octave::sys::env::absolute_pathname (dir)
-          || octave::sys::env::rooted_relative_pathname (dir)))
-    {
-      octave::sys::file_stat fs (dir);
-
-      if (fs.exists () && fs.is_dir ())
-        retlist.push_back (dir);
-    }
-  else
-    {
-      for (const auto& di : dir_info_list)
-        {
-          std::string dname = octave::sys::env::make_absolute (di.dir_name);
-
-          size_t dname_len = dname.length ();
-
-          if (dname.substr (dname_len - 1)
-              == octave::sys::file_ops::dir_sep_str ())
-            {
-              dname = dname.substr (0, dname_len - 1);
-              dname_len--;
-            }
-
-          size_t dir_len = dir.length ();
-
-          if (dname_len > dir_len
-              && octave::sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
-              && dir == dname.substr (dname_len - dir_len))
-            {
-              octave::sys::file_stat fs (di.dir_name);
-
-              if (fs.exists () && fs.is_dir ())
-                retlist.push_back (di.dir_name);
-            }
-        }
-    }
-
-  return retlist;
-}
-
-std::string
-load_path::do_find_first_of (const string_vector& flist) const
-{
-  std::string retval;
-
-  std::string dir_name;
-  std::string file_name;
-
-  octave_idx_type flen = flist.numel ();
-  octave_idx_type rel_flen = 0;
-
-  string_vector rel_flist (flen);
-
-  for (octave_idx_type i = 0; i < flen; i++)
-    {
-      std::string file = flist[i];
-
-      if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
-          != std::string::npos)
-        {
-          if (octave::sys::env::absolute_pathname (file)
-              || octave::sys::env::rooted_relative_pathname (file))
-            {
-              octave::sys::file_stat fs (file);
-
-              if (fs.exists ())
-                return file;
-            }
-          else
-            {
-              for (const auto& di : dir_info_list)
-                {
-                  std::string tfile;
-                  tfile = octave::sys::file_ops::concat (di.dir_name, file);
-
-                  octave::sys::file_stat fs (tfile);
-
-                  if (fs.exists ())
-                    return tfile;
-                }
-            }
-        }
-      else
-        rel_flist[rel_flen++] = file;
-    }
-
-  rel_flist.resize (rel_flen);
-
-  for (const auto& di : dir_info_list)
-    {
-      string_vector all_files = di.all_files;
-
-      octave_idx_type len = all_files.numel ();
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          for (octave_idx_type j = 0; j < rel_flen; j++)
-            {
-              if (all_files[i] == rel_flist[j])
-                {
-                  dir_name = di.dir_name;
-                  file_name = rel_flist[j];
-
-                  goto done;
-                }
-            }
-        }
-    }
-
-done:
-
-  if (! dir_name.empty ())
-    retval = octave::sys::file_ops::concat (dir_name, file_name);
-
-  return retval;
-}
-
-string_vector
-load_path::do_find_all_first_of (const string_vector& flist) const
-{
-  std::list<std::string> retlist;
-
-  std::string dir_name;
-  std::string file_name;
-
-  octave_idx_type flen = flist.numel ();
-  octave_idx_type rel_flen = 0;
-
-  string_vector rel_flist (flen);
-
-  for (octave_idx_type i = 0; i < flen; i++)
-    {
-      std::string file = flist[i];
-
-      if (file.find_first_of (octave::sys::file_ops::dir_sep_chars ())
-          != std::string::npos)
-        {
-          if (octave::sys::env::absolute_pathname (file)
-              || octave::sys::env::rooted_relative_pathname (file))
-            {
-              octave::sys::file_stat fs (file);
-
-              if (fs.exists ())
-                retlist.push_back (file);
-            }
-          else
-            {
-              for (const auto& di : dir_info_list)
-                {
-                  std::string tfile;
-                  tfile = octave::sys::file_ops::concat (di.dir_name, file);
-
-                  octave::sys::file_stat fs (tfile);
-
-                  if (fs.exists ())
-                    retlist.push_back (tfile);
-                }
-            }
-        }
-      else
-        rel_flist[rel_flen++] = file;
-    }
-
-  rel_flist.resize (rel_flen);
-
-  for (const auto& di : dir_info_list)
-    {
-      string_vector all_files = di.all_files;
-
-      octave_idx_type len = all_files.numel ();
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          for (octave_idx_type j = 0; j < rel_flen; j++)
-            {
-              if (all_files[i] == rel_flist[j])
-                retlist.push_back (octave::sys::file_ops::concat (di.dir_name,
-                                                                  rel_flist[j]));
-            }
-        }
-    }
-
-  return retlist;
-}
-
-string_vector
-load_path::do_dirs (void) const
-{
-  size_t len = dir_info_list.size ();
-
-  string_vector retval (len);
-
-  octave_idx_type k = 0;
-
-  for (const auto& di : dir_info_list)
-    retval[k++] = di.dir_name;
-
-  return retval;
-}
-
-std::list<std::string>
-load_path::do_dir_list (void) const
-{
-  std::list<std::string> retval;
-
-  for (const auto& di : dir_info_list)
-    retval.push_back (di.dir_name);
-
-  return retval;
-}
-
-string_vector
-load_path::do_files (const std::string& dir, bool omit_exts) const
-{
-  string_vector retval;
-
-  const_dir_info_list_iterator p = find_dir_info (dir);
-
-  if (p != dir_info_list.end ())
-    retval = p->fcn_files;
-
-  if (omit_exts)
-    {
-      octave_idx_type len = retval.numel ();
-
-      for (octave_idx_type i = 0; i < len; i++)
-        {
-          std::string fname = retval[i];
-
-          size_t pos = fname.rfind ('.');
-
-          if (pos != std::string::npos)
-            retval[i] = fname.substr (0, pos);
-        }
-    }
-
-  return retval;
-}
-
-string_vector
-load_path::do_fcn_names (void) const
-{
-  return top_level_package.fcn_names ();
-}
-
 string_vector
 load_path::package_info::fcn_names (void) const
 {
@@ -1667,177 +1622,9 @@
   return retval;
 }
 
-std::string
-load_path::do_path (void) const
-{
-  std::string xpath;
-
-  string_vector xdirs = load_path::dirs ();
-
-  octave_idx_type len = xdirs.numel ();
-
-  if (len > 0)
-    xpath = xdirs[0];
-
-  for (octave_idx_type i = 1; i < len; i++)
-    xpath += octave::directory_path::path_sep_str () + xdirs[i];
-
-  return xpath;
-}
-
 void
-print_types (std::ostream& os, int types)
-{
-  bool printed_type = false;
-
-  if (types & load_path::OCT_FILE)
-    {
-      os << "oct";
-      printed_type = true;
-    }
-
-  if (types & load_path::MEX_FILE)
-    {
-      if (printed_type)
-        os << "|";
-      os << "mex";
-      printed_type = true;
-    }
-
-  if (types & load_path::M_FILE)
-    {
-      if (printed_type)
-        os << "|";
-      os << "m";
-      printed_type = true;
-    }
-}
-
-void
-print_fcn_list (std::ostream& os,
-                const load_path::dir_info::fcn_file_map_type& lst)
-{
-  for (const auto& nm_typ : lst)
-    {
-      os << "  " << nm_typ.first << " (";
-
-      print_types (os, nm_typ.second);
-
-      os << ")\n";
-    }
-}
-
-string_vector
-get_file_list (const load_path::dir_info::fcn_file_map_type& lst)
-{
-  octave_idx_type n = lst.size ();
-
-  string_vector retval (n);
-
-  octave_idx_type count = 0;
-
-  for (const auto& nm_typ : lst)
-    {
-      std::string nm = nm_typ.first;
-
-      int types = nm_typ.second;
-
-      if (types & load_path::OCT_FILE)
-        nm += ".oct";
-      else if (types & load_path::MEX_FILE)
-        nm += ".mex";
-      else
-        nm += ".m";
-
-      retval[count++] = nm;
-    }
-
-  return retval;
-}
-
-void
-load_path::do_display (std::ostream& os) const
-{
-  for (const auto& di : dir_info_list)
-    {
-      string_vector fcn_files = di.fcn_files;
-
-      if (! fcn_files.empty ())
-        {
-          os << "\n*** function files in " << di.dir_name << ":\n\n";
-
-          fcn_files.list_in_columns (os);
-        }
-
-      const dir_info::method_file_map_type& method_file_map
-        = di.method_file_map;
-
-      if (! method_file_map.empty ())
-        {
-          for (const auto& cls_ci : method_file_map)
-            {
-              os << "\n*** methods in " << di.dir_name
-                 << "/@" << cls_ci.first << ":\n\n";
-
-              const dir_info::class_info& ci = cls_ci.second;
-
-              string_vector method_files = get_file_list (ci.method_file_map);
-
-              method_files.list_in_columns (os);
-            }
-        }
-    }
-
-  top_level_package.display (os);
-
-  for (const auto& nm_ldr : package_map)
-    nm_ldr.second.display (os);
-}
-
-// True if a path is contained in a path list separated by path_sep_char
-static bool
-in_path_list (const std::string& path_list, const std::string& path)
-{
-  size_t ps = path.size ();
-  size_t pls = path_list.size ();
-  size_t pos = path_list.find (path);
-  char psc = octave::directory_path::path_sep_char ();
-  while (pos != std::string::npos)
-    {
-      if ((pos == 0 || path_list[pos-1] == psc)
-          && (pos + ps == pls || path_list[pos + ps] == psc))
-        return true;
-      else
-        pos = path_list.find (path, pos + 1);
-    }
-
-  return false;
-}
-
-void
-load_path::add (const dir_info& di, bool at_end,
-                const std::string& pname, bool updating) const
-{
-  package_info& pkg = get_package (pname);
-
-  pkg.add (di, at_end, updating);
-
-  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
-
-  for (const auto& pkg_di : package_dir_map)
-    {
-      std::string full_name = pkg_di.first;
-
-      if (! pname.empty ())
-        full_name = pname + "." + full_name;
-
-      add (pkg_di.second, at_end, full_name);
-    }
-}
-
-void
-load_path::package_info::add_to_fcn_map (const dir_info& di, bool at_end,
-                                   bool updating)
+load_path::package_info::add_to_fcn_map (const dir_info& di,
+                                         bool at_end, bool updating)
 {
   std::string dir_name = di.dir_name;
 
@@ -2012,67 +1799,319 @@
 }
 
 void
-load_path::package_info::display (std::ostream& os) const
+load_path::package_info::move_fcn_map (const std::string& dir_name,
+                                       const string_vector& fcn_files, bool at_end)
 {
-  os << "*** package info: "
-     << (m_package_name.empty () ? "<top-level>" : m_package_name) << "\n\n";
-
-  for (const auto& dir : dir_list)
-    os << dir << "\n";
-  os << "\n";
-
-  for (const auto& dir_fnlst : private_fcn_map)
+  octave_idx_type len = fcn_files.numel ();
+
+  for (octave_idx_type k = 0; k < len; k++)
     {
-      os << "\n*** private functions in "
-         << octave::sys::file_ops::concat (dir_fnlst.first, "private") << ":\n\n";
-
-      print_fcn_list (os, dir_fnlst.second);
-    }
-
-#if defined (DEBUG_LOAD_PATH)
-
-  for (const auto& nm_filst : fcn_map)
-    {
-      os << nm_filst.first << ":\n";
-
-      const file_info_list_type& file_info_list = nm_filst.second;
-
-      for (const auto& finfo : file_info_list)
+      std::string fname = fcn_files[k];
+
+      std::string ext;
+      std::string base = fname;
+
+      size_t pos = fname.rfind ('.');
+
+      if (pos != std::string::npos)
+        {
+          base = fname.substr (0, pos);
+          ext = fname.substr (pos);
+        }
+
+      file_info_list_type& file_info_list = fcn_map[base];
+
+      if (file_info_list.size () == 1)
+        continue;
+      else
         {
-          os << "  " << finfo.dir_name << " (";
-
-          print_types (os, finfo.types);
-
-          os << ")\n";
+          for (auto fi_it = file_info_list.begin ();
+               fi_it != file_info_list.end ();
+               fi_it++)
+            {
+              if (fi_it->dir_name == dir_name)
+                {
+                  file_info fi_tmp = *fi_it;
+
+                  file_info_list.erase (fi_it);
+
+                  if (at_end)
+                    file_info_list.push_back (fi_tmp);
+                  else
+                    file_info_list.push_front (fi_tmp);
+
+                  break;
+                }
+            }
         }
     }
-
-  for (const auto& cls_fnmap : method_map)
+}
+
+void
+load_path::package_info::move_method_map (const std::string& dir_name, bool at_end)
+{
+  for (auto& cls_fnmap : method_map)
     {
-      os << "CLASS " << cls_fnmap.first << ":\n";
-
-      const fcn_map_type& fm = cls_fnmap.second;
-
-      for (const auto& nm_fnlst : fcn_map)
+      std::string class_name = cls_fnmap.first;
+
+      fcn_map_type& fn_map = cls_fnmap.second;
+
+      std::string full_dir_name
+        = octave::sys::file_ops::concat (dir_name, "@" + class_name);
+
+      for (auto& nm_filst : fn_map)
         {
-          os << "  " << nm_fnlst.first << ":\n";
-
-          const file_info_list_type& file_info_list = nm_fnlst.second;
-
-          for (const auto& finfo : file_info_list)
+          file_info_list_type& file_info_list = nm_filst.second;
+
+          if (file_info_list.size () == 1)
+            continue;
+          else
             {
-              os << "  " << finfo.dir_name << " (";
-
-              print_types (os, finfo.types);
-
-              os << ")\n";
+              for (auto fi_it = file_info_list.begin ();
+                   fi_it != file_info_list.end (); fi_it++)
+                {
+                  if (fi_it->dir_name == full_dir_name)
+                    {
+                      file_info fi_tmp = *fi_it;
+
+                      file_info_list.erase (fi_it);
+
+                      if (at_end)
+                        file_info_list.push_back (fi_tmp);
+                      else
+                        file_info_list.push_front (fi_tmp);
+
+                      break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+void
+load_path::package_info::remove_fcn_map (const std::string& dir,
+                                         const string_vector& fcn_files)
+{
+  octave_idx_type len = fcn_files.numel ();
+
+  for (octave_idx_type k = 0; k < len; k++)
+    {
+      std::string fname = fcn_files[k];
+
+      std::string ext;
+      std::string base = fname;
+
+      size_t pos = fname.rfind ('.');
+
+      if (pos != std::string::npos)
+        {
+          base = fname.substr (0, pos);
+          ext = fname.substr (pos);
+        }
+
+      file_info_list_type& file_info_list = fcn_map[base];
+
+      for (auto fi_it = file_info_list.begin ();
+           fi_it != file_info_list.end ();
+           fi_it++)
+        {
+          if (fi_it->dir_name == dir)
+            {
+              file_info_list.erase (fi_it);
+
+              if (file_info_list.empty ())
+                fcn_map.erase (fname);
+
+              break;
             }
         }
     }
-
-  os << "\n";
-
-#endif
+}
+
+void
+load_path::package_info::remove_private_fcn_map (const std::string& dir)
+{
+  private_fcn_map_iterator p = private_fcn_map.find (dir);
+
+  if (p != private_fcn_map.end ())
+    private_fcn_map.erase (p);
+}
+
+void
+load_path::package_info::remove_method_map (const std::string& dir)
+{
+  for (auto& cls_fnmap : method_map)
+    {
+      std::string class_name = cls_fnmap.first;
+
+      fcn_map_type& fn_map = cls_fnmap.second;
+
+      std::string full_dir_name
+        = octave::sys::file_ops::concat (dir, "@" + class_name);
+
+      for (auto& nm_filst : fn_map)
+        {
+          file_info_list_type& file_info_list = nm_filst.second;
+
+          if (file_info_list.size () == 1)
+            continue;
+          else
+            {
+              for (auto fi_it = file_info_list.begin ();
+                   fi_it != file_info_list.end (); fi_it++)
+                {
+                  if (fi_it->dir_name == full_dir_name)
+                    {
+                      file_info_list.erase (fi_it);
+                      // FIXME: if there are no other elements, we
+                      // should remove this element of fn_map but calling
+                      // erase here would invalidate the iterator fi_it.
+
+                      break;
+                    }
+                }
+            }
+        }
+    }
+}
+
+bool
+load_path::package_info::check_file_type (std::string& fname, int type,
+                                          int possible_types,
+                                          const std::string& fcn,
+                                          const char *who) const
+{
+  bool retval = false;
+
+  if (type == load_path::OCT_FILE)
+    {
+      if ((type & possible_types) == load_path::OCT_FILE)
+        {
+          fname += ".oct";
+          retval = true;
+        }
+    }
+  else if (type == load_path::M_FILE)
+    {
+      if ((type & possible_types) == load_path::M_FILE)
+        {
+          fname += ".m";
+          retval = true;
+        }
+    }
+  else if (type == load_path::MEX_FILE)
+    {
+      if ((type & possible_types) == load_path::MEX_FILE)
+        {
+          fname += ".mex";
+          retval = true;
+        }
+    }
+  else if (type == (load_path::M_FILE | load_path::OCT_FILE))
+    {
+      if (possible_types & load_path::OCT_FILE)
+        {
+          fname += ".oct";
+          retval = true;
+        }
+      else if (possible_types & load_path::M_FILE)
+        {
+          fname += ".m";
+          retval = true;
+        }
+    }
+  else if (type == (load_path::M_FILE | load_path::MEX_FILE))
+    {
+      if (possible_types & load_path::MEX_FILE)
+        {
+          fname += ".mex";
+          retval = true;
+        }
+      else if (possible_types & load_path::M_FILE)
+        {
+          fname += ".m";
+          retval = true;
+        }
+    }
+  else if (type == (load_path::OCT_FILE | load_path::MEX_FILE))
+    {
+      if (possible_types & load_path::OCT_FILE)
+        {
+          fname += ".oct";
+          retval = true;
+        }
+      else if (possible_types & load_path::MEX_FILE)
+        {
+          fname += ".mex";
+          retval = true;
+        }
+    }
+  else if (type == (load_path::M_FILE | load_path::OCT_FILE
+                    | load_path::MEX_FILE))
+    {
+      if (possible_types & load_path::OCT_FILE)
+        {
+          fname += ".oct";
+          retval = true;
+        }
+      else if (possible_types & load_path::MEX_FILE)
+        {
+          fname += ".mex";
+          retval = true;
+        }
+      else if (possible_types & load_path::M_FILE)
+        {
+          fname += ".m";
+          retval = true;
+        }
+    }
+  else
+    error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type);
+
+  return retval;
+}
+
+void
+load_path::package_info::print_types (std::ostream& os, int types) const
+{
+  bool printed_type = false;
+
+  if (types & load_path::OCT_FILE)
+    {
+      os << "oct";
+      printed_type = true;
+    }
+
+  if (types & load_path::MEX_FILE)
+    {
+      if (printed_type)
+        os << "|";
+      os << "mex";
+      printed_type = true;
+    }
+
+  if (types & load_path::M_FILE)
+    {
+      if (printed_type)
+        os << "|";
+      os << "m";
+      printed_type = true;
+    }
+}
+
+void
+load_path::package_info::print_fcn_list (std::ostream& os,
+                                         const load_path::dir_info::fcn_file_map_type& lst) const
+{
+  for (const auto& nm_typ : lst)
+    {
+      os << "  " << nm_typ.first << " (";
+
+      print_types (os, nm_typ.second);
+
+      os << ")\n";
+    }
 }
 
 std::string
@@ -2122,49 +2161,6 @@
   return retval;
 }
 
-std::list<std::string>
-load_path::do_get_all_package_names (bool only_top_level) const
-{
-  std::list<std::string> retval;
-
-  for (const auto& dir_ldr : package_map)
-    {
-      if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos)
-        retval.push_back (dir_ldr.first);
-    }
-
-  return retval;
-}
-
-static void
-execute_pkg_add_or_del (const std::string& dir,
-                        const std::string& script_file)
-{
-  if (! octave_interpreter_ready)
-    return;
-
-  octave::unwind_protect frame;
-
-  std::string file = octave::sys::file_ops::concat (dir, script_file);
-
-  octave::sys::file_stat fs (file);
-
-  if (fs.exists ())
-    octave::source_file (file, "base");
-}
-
-void
-load_path::execute_pkg_add (const std::string& dir)
-{
-  execute_pkg_add_or_del (dir, "PKG_ADD");
-}
-
-void
-load_path::execute_pkg_del (const std::string& dir)
-{
-  execute_pkg_add_or_del (dir, "PKG_DEL");
-}
-
 DEFUN (genpath, args, ,
        doc: /* -*- texinfo -*-
 @deftypefn  {} {} genpath (@var{dir})
@@ -2203,18 +2199,6 @@
   return retval;
 }
 
-static void
-rehash_internal (void)
-{
-  load_path::update ();
-
-  // FIXME: maybe we should rename this variable since it is being
-  // used for more than keeping track of the prompt time.
-
-  // This will force updated functions to be found.
-  Vlast_prompt_time.stamp ();
-}
-
 DEFUN (rehash, , ,
        doc: /* -*- texinfo -*-
 @deftypefn {} {} rehash ()
@@ -2226,28 +2210,38 @@
   return ovl ();
 }
 
-DEFUN (command_line_path, , ,
+DEFUN (command_line_path, args, ,
        doc: /* -*- texinfo -*-
-@deftypefn {} {} command_line_path (@dots{})
+@deftypefn {} {} command_line_path ()
 Return the command line path variable.
 
 @seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}
 @end deftypefn */)
 {
-  return ovl (load_path::get_command_line_path ());
+  if (! args.empty ())
+    print_usage ();
+
+  load_path& lp = octave::__get_load_path__ ("command_line_path");
+
+  return ovl (lp.get_command_line_path ());
 }
 
-DEFUN (restoredefaultpath, , ,
+DEFUN (restoredefaultpath, args, ,
        doc: /* -*- texinfo -*-
-@deftypefn {} {} restoredefaultpath (@dots{})
+@deftypefn {} {} restoredefaultpath ()
 Restore Octave's path to its initial state at startup.
 
 @seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}
 @end deftypefn */)
 {
-  load_path::initialize (true);
-
-  return ovl (load_path::system_path ());
+  if (! args.empty ())
+    print_usage ();
+
+  load_path& lp = octave::__get_load_path__ ("restoredefaultpath");
+
+  lp.initialize (true);
+
+  return ovl (lp.system_path ());
 }
 
 // Return Octave's original default list of directories in which to
@@ -2261,7 +2255,11 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  return ovl (load_path::system_path ());
+  load_path& lp = octave::__get_load_path__ ("__pathorig__");
+
+  lp.initialize (true);
+
+  return ovl (lp.system_path ());
 }
 
 DEFUN (path, args, nargout,
@@ -2289,6 +2287,8 @@
 
   string_vector argv = args.make_argv ("path");
 
+  load_path& lp = octave::__get_load_path__ ("path");
+
   if (nargin > 0)
     {
       std::string path = argv[1];
@@ -2296,19 +2296,19 @@
       for (int i = 2; i <= nargin; i++)
         path += octave::directory_path::path_sep_str () + argv[i];
 
-      load_path::set (path, true);
+      lp.set (path, true);
 
       rehash_internal ();
     }
 
   if (nargout > 0)
-    return ovl (load_path::path ());
+    return ovl (lp.path ());
   else if (nargin == 0 && nargout == 0)
     {
       octave_stdout <<
         "\nOctave's search path contains the following directories:\n\n";
 
-      string_vector dirs = load_path::dirs ();
+      string_vector dirs = lp.dirs ();
 
       dirs.list_in_columns (octave_stdout);
 
@@ -2351,10 +2351,12 @@
   if (nargin == 0)
     print_usage ();
 
+  load_path& lp = octave::__get_load_path__ ("addpath");
+
   octave_value retval;
 
   if (nargout > 0)
-    retval = load_path::path ();
+    retval = lp.path ();
 
   bool append = false;
 
@@ -2414,9 +2416,9 @@
                      dir.end ());
 
           if (append)
-            load_path::append (dir, true);
+            lp.append (dir, true);
           else
-            load_path::prepend (dir, true);
+            lp.prepend (dir, true);
 
           need_to_update = true;
         }
@@ -2457,8 +2459,10 @@
 
   octave_value retval;
 
+  load_path& lp = octave::__get_load_path__ ("rmpath");
+
   if (nargout > 0)
-    retval = load_path::path ();
+    retval = lp.path ();
 
   bool need_to_update = false;
 
@@ -2472,7 +2476,7 @@
           //dir = regexprep (dir_elts{j}, '//+', "/");
           //dir = regexprep (dir, '/$', "");
 
-          if (! load_path::remove (dir))
+          if (! lp.remove (dir))
             warning ("rmpath: %s: not found", dir.c_str ());
           else
             need_to_update = true;
@@ -2491,7 +2495,9 @@
 Undocumented internal function.
 @end deftypefn */)
 {
-  load_path::display (octave_stdout);
+  load_path& lp = octave::__get_load_path__ ("__dump_load_path__");
+
+  lp.display (octave_stdout);
 
   return ovl ();
 }
--- a/libinterp/corefcn/load-path.h	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/load-path.h	Thu Apr 20 00:20:59 2017 -0400
@@ -32,6 +32,7 @@
 #include <set>
 #include <string>
 
+#include "oct-time.h"
 #include "pathsearch.h"
 #include "str-vec.h"
 
@@ -39,254 +40,152 @@
 OCTINTERP_API
 load_path
 {
-protected:
+public:
 
   load_path (void)
-    : package_map (), top_level_package (), dir_info_list (), init_dirs () { }
-
-public:
+    : package_map (), top_level_package (), dir_info_list (), init_dirs (),
+      m_command_line_path (), add_hook (load_path::execute_pkg_add),
+      remove_hook (load_path::execute_pkg_del)
+    { }
 
   typedef void (*hook_fcn_ptr) (const std::string& dir);
 
+  load_path (const load_path&) = delete;
+
+  load_path& operator = (const load_path&) = delete;
+
   ~load_path (void) = default;
 
-  static void initialize (bool set_initial_path = false)
-  {
-    if (instance_ok ())
-      instance->do_initialize (set_initial_path);
-  }
+  void initialize (bool set_initial_path = false);
+
+  void clear (void);
+
+  void set (const std::string& p, bool warn = false, bool is_init = false);
+
+  void append (const std::string& dir, bool warn = false);
+
+  void prepend (const std::string& dir, bool warn = false);
 
-  static void clear (void)
-  {
-    if (instance_ok ())
-      instance->do_clear ();
-  }
+  bool remove (const std::string& dir);
+
+  void update (void) const;
 
-  static void set (const std::string& p, bool warn = false)
+  bool contains_canonical (const std::string& dir_name) const;
+
+  std::string find_method (const std::string& class_name,
+                           const std::string& meth,
+                           std::string& dir_name,
+                           const std::string& pack_name = "")
   {
-    if (instance_ok ())
-      instance->do_set (p, warn);
-  }
-
-  static void append (const std::string& dir, bool warn = false)
-  {
-    if (instance_ok ())
-      instance->do_append (dir, warn);
-  }
-
-  static void prepend (const std::string& dir, bool warn = false)
-  {
-    if (instance_ok ())
-      instance->do_prepend (dir, warn);
+    return get_package (pack_name).find_method (class_name, meth, dir_name);
   }
 
-  static bool remove (const std::string& dir)
-  {
-    return instance_ok () ? instance->do_remove (dir) : false;
-  }
-
-  static void update (void)
-  {
-    if (instance_ok ())
-      instance->do_update ();
-  }
-
-  static bool contains_canonical (const std::string& dir_name)
-  {
-    return instance_ok () ? instance->do_contains_canonical (dir_name) : false;
-  }
-
-  static std::string find_method (const std::string& class_name,
-                                  const std::string& meth,
-                                  std::string& dir_name,
-                                  const std::string& pack_name = "")
-  {
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_method (class_name, meth,
-                                                      dir_name)
-      : "";
-  }
-
-  static std::string find_method (const std::string& class_name,
-                                  const std::string& meth,
-                                  const std::string& pack_name = "")
+  std::string find_method (const std::string& class_name,
+                           const std::string& meth,
+                           const std::string& pack_name = "")
   {
     std::string dir_name;
     return find_method (class_name, meth, dir_name, pack_name);
   }
 
-  static std::list<std::string> methods (const std::string& class_name,
-                                         const std::string& pack_name = "")
+  std::list<std::string> methods (const std::string& class_name,
+                                  const std::string& pack_name = "")
   {
-    return instance_ok ()
-      ? instance->get_package (pack_name).methods (class_name)
-      : std::list<std::string> ();
-  }
-
-  static std::list<std::string> overloads (const std::string& meth)
-  {
-    return instance_ok ()
-           ? instance->do_overloads (meth) : std::list<std::string> ();
+    return get_package (pack_name).methods (class_name);
   }
 
-  static bool find_package (const std::string& package_name)
+  std::list<std::string> overloads (const std::string& meth) const;
+
+  bool find_package (const std::string& package_name) const
   {
-    return instance_ok ()
-      ? instance->do_find_package (package_name) : false;
+    return (package_map.find (package_name) != package_map.end ());
   }
 
-  static std::list<std::string>
-  get_all_package_names (bool only_top_level = true)
+  std::list<std::string> get_all_package_names (bool only_top_level = true) const;
+
+  std::string find_fcn (const std::string& fcn, std::string& dir_name,
+                        const std::string& pack_name = "")
   {
-    return instance_ok ()
-      ? instance->do_get_all_package_names (only_top_level)
-      : std::list<std::string> ();
+    return get_package (pack_name).find_fcn (fcn, dir_name);
   }
 
-  static std::string find_fcn (const std::string& fcn, std::string& dir_name,
-                               const std::string& pack_name = "")
-  {
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_fcn (fcn, dir_name)
-      : "";
-  }
-
-  static std::string find_fcn (const std::string& fcn,
-                               const std::string& pack_name = "")
+  std::string find_fcn (const std::string& fcn,
+                        const std::string& pack_name = "")
   {
     std::string dir_name;
     return find_fcn (fcn, dir_name, pack_name);
   }
 
-  static std::string find_private_fcn (const std::string& dir,
-                                       const std::string& fcn,
-                                       const std::string& pack_name = "")
+  std::string find_private_fcn (const std::string& dir,
+                                const std::string& fcn,
+                                const std::string& pack_name = "")
   {
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_private_fcn (dir, fcn)
-      : "";
+    return get_package (pack_name).find_private_fcn (dir, fcn);
   }
 
-  static std::string find_fcn_file (const std::string& fcn,
-                                    const std::string& pack_name = "")
-  {
-    std::string dir_name;
-
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_fcn (fcn, dir_name, M_FILE)
-      : "";
-  }
-
-  static std::string find_oct_file (const std::string& fcn,
-                                    const std::string& pack_name = "")
+  std::string find_fcn_file (const std::string& fcn,
+                             const std::string& pack_name = "")
   {
     std::string dir_name;
-
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_fcn (fcn, dir_name, M_FILE)
-      : "";
+    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);
   }
 
-  static std::string find_mex_file (const std::string& fcn,
-                                    const std::string& pack_name = "")
+  std::string find_oct_file (const std::string& fcn,
+                             const std::string& pack_name = "")
   {
     std::string dir_name;
-
-    return instance_ok ()
-      ? instance->get_package (pack_name).find_fcn (fcn, dir_name, M_FILE)
-      : "";
+    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);
   }
 
-  static std::string find_file (const std::string& file)
+  std::string find_mex_file (const std::string& fcn,
+                             const std::string& pack_name = "")
   {
-    return instance_ok ()
-           ? instance->do_find_file (file) : "";
-  }
-
-  static std::string find_dir (const std::string& dir)
-  {
-    return instance_ok ()
-           ? instance->do_find_dir (dir) : "";
+    std::string dir_name;
+    return get_package (pack_name).find_fcn (fcn, dir_name, M_FILE);
   }
 
-  static string_vector find_matching_dirs (const std::string& dir)
-  {
-    return instance_ok ()
-           ? instance->do_find_matching_dirs (dir) : string_vector ();
-  }
+  std::string find_file (const std::string& file) const;
+
+  std::string find_dir (const std::string& dir) const;
+
+  string_vector find_matching_dirs (const std::string& dir) const;
 
-  static std::string find_first_of (const string_vector& files)
-  {
-    return instance_ok () ?
-           instance->do_find_first_of (files) : "";
-  }
+  std::string find_first_of (const string_vector& files) const;
+
+  string_vector find_all_first_of (const string_vector& files) const;
 
-  static string_vector find_all_first_of (const string_vector& files)
-  {
-    return instance_ok () ?
-           instance->do_find_all_first_of (files) : string_vector ();
-  }
+  string_vector dirs (void) const;
 
-  static string_vector dirs (void)
-  {
-    return instance_ok () ? instance->do_dirs () : string_vector ();
-  }
+  std::list<std::string> dir_list (void) const;
 
-  static std::list<std::string> dir_list (void)
-  {
-    return instance_ok ()
-           ? instance->do_dir_list () : std::list<std::string> ();
-  }
+  string_vector files (const std::string& dir, bool omit_exts = false) const;
 
-  static string_vector files (const std::string& dir, bool omit_exts = false)
-  {
-    return instance_ok ()
-           ? instance->do_files (dir, omit_exts) : string_vector ();
-  }
+  string_vector fcn_names (void) const;
 
-  static string_vector fcn_names (void)
-  {
-    return instance_ok () ? instance->do_fcn_names () : string_vector ();
-  }
+  std::string path (void) const;
 
-  static std::string path (void)
-  {
-    return instance_ok () ? instance->do_path () : "";
-  }
+  void display (std::ostream& os) const;
 
-  static void display (std::ostream& os)
-  {
-    if (instance_ok ())
-      instance->do_display (os);
-  }
+  hook_fcn_ptr get_add_hook (void) { return add_hook; }
+  hook_fcn_ptr get_remove_hook (void) { return remove_hook; }
 
-  static hook_fcn_ptr get_add_hook (void) { return add_hook; }
-  static hook_fcn_ptr get_remove_hook (void) { return remove_hook; }
-
-  static void set_add_hook (hook_fcn_ptr f) { add_hook = f; }
-  static void set_remove_hook (hook_fcn_ptr f) { remove_hook = f; }
+  void set_add_hook (hook_fcn_ptr f) { add_hook = f; }
+  void set_remove_hook (hook_fcn_ptr f) { remove_hook = f; }
 
   static void execute_pkg_add (const std::string& dir);
   static void execute_pkg_del (const std::string& dir);
 
-  static void set_command_line_path (const std::string& p)
+  void set_command_line_path (const std::string& p)
   {
-    if (command_line_path.empty ())
-      command_line_path = p;
+    if (m_command_line_path.empty ())
+      m_command_line_path = p;
     else
-      command_line_path += octave::directory_path::path_sep_str () + p;
+      m_command_line_path += octave::directory_path::path_sep_str () + p;
   }
 
-  static std::string get_command_line_path (void)
-  {
-    return instance_ok () ? instance->do_get_command_line_path ()
-                          : "";
-  }
+  std::string get_command_line_path (void) const { return m_command_line_path; }
 
-  static std::string system_path (void)
-  {
-    return instance_ok () ? instance->do_system_path () : "";
-  }
+  std::string system_path (void) const { return sys_path; }
 
 private:
 
@@ -343,52 +242,21 @@
     // This default constructor is only provided so we can create a
     // std::map of dir_info objects.  You should not use this
     // constructor for any other purpose.
-    dir_info (void)
-      : dir_name (), abs_dir_name (), is_relative (false),
-        dir_mtime (), dir_time_last_checked (),
-        all_files (), fcn_files (), private_file_map (), method_file_map (),
-        package_dir_map ()
-    { }
+    dir_info (void) = default;
 
     dir_info (const std::string& d)
       : dir_name (d), abs_dir_name (), is_relative (false),
-        dir_mtime (), dir_time_last_checked (),
-        all_files (), fcn_files (), private_file_map (), method_file_map (),
-        package_dir_map ()
+        dir_mtime (), dir_time_last_checked (), all_files (), fcn_files (),
+        private_file_map (), method_file_map (), package_dir_map ()
     {
       initialize ();
     }
 
-    dir_info (const dir_info& di)
-      : dir_name (di.dir_name), abs_dir_name (di.abs_dir_name),
-        is_relative (di.is_relative),
-        dir_mtime (di.dir_mtime),
-        dir_time_last_checked (di.dir_time_last_checked),
-        all_files (di.all_files), fcn_files (di.fcn_files),
-        private_file_map (di.private_file_map),
-        method_file_map (di.method_file_map),
-        package_dir_map (di.package_dir_map) { }
+    dir_info (const dir_info& di) = default;
 
     ~dir_info (void) = default;
 
-    dir_info& operator = (const dir_info& di)
-    {
-      if (&di != this)
-        {
-          dir_name = di.dir_name;
-          abs_dir_name = di.abs_dir_name;
-          is_relative = di.is_relative;
-          dir_mtime = di.dir_mtime;
-          dir_time_last_checked = di.dir_time_last_checked;
-          all_files = di.all_files;
-          fcn_files = di.fcn_files;
-          private_file_map = di.private_file_map;
-          method_file_map = di.method_file_map;
-          package_dir_map = di.package_dir_map;
-        }
-
-      return *this;
-    }
+    dir_info& operator = (const dir_info& di) = default;
 
     void update (void);
 
@@ -498,6 +366,7 @@
   class package_info
   {
   public:
+
     package_info (const std::string& package_name = "")
       : m_package_name (package_name), dir_list (), fcn_map (), private_fcn_map (),
         method_map () { }
@@ -573,6 +442,7 @@
     string_vector fcn_names (void) const;
 
   private:
+
     void add_to_fcn_map (const dir_info& di, bool at_end, bool updating);
 
     void add_to_private_fcn_map (const dir_info& di);
@@ -591,7 +461,13 @@
 
     void remove_method_map (const std::string& dir);
 
-  private:
+    bool check_file_type (std::string& fname, int type, int possible_types,
+                          const std::string& fcn, const char *who) const;
+
+    void print_types (std::ostream& os, int types) const;
+
+    void print_fcn_list (std::ostream& os,
+                         const dir_info::fcn_file_map_type& lst) const;
 
     std::string m_package_name;
 
@@ -604,7 +480,7 @@
     method_map_type method_map;
   };
 
-  // <PACKAGE_NAME, LOADER>
+  // <PACKAGE_NAME, PACKAGE_INFO>
   typedef std::map<std::string, package_info> package_map_type;
 
   typedef package_map_type::const_iterator const_package_map_iterator;
@@ -618,56 +494,31 @@
 
   mutable std::set<std::string> init_dirs;
 
-  static load_path *instance;
-
-  static void cleanup_instance (void) { delete instance; instance = 0; }
-
-  static hook_fcn_ptr add_hook;
-
-  static hook_fcn_ptr remove_hook;
-
-  static std::string command_line_path;
+  std::string m_command_line_path;
 
   static std::string sys_path;
 
   static abs_dir_cache_type abs_dir_cache;
 
-  static bool instance_ok (void);
+  hook_fcn_ptr add_hook;
+
+  hook_fcn_ptr remove_hook;
 
   const_dir_info_list_iterator find_dir_info (const std::string& dir) const;
   dir_info_list_iterator find_dir_info (const std::string& dir);
 
   bool contains (const std::string& dir) const;
 
-  bool do_contains_canonical (const std::string& dir) const;
-
-  void do_move (dir_info_list_iterator i, bool at_end);
-
-  void move (const dir_info& di, bool at_end,
-             const std::string& pname = "");
+  void move (dir_info_list_iterator i, bool at_end);
 
-  void remove (const dir_info& di,
-               const std::string& pname = "");
-
-  void do_initialize (bool set_initial_path);
-
-  void do_clear (void);
+  void move (const dir_info& di, bool at_end, const std::string& pname = "");
 
-  void do_set (const std::string& p, bool warn, bool is_init = false);
-
-  void do_append (const std::string& dir, bool warn);
-
-  void do_prepend (const std::string& dir, bool warn);
-
-  void do_add (const std::string& dir, bool at_end, bool warn);
+  void remove (const dir_info& di, const std::string& pname = "");
 
-  bool do_remove (const std::string& dir);
-
-  void do_update (void) const;
+  void add (const std::string& dir, bool at_end, bool warn);
 
-  static bool
-  check_file_type (std::string& fname, int type, int possible_types,
-                   const std::string& fcn, const char *who);
+  void add (const dir_info& di, bool at_end, const std::string& pname = "",
+            bool updating = false) const;
 
   bool is_package (const std::string& name) const;
 
@@ -675,64 +526,19 @@
   {
     if (! name.empty () && is_package (name))
       {
-        package_map_iterator pi = package_map.find (name);
+        package_map_iterator l = package_map.find (name);
 
-        if (pi == package_map.end ())
-          pi = package_map.insert (package_map.end (),
-                                   package_map_type::value_type (name, package_info (name)));
+        if (l == package_map.end ())
+          l = package_map.insert (package_map.end (),
+                                  package_map_type::value_type (name, package_info (name)));
 
-        return pi->second;
+        return l->second;
       }
 
     return top_level_package;
   }
 
-  std::list<std::string> do_overloads (const std::string& meth) const;
-
-  bool do_find_package (const std::string& package_name) const
-  {
-    return (package_map.find (package_name) != package_map.end ());
-  }
-
-  std::list<std::string> do_get_all_package_names (bool only_top_level) const;
-
-  std::string do_find_file (const std::string& file) const;
-
-  std::string do_find_dir (const std::string& dir) const;
-
-  string_vector do_find_matching_dirs (const std::string& dir) const;
-
-  std::string do_find_first_of (const string_vector& files) const;
-
-  string_vector do_find_all_first_of (const string_vector& files) const;
-
-  string_vector do_dirs (void) const;
-
-  std::list<std::string> do_dir_list (void) const;
-
-  string_vector do_files (const std::string& dir, bool omit_exts) const;
-
-  string_vector do_fcn_names (void) const;
-
-  std::string do_path (void) const;
-
-  friend void print_types (std::ostream& os, int types);
-
-  friend string_vector get_file_list (const dir_info::fcn_file_map_type& lst);
-
-  friend void
-  print_fcn_list (std::ostream& os, const dir_info::fcn_file_map_type& lst);
-
-  void do_display (std::ostream& os) const;
-
-  std::string do_system_path (void) const { return sys_path; }
-
-  std::string do_get_command_line_path (void) const
-  { return command_line_path; }
-
-  void add (const dir_info& di, bool at_end,
-            const std::string& pname = "",
-            bool updating = false) const;
+  string_vector get_file_list (const dir_info::fcn_file_map_type& lst) const;
 
   friend dir_info::fcn_file_map_type get_fcn_files (const std::string& d);
 };
--- a/libinterp/corefcn/ls-mat5.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/ls-mat5.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -65,6 +65,7 @@
 #include "pager.h"
 #include "pt-exp.h"
 #include "sysdep.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "unwind-prot.h"
 #include "utils.h"
@@ -905,7 +906,9 @@
                         names.push_back (fname + ".mex");
                         names.push_back (fname + ".m");
 
-                        octave::directory_path p (load_path::system_path ());
+                        load_path& lp = octave::__get_load_path__ ("read_mat5_binary_element");
+
+                        octave::directory_path p (lp.system_path ());
 
                         str =
                           octave::sys::env::make_absolute (p.find_first_of (names));
@@ -1204,8 +1207,10 @@
                       warning ("load: unable to reconstruct object inheritance");
 
                     tc = cls;
-                    if (load_path::find_method (classname, "loadobj")
-                        != "")
+
+                    load_path& lp = octave::__get_load_path__ ("read_mat5_binary_element");
+
+                    if (lp.find_method (classname, "loadobj") != "")
                       {
                         try
                           {
@@ -2600,9 +2605,10 @@
 
       octave_map m;
 
+      load_path& lp = octave::__get_load_path__ ("read_mat5_binary_element");
+
       if (tc.is_object ()
-          && load_path::find_method (tc.class_name (),
-                                     "saveobj") != "")
+          && lp.find_method (tc.class_name (), "saveobj") != "")
         {
           try
             {
--- a/libinterp/corefcn/module.mk	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/module.mk	Thu Apr 20 00:20:59 2017 -0400
@@ -93,6 +93,7 @@
   libinterp/corefcn/zfstream.h
 
 NOINSTALL_COREFCN_INC = \
+  libinterp/corefcn/interpreter-private.h \
   libinterp/corefcn/oct-hdf5.h \
   libinterp/corefcn/oct-opengl.h
 
@@ -166,6 +167,7 @@
   libinterp/corefcn/hook-fcn.cc \
   libinterp/corefcn/input.cc \
   libinterp/corefcn/inv.cc \
+  libinterp/corefcn/interpreter-private.cc \
   libinterp/corefcn/interpreter.cc \
   libinterp/corefcn/kron.cc \
   libinterp/corefcn/load-path.cc \
--- a/libinterp/corefcn/symtab.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/symtab.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -37,6 +37,7 @@
 #include "defun.h"
 #include "dirfns.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "load-path.h"
 #include "ov-classdef.h"
 #include "ov-fcn.h"
@@ -264,8 +265,10 @@
 
                           if (! dispatch_type.empty ())
                             {
-                              file = load_path::find_method (dispatch_type, nm,
-                                                             dir_name, pack);
+                              load_path& lp = octave::__get_load_path__ ("out_of_date_check");
+
+                              file = lp.find_method (dispatch_type, nm,
+                                                     dir_name, pack);
 
                               if (file.empty ())
                                 {
@@ -282,9 +285,8 @@
                                       split_name_with_package (*it, s_name,
                                                                s_pack);
 
-                                      file = load_path::find_method (*it, nm,
-                                                                     dir_name,
-                                                                     s_pack);
+                                      file = lp.find_method (*it, nm, dir_name,
+                                                             s_pack);
                                       if (! file.empty ())
                                         {
                                           pack = s_pack;
@@ -301,7 +303,10 @@
                             file = octave::lookup_autoload (nm);
 
                           if (file.empty ())
-                            file = load_path::find_fcn (nm, dir_name, pack);
+                            {
+                              load_path& lp = octave::__get_load_path__ ("out_of_date_check");
+                              file = lp.find_fcn (nm, dir_name, pack);
+                            }
                         }
 
                       if (! file.empty ())
@@ -387,7 +392,9 @@
 {
   octave_value retval;
 
-  std::string file_name = load_path::find_private_fcn (dir_name, name);
+  load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::load_private_function");
+
+  std::string file_name = lp.find_private_fcn (dir_name, name);
 
   if (! file_name.empty ())
     {
@@ -425,8 +432,9 @@
 
   std::string dir_name;
 
-  std::string file_name = load_path::find_method (name, name, dir_name,
-                                                  package_name);
+  load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::load_class_constructor");
+
+  std::string file_name = lp.find_method (name, name, dir_name, package_name);
 
   if (! file_name.empty ())
     {
@@ -492,8 +500,10 @@
         {
           std::string dir_name;
 
-          std::string file_name = load_path::find_method (dispatch_type, name,
-                                                          dir_name);
+          load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::load_class_method");
+
+          std::string file_name = lp.find_method (dispatch_type, name,
+                                                  dir_name);
 
           if (! file_name.empty ())
             {
@@ -692,7 +702,9 @@
       // the last prompt or chdir, so try updating the load path and
       // searching again.
 
-      load_path::update ();
+      load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::find");
+
+      lp.update ();
 
       retval = xfind (args, local_funcs);
     }
@@ -892,7 +904,9 @@
       // the last prompt or chdir, so try updating the load path and
       // searching again.
 
-      load_path::update ();
+      load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::builtin_find");
+
+      lp.update ();
 
       retval = x_builtin_find ();
     }
@@ -1090,8 +1104,10 @@
     {
       std::string dir_name;
 
-      std::string file_name = load_path::find_fcn (name, dir_name,
-                                                   package_name);
+      load_path& lp = octave::__get_load_path__ ("symbol_table::fcn_info::fcn_info_rep::find_user_function");
+
+
+      std::string file_name = lp.find_fcn (name, dir_name, package_name);
 
       if (! file_name.empty ())
         {
--- a/libinterp/corefcn/utils.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/utils.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -54,6 +54,7 @@
 #include "error.h"
 #include "errwarn.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
@@ -311,8 +312,10 @@
   if (names.empty ())
     error ("file_in_loadpath: FILE argument must not be empty");
 
+  load_path& lp = octave::__get_load_path__ ("file_in_loadpath");
+
   if (nargin == 1)
-    return ovl (octave::sys::env::make_absolute (load_path::find_first_of (names)));
+    return ovl (octave::sys::env::make_absolute (lp.find_first_of (names)));
   else
     {
       std::string opt = args(1).xstring_value ("file_in_loadpath: optional second argument must be a string");
@@ -320,7 +323,7 @@
       if (opt != "all")
         error ("file_in_loadpath: \"all\" is only valid second argument");
 
-      return ovl (Cell (make_absolute (load_path::find_all_first_of (names))));
+      return ovl (Cell (make_absolute (lp.find_all_first_of (names))));
     }
 }
 
@@ -425,7 +428,9 @@
   if (! suffix.empty ())
     nm.append (suffix);
 
-  return octave::sys::env::make_absolute (load_path::find_file (nm));
+  load_path& lp = octave::__get_load_path__ ("file_in_path");
+
+  return octave::sys::env::make_absolute (lp.find_file (nm));
 }
 
 std::string
@@ -448,9 +453,11 @@
 
       if (! local_file_ok)
         {
+          load_path& lp = octave::__get_load_path__ ("find_data_file_in_load_path");
+
           // Not directly found; search load path.
           std::string tmp
-            = octave::sys::env::make_absolute (load_path::find_file (fname));
+            = octave::sys::env::make_absolute (lp.find_file (fname));
 
           if (! tmp.empty ())
             {
@@ -484,7 +491,11 @@
             retval = name;
         }
       else if (len > 2 && name[len - 2] == '.' && name[len - 1] == 'm')
-        retval = load_path::find_fcn_file (name.substr (0, len-2));
+        {
+          load_path& lp = octave::__get_load_path__ ("fcn_file_in_path");
+
+          retval = lp.find_fcn_file (name.substr (0, len-2));
+        }
       else
         {
           std::string fname = name;
@@ -492,7 +503,9 @@
           if (pos != std::string::npos)
             fname = name.substr (0, pos);
 
-          retval = load_path::find_fcn_file (fname);
+          load_path& lp = octave::__get_load_path__ ("fcn_file_in_path");
+
+          retval = lp.find_fcn_file (fname);
         }
     }
 
@@ -509,8 +522,11 @@
 
   if (dir.length () > 0)
     {
-      std::string tcontents = octave::sys::file_ops::concat (load_path::find_dir (dir),
-                                                std::string ("Contents.m"));
+      load_path& lp = octave::__get_load_path__ ("contents_in_file_path");
+
+      std::string tcontents
+        = octave::sys::file_ops::concat (lp.find_dir (dir),
+                                         std::string ("Contents.m"));
 
       octave::sys::file_stat fs (tcontents);
 
@@ -542,9 +558,17 @@
             retval = name;
         }
       else if (len > 4 && name.find (".oct", len-5))
-        retval = load_path::find_oct_file (name.substr (0, len-4));
+        {
+          load_path& lp = octave::__get_load_path__ ("oct_file_in_path");
+
+          retval = lp.find_oct_file (name.substr (0, len-4));
+        }
       else
-        retval = load_path::find_oct_file (name);
+        {
+          load_path& lp = octave::__get_load_path__ ("oct_file_in_path");
+
+          retval = lp.find_oct_file (name);
+        }
     }
 
   return retval;
@@ -571,9 +595,17 @@
             retval = name;
         }
       else if (len > 4 && name.find (".mex", len-5))
-        retval = load_path::find_mex_file (name.substr (0, len-4));
+        {
+          load_path& lp = octave::__get_load_path__ ("mex_file_in_path");
+
+          retval = lp.find_mex_file (name.substr (0, len-4));
+        }
       else
-        retval = load_path::find_mex_file (name);
+        {
+          load_path& lp = octave::__get_load_path__ ("mex_file_in_path");
+
+          retval = lp.find_mex_file (name);
+        }
     }
 
   return retval;
@@ -976,10 +1008,12 @@
 
   dir = args(0).xstring_value ("dir_in_loadpath: DIR must be a directory name");
 
+  load_path& lp = octave::__get_load_path__ ("dir_in_loadpath");
+
   if (nargin == 1)
-    return ovl (load_path::find_dir (dir));
+    return ovl (lp.find_dir (dir));
   else
-    return ovl (Cell (load_path::find_matching_dirs (dir)));
+    return ovl (Cell (lp.find_matching_dirs (dir)));
 }
 
 /*
--- a/libinterp/corefcn/variables.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/corefcn/variables.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -48,6 +48,7 @@
 #include "errwarn.h"
 #include "help.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
@@ -426,7 +427,11 @@
       std::string file_name = octave::lookup_autoload (name);
 
       if (file_name.empty ())
-        file_name = load_path::find_fcn (name);
+        {
+          load_path& lp = octave::__get_load_path__ ("symbol_exist");
+
+          file_name = lp.find_fcn (name);
+        }
 
       size_t len = file_name.length ();
 
--- a/libinterp/octave-value/ov-class.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/octave-value/ov-class.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -38,6 +38,7 @@
 #include "error.h"
 #include "file-ops.h"
 #include "errwarn.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "ls-hdf5.h"
@@ -1141,7 +1142,10 @@
 {
   os << "# classname: " << class_name () << "\n";
   octave_map m;
-  if (load_path::find_method (class_name (), "saveobj") != "")
+
+  load_path& lp = octave::__get_load_path__ ("octave_class::save_ascii");
+
+  if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
       octave_value_list tmp = octave::feval ("saveobj", in, 1);
@@ -1213,8 +1217,9 @@
       if (! reconstruct_parents ())
         warning ("load: unable to reconstruct object inheritance");
 
-      if (load_path::find_method (classname, "loadobj")
-          != "")
+      load_path& lp = octave::__get_load_path__ ("octave_class::load_ascii");
+
+      if (lp.find_method (classname, "loadobj") != "")
         {
           octave_value in = new octave_class (*this);
           octave_value_list tmp = octave::feval ("loadobj", in, 1);
@@ -1242,7 +1247,10 @@
   os << class_name ();
 
   octave_map m;
-  if (load_path::find_method (class_name (), "saveobj") != "")
+
+  load_path& lp = octave::__get_load_path__ ("octave_class::save_binary");
+
+  if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
       octave_value_list tmp = octave::feval ("saveobj", in, 1);
@@ -1329,7 +1337,9 @@
           if (! reconstruct_parents ())
             warning ("load: unable to reconstruct object inheritance");
 
-          if (load_path::find_method (c_name, "loadobj") != "")
+          load_path& lp = octave::__get_load_path__ ("octave_class::load_binary");
+
+          if (lp.find_method (c_name, "loadobj") != "")
             {
               octave_value in = new octave_class (*this);
               octave_value_list tmp = octave::feval ("loadobj", in, 1);
@@ -1366,6 +1376,8 @@
   octave_map m;
   octave_map::iterator i;
 
+  load_path& lp = octave::__get_load_path__ ("octave_class::save_hdf5");
+
 #if defined (HAVE_HDF5_18)
   group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
                          octave_H5P_DEFAULT);
@@ -1406,7 +1418,7 @@
   if (data_hid < 0)
     goto error_cleanup;
 
-  if (load_path::find_method (class_name (), "saveobj") != "")
+  if (lp.find_method (class_name (), "saveobj") != "")
     {
       octave_value in = new octave_class (*this);
       octave_value_list tmp = octave::feval ("saveobj", in, 1);
@@ -1574,7 +1586,9 @@
       if (! reconstruct_parents ())
         warning ("load: unable to reconstruct object inheritance");
 
-      if (load_path::find_method (c_name, "loadobj") != "")
+      load_path& lp = octave::__get_load_path__ ("octave_class::load_hdf5");
+
+      if (lp.find_method (c_name, "loadobj") != "")
         {
           octave_value in = new octave_class (*this);
           octave_value_list tmp = octave::feval ("loadobj", in, 1);
@@ -1912,7 +1926,9 @@
 
   std::string method = args(1).string_value ();
 
-  if (load_path::find_method (class_name, method) != "")
+  load_path& lp = octave::__get_load_path__ ("ismethod");
+
+  if (lp.find_method (class_name, method) != "")
     return ovl (true);
   else
     return ovl (false);
@@ -1938,7 +1954,9 @@
   else if (arg.is_string ())
     class_name = arg.string_value ();
 
-  string_vector sv = load_path::methods (class_name);
+  load_path& lp = octave::__get_load_path__ ("__methods__");
+
+  string_vector sv = lp.methods (class_name);
 
   return ovl (Cell (sv));
 }
--- a/libinterp/octave-value/ov-classdef.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/octave-value/ov-classdef.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -28,6 +28,7 @@
 
 #include "call-stack.h"
 #include "defun.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "ov-builtin.h"
@@ -2632,6 +2633,8 @@
 
       std::list<octave::tree_classdef_methods_block *> mb_list = b->methods_list ();
 
+      load_path& lp = octave::__get_load_path__ ("cdef_class::make_meta_class");
+
       for (auto& mb_p : mb_list)
         {
           std::map<std::string, octave_value> amap;
@@ -2702,8 +2705,8 @@
           // in the @-folder containing the original classdef file.  However,
           // this is easier to implement it that way at the moment.
 
-          std::list<std::string> external_methods =
-            load_path::methods (full_class_name);
+          std::list<std::string> external_methods
+            = lp.methods (full_class_name);
 
           for (const auto& mtdnm : external_methods)
             {
@@ -2979,6 +2982,8 @@
     {
       if (is_dummy_method (function))
         {
+          load_path& lp = octave::__get_load_path__ ("cdef_method::cdef_method_rep::check_method");
+
           std::string name = get_name ();
           std::string cls_name = dispatch_type;
           std::string pack_name;
@@ -2992,8 +2997,8 @@
             }
 
           std::string dir_name;
-          std::string file_name = load_path::find_method (cls_name, name,
-                                                          dir_name, pack_name);
+          std::string file_name = lp.find_method (cls_name, name,
+                                                  dir_name, pack_name);
 
           if (! file_name.empty ())
             {
@@ -3190,7 +3195,9 @@
 {
   std::map<std::string, cdef_package> toplevel_packages;
 
-  std::list<std::string> names = load_path::get_all_package_names ();
+  load_path& lp = octave::__get_load_path__ ("package_getAllPackages");
+
+  std::list<std::string> names = lp.get_all_package_names ();
 
   toplevel_packages["meta"] = cdef_manager::find_package ("meta", false,
                                                           false);
@@ -3625,7 +3632,9 @@
     }
   else
     {
-      if (load_if_not_found && load_path::find_package (name))
+      load_path& lp = octave::__get_load_path__ ("cdef_manager::do_find_package");
+
+      if (load_if_not_found && lp.find_package (name))
         {
           size_t pos = name.find ('.');
 
--- a/libinterp/octave-value/ov-fcn-handle.cc	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Thu Apr 20 00:20:59 2017 -0400
@@ -41,6 +41,7 @@
 #include "errwarn.h"
 #include "file-stat.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "load-path.h"
 #include "oct-env.h"
@@ -297,7 +298,9 @@
           names.push_back (nm + ".mex");
           names.push_back (nm + ".m");
 
-          octave::directory_path p (load_path::system_path ());
+          load_path& lp = octave::__get_load_path__ ("octave_fcn_handle::set_fcn");
+
+          octave::directory_path p (lp.system_path ());
 
           str = octave::sys::env::make_absolute (p.find_first_of (names));
 
@@ -1584,14 +1587,16 @@
     }
   else
     {
+      load_path& lp = octave::__get_load_path__ ("make_fcn_handle");
+
       // Globally visible (or no match yet).  Query overloads.
-      std::list<std::string> classes = load_path::overloads (tnm);
+      std::list<std::string> classes = lp.overloads (tnm);
       bool any_match = fptr != 0 || classes.size () > 0;
       if (! any_match)
         {
           // No match found, try updating load_path and query classes again.
-          load_path::update ();
-          classes = load_path::overloads (tnm);
+          lp.update ();
+          classes = lp.overloads (tnm);
           any_match = classes.size () > 0;
         }
 
--- a/libinterp/parse-tree/oct-parse.in.yy	Tue Apr 25 14:20:34 2017 -0400
+++ b/libinterp/parse-tree/oct-parse.in.yy	Thu Apr 20 00:20:59 2017 -0400
@@ -61,6 +61,7 @@
 #include "dynamic-ld.h"
 #include "error.h"
 #include "input.h"
+#include "interpreter-private.h"
 #include "interpreter.h"
 #include "lex.h"
 #include "load-path.h"
@@ -4430,7 +4431,11 @@
     am_iter p = autoload_map.find (nm);
 
     if (p != autoload_map.end ())
-      retval = load_path::find_file (p->second);
+      {
+        load_path& lp = octave::__get_load_path__ ("lookup_autoload");
+
+        retval = lp.find_file (p->second);
+      }
 
     return retval;
   }