# HG changeset patch # User John W. Eaton # Date 1492662059 14400 # Node ID d24d01273bd031b3f805d072177a6098a42a3f2c # Parent 442fe5b5afb543f298292bdd1e119d810f103332 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. diff -r 442fe5b5afb5 -r d24d01273bd0 libgui/src/octave-qt-link.cc --- 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: diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/dirfns.cc --- 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 ()); diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/help.cc --- 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). diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/input.cc --- 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; diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/interpreter-private.cc --- /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 +. + +*/ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include + +#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 (); + } +} diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/interpreter-private.h --- /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 +. + +*/ + +#if ! defined (octave_interpreter_private_h) +#define octave_interpreter_private_h 1 + +#include "octave-config.h" + +#include + +#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 diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/interpreter.cc --- 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 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; } diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/interpreter.h --- 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; diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/load-path.cc --- 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 -. + 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 + . */ @@ -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 +split_path (const std::string& p) +{ + std::list 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 elts = split_path (p); + + // Use a set when we need to search and order is not important. + std::set 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 +load_path::overloads (const std::string& meth) const +{ + std::list 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 +load_path::get_all_package_names (bool only_top_level) const +{ + std::list 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 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 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 +load_path::dir_list (void) const +{ + std::list 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 -split_path (const std::string& p) -{ - std::list 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 elts = split_path (p); - - // Use a set when we need to search and order is not important. - std::set 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 () ? "" : 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 -load_path::do_overloads (const std::string& meth) const -{ - std::list 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& l) const + std::list& 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 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 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 -load_path::do_dir_list (void) const -{ - std::list 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 () ? "" : 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 -load_path::do_get_all_package_names (bool only_top_level) const -{ - std::list 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 (); } diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/load-path.h --- 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 #include +#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 methods (const std::string& class_name, - const std::string& pack_name = "") + std::list methods (const std::string& class_name, + const std::string& pack_name = "") { - return instance_ok () - ? instance->get_package (pack_name).methods (class_name) - : std::list (); - } - - static std::list overloads (const std::string& meth) - { - return instance_ok () - ? instance->do_overloads (meth) : std::list (); + return get_package (pack_name).methods (class_name); } - static bool find_package (const std::string& package_name) + std::list 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 - get_all_package_names (bool only_top_level = true) + std::list 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 (); + 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 dir_list (void) const; - static std::list dir_list (void) - { - return instance_ok () - ? instance->do_dir_list () : std::list (); - } + 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; }; - // + // typedef std::map package_map_type; typedef package_map_type::const_iterator const_package_map_iterator; @@ -618,56 +494,31 @@ mutable std::set 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 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 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 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); }; diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/ls-mat5.cc --- 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 { diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/module.mk --- 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 \ diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/symtab.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 ()) { diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/utils.cc --- 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))); } /* diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/corefcn/variables.cc --- 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 (); diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/octave-value/ov-class.cc --- 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)); } diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/octave-value/ov-classdef.cc --- 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 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 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 external_methods = - load_path::methods (full_class_name); + std::list 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 toplevel_packages; - std::list names = load_path::get_all_package_names (); + load_path& lp = octave::__get_load_path__ ("package_getAllPackages"); + + std::list 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 ('.'); diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/octave-value/ov-fcn-handle.cc --- 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 classes = load_path::overloads (tnm); + std::list 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; } diff -r 442fe5b5afb5 -r d24d01273bd0 libinterp/parse-tree/oct-parse.in.yy --- 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; }