28#if defined (HAVE_CONFIG_H)
40#if ! defined (OCTAVE_USE_WINDOWS_API)
63maybe_canonicalize (
const std::string& dir_arg)
65 bool is_absolute_path = sys::env::absolute_pathname (dir_arg);
67 std::string canonical_dir = sys::canonicalize_file_name (dir_arg);
69 if (canonical_dir.empty ())
75 if (! is_absolute_path)
79 std::string cwd = sys::canonicalize_file_name (
".");
80 if (dir.compare (0, cwd.length (), cwd) == 0)
81 dir.erase (0, cwd.length ()+1);
91maybe_add_path_elts (std::string& path,
const std::string& dir)
93 std::string tpath =
genpath (maybe_canonicalize (dir));
104static std::list<std::string>
105split_path (
const std::string& p)
107 std::list<std::string> retval;
112 std::size_t
len = p.length ();
114 while (end != std::string::npos)
116 std::string elt = p.substr (beg, end-beg);
119 retval.push_back (elt);
129 std::string elt = p.substr (beg);
132 retval.push_back (elt);
140strip_trailing_separators (
const std::string& dir_arg)
142 std::string dir = dir_arg;
144 std::size_t k = dir.length ();
146 while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1]))
149 if (k < dir.length ())
158in_path_list (
const std::string& path_list,
const std::string& path)
160 std::size_t ps = path.size ();
161 std::size_t pls = path_list.size ();
162 std::size_t pos = path_list.find (path);
164 while (pos != std::string::npos)
166 if ((pos == 0 || path_list[pos-1] == psc)
167 && (pos + ps == pls || path_list[pos + ps] == psc))
170 pos = path_list.find (path, pos + 1);
205subdirs_modified (
const std::string&
d,
const sys::file_time& last_checked)
207 sys::dir_entry dir (
d);
217 std::string fname = flist[i];
219 std::string full_name = sys::file_ops::concat (
d, fname);
223#if defined (OCTAVE_USE_WINDOWS_API)
224 if (sys::dir_exists (full_name)
226 sys::file_stat fs (full_name);
228 if (fs && fs.is_dir ()
230 && (fname[0] ==
'@' || fname[0] ==
'+' || fname ==
"private")
231#
if defined (OCTAVE_USE_WINDOWS_API)
232 && ((sys::file_time (full_name)
234 && ((sys::file_time (fs.mtime ().unix_time ())
236 + sys::file_time::time_resolution () > last_checked)
237 || ((fname[0] ==
'@' || fname[0] ==
'+')
238 && subdirs_modified (full_name, last_checked))))
244 std::string msg = dir.error ();
245 warning (
"load_path: %s: %s",
d.c_str (), msg.c_str ());
251std::string load_path::s_sys_path;
252load_path::abs_dir_cache_type load_path::s_abs_dir_cache;
255 : m_add_hook ([this] (const std::string& dir) { this->
execute_pkg_add (dir); }),
256m_remove_hook ([
this] (
const std::string& dir) { this->
execute_pkg_del (dir); }),
257m_interpreter (interp), m_package_map (), m_top_level_package (),
258m_dir_info_list (), m_init_dirs (), m_command_line_path ()
266 if (set_initial_path)
268 maybe_add_path_elts (s_sys_path, config::local_ver_oct_file_dir ());
269 maybe_add_path_elts (s_sys_path, config::local_api_oct_file_dir ());
270 maybe_add_path_elts (s_sys_path, config::local_oct_file_dir ());
271 maybe_add_path_elts (s_sys_path, config::local_ver_fcn_file_dir ());
272 maybe_add_path_elts (s_sys_path, config::local_api_fcn_file_dir ());
273 maybe_add_path_elts (s_sys_path, config::local_fcn_file_dir ());
274 maybe_add_path_elts (s_sys_path, config::oct_file_dir ());
275 maybe_add_path_elts (s_sys_path, config::fcn_file_dir ());
276 maybe_add_path_elts (s_sys_path, config::oct_data_dir ());
279 std::string tpath = load_path::m_command_line_path;
282 tpath = sys::env::getenv (
"OCTAVE_PATH");
286 if (! tpath.empty ())
290 if (! s_sys_path.empty ())
296 set (xpath,
false,
true);
302 m_dir_info_list.clear ();
304 m_top_level_package.clear ();
306 m_package_map.clear ();
313 std::list<std::string> elts = split_path (p);
315 for (
auto& elt : elts)
316 elt = maybe_canonicalize (elt);
319 std::set<std::string> elts_set (elts.begin (), elts.end ());
322 m_init_dirs = elts_set;
325 for (
const auto& init_dir : m_init_dirs)
327 if (elts_set.find (init_dir) == elts_set.end ())
330 "default load path altered. Some built-in functions may not be found. Try restoredefaultpath() to recover it.");
341 m_add_hook =
nullptr;
345 for (
const auto& elt : elts)
362 for (
auto& di : m_dir_info_list)
365 if (di.m_dir_name.compare (
"."))
366 m_add_hook (di.m_dir_name);
375 add (dir,
true, warn);
382 add (dir,
false, warn);
390 if (! dir_arg.empty ())
392 if (sys::same_file (dir_arg,
"."))
394 warning (R
"(rmpath: can't remove "." from path)");
401 std::string dir = sys::file_ops::tilde_expand (dir_arg);
403 dir = strip_trailing_separators (dir);
405 auto i = find_dir_info (dir);
407 if (i != m_dir_info_list.end ())
418 m_dir_info_list.erase (i);
433 m_top_level_package.clear ();
435 m_package_map.clear ();
437 for (dir_info_list_iterator di = m_dir_info_list.begin ();
438 di != m_dir_info_list.end ();)
440 bool ok = di->update ();
445 (
"Octave:load-path:update-failed",
446 "load-path: update failed for '%s', removing from path",
447 di->m_dir_name.c_str ());
450 m_remove_hook (di->m_dir_name.c_str ());
454 di = m_dir_info_list.erase (di);
458 add (*di,
true,
"",
true);
469 for (
const auto&
d : m_dir_info_list)
471 if (sys::same_file (dir,
d.m_dir_name))
483 const std::string& dir)
486 bool addpath_option =
true;
488 std::string curr_dir = sys::env::get_current_directory ();
490 if (sys::same_file (curr_dir, dir))
497 std::string base_file = (file.length () > dir.length ())
498 ? file.substr (dir.length () + 1)
499 : sys::env::base_pathname (file);
501 std::string lp_file =
find_file (base_file);
503 if (dir_in_load_path)
505 if (sys::same_file (lp_file, file))
516 if (sys::same_file (lp_file, base_file))
518 if (sys::same_file (curr_dir, dir))
521 addpath_option =
false;
536 m_interpreter.
chdir (dir);
555std::list<std::string>
558 std::list<std::string> retval;
562 m_top_level_package.overloads (meth, retval);
564 for (
const auto& nm_ldr : m_package_map)
565 nm_ldr.second.overloads (meth, retval);
570std::list<std::string>
573 std::list<std::string> retval;
575 for (
const auto& dir_ldr : m_package_map)
577 if (! only_top_level || dir_ldr.first.find (
'.') == std::string::npos)
578 retval.push_back (dir_ldr.first);
589 if (sys::env::absolute_pathname (file)
590 || sys::env::rooted_relative_pathname (file))
591 return sys::file_exists (file) ? file : retval;
594 std::string tfile = find_private_file (file);
596 if (! tfile.empty ())
600 if (file.find_first_of (sys::file_ops::dir_sep_chars ())
601 != std::string::npos)
605 for (
const auto& di : m_dir_info_list)
607 std::string tfile = sys::file_ops::concat (di.m_abs_dir_name, file);
609 if (sys::file_exists (tfile))
616 for (
const auto& di : m_dir_info_list)
624 if (all_files[i] == file)
625 return sys::file_ops::concat (di.m_abs_dir_name, file);
638 if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos
639 && (sys::env::absolute_pathname (dir)
640 || sys::env::rooted_relative_pathname (dir)))
642 if (sys::dir_exists (dir))
647 std::string canon_dir = maybe_canonicalize (dir);
648 for (
const auto& di : m_dir_info_list)
650 std::string dname = di.m_abs_dir_name;
652 std::size_t dname_len = dname.length ();
654 if (dname.substr (dname_len - 1)
655 == sys::file_ops::dir_sep_str ())
657 dname = dname.substr (0, dname_len - 1);
661 std::size_t dir_len = canon_dir.length ();
663 if (dname_len > dir_len
664 && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
665 && canon_dir == dname.substr (dname_len - dir_len)
666 && sys::dir_exists (di.m_dir_name))
667 return di.m_abs_dir_name;
677 std::list<std::string> retlist;
679 if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos
680 && (sys::env::absolute_pathname (dir)
681 || sys::env::rooted_relative_pathname (dir)))
683 if (sys::dir_exists (dir))
684 retlist.push_back (dir);
688 std::string canon_dir = maybe_canonicalize (dir);
689 for (
const auto& di : m_dir_info_list)
691 std::string dname = di.m_abs_dir_name;
693 std::size_t dname_len = dname.length ();
695 if (dname.substr (dname_len - 1)
696 == sys::file_ops::dir_sep_str ())
698 dname = dname.substr (0, dname_len - 1);
702 std::size_t dir_len = canon_dir.length ();
704 if (dname_len > dir_len
705 && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
706 && canon_dir == dname.substr (dname_len - dir_len)
707 && sys::dir_exists (di.m_dir_name))
708 retlist.push_back (di.m_abs_dir_name);
720 std::string dir_name;
721 std::string file_name;
730 std::string file = flist[i];
732 if (file.find_first_of (sys::file_ops::dir_sep_chars ())
733 != std::string::npos)
735 if (sys::env::absolute_pathname (file)
736 || sys::env::rooted_relative_pathname (file))
738 if (sys::file_exists (file))
743 for (
const auto& di : m_dir_info_list)
746 tfile = sys::file_ops::concat (di.m_abs_dir_name, file);
748 if (sys::file_exists (tfile))
754 rel_flist[rel_flen++] = file;
757 rel_flist.
resize (rel_flen);
759 for (
const auto& di : m_dir_info_list)
769 if (all_files[i] == rel_flist[j])
771 dir_name = di.m_abs_dir_name;
772 file_name = rel_flist[j];
782 if (! dir_name.empty ())
783 retval = sys::file_ops::concat (dir_name, file_name);
791 std::list<std::string> retlist;
793 std::string dir_name;
794 std::string file_name;
803 std::string file = flist[i];
805 if (file.find_first_of (sys::file_ops::dir_sep_chars ())
806 != std::string::npos)
808 if (sys::env::absolute_pathname (file)
809 || sys::env::rooted_relative_pathname (file))
811 if (sys::file_exists (file))
812 retlist.push_back (file);
816 for (
const auto& di : m_dir_info_list)
819 tfile = sys::file_ops::concat (di.m_abs_dir_name, file);
821 if (sys::file_exists (tfile))
822 retlist.push_back (tfile);
827 rel_flist[rel_flen++] = file;
830 rel_flist.
resize (rel_flen);
832 for (
const auto& di : m_dir_info_list)
842 if (all_files[i] == rel_flist[j])
843 retlist.push_back (sys::file_ops::concat (di.m_abs_dir_name,
855 std::size_t
len = m_dir_info_list.size ();
861 for (
const auto& di : m_dir_info_list)
862 retval[k++] = di.m_dir_name;
867std::list<std::string>
870 std::list<std::string> retval;
872 for (
const auto& di : m_dir_info_list)
873 retval.push_back (di.m_dir_name);
883 const_dir_info_list_iterator p = find_dir_info (dir);
885 if (p != m_dir_info_list.end ())
886 retval = p->m_fcn_files;
894 std::string fname = retval[i];
896 std::size_t pos = fname.rfind (
'.');
898 if (pos != std::string::npos)
899 retval[i] = fname.substr (0, pos);
909 return m_top_level_package.fcn_names ();
933 for (
const auto& di : m_dir_info_list)
937 if (! fcn_files.
empty ())
939 os <<
"\n*** function files in " << di.m_dir_name <<
":\n\n";
944 const dir_info::method_file_map_type& method_file_map
945 = di.m_method_file_map;
947 if (! method_file_map.empty ())
949 for (
const auto& cls_ci : method_file_map)
951 os <<
"\n*** methods in " << di.m_dir_name
952 <<
"/@" << cls_ci.first <<
":\n\n";
963 m_top_level_package.display (os);
965 for (
const auto& nm_ldr : m_package_map)
966 nm_ldr.second.display (os);
972 execute_pkg_add_or_del (dir,
"PKG_ADD");
978 execute_pkg_add_or_del (dir,
"PKG_DEL");
1000load_path::execute_pkg_add_or_del (
const std::string& dir,
1001 const std::string& script_file)
1006 std::string file = sys::file_ops::concat (dir, script_file);
1008 if (sys::file_exists (file))
1015load_path::const_dir_info_list_iterator
1016load_path::find_dir_info (
const std::string& dir_arg)
const
1018 std::string dir = sys::file_ops::tilde_expand (dir_arg);
1020 dir = maybe_canonicalize (dir);
1022 auto retval = m_dir_info_list.cbegin ();
1024 while (retval != m_dir_info_list.cend ())
1026 if (retval->m_dir_name == dir)
1035load_path::dir_info_list_iterator
1036load_path::find_dir_info (
const std::string& dir_arg)
1038 std::string dir = sys::file_ops::tilde_expand (dir_arg);
1040 dir = maybe_canonicalize (dir);
1042 auto retval = m_dir_info_list.begin ();
1044 while (retval != m_dir_info_list.end ())
1046 if (retval->m_dir_name == dir)
1056load_path::contains (
const std::string& dir)
const
1058 return find_dir_info (dir) != m_dir_info_list.end ();
1062load_path::move (dir_info_list_iterator i,
bool at_end)
1064 if (m_dir_info_list.size () > 1)
1068 m_dir_info_list.erase (i);
1071 m_dir_info_list.push_back (di);
1073 m_dir_info_list.push_front (di);
1080load_path::move (
const dir_info& di,
bool at_end,
const std::string& pname)
1082 package_info& l = get_package (pname);
1084 l.move (di, at_end);
1086 dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;
1088 for (
const auto& pkg_di : package_dir_map)
1090 std::string full_name = pkg_di.first;
1092 if (! pname.empty ())
1093 full_name = pname +
'.' + full_name;
1095 move (pkg_di.second, at_end, full_name);
1100load_path::add (
const std::string& dir_arg,
bool at_end,
bool warn)
1102 std::size_t
len = dir_arg.length ();
1104 if (
len > 1 && dir_arg.substr (
len-2) ==
"//")
1106 "trailing '//' is no longer special in search path elements");
1108 std::string dir = sys::file_ops::tilde_expand (dir_arg);
1110 dir = strip_trailing_separators (dir);
1112 dir = maybe_canonicalize (dir);
1114 auto i = find_dir_info (dir);
1116 if (i != m_dir_info_list.end ())
1122 if (sys::dir_exists (dir, msg))
1129 m_dir_info_list.push_back (di);
1131 m_dir_info_list.push_front (di);
1135 if (m_add_hook && di.m_dir_name.compare (
"."))
1139 if (warn && ! msg.empty ())
1140 warning (
"addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
1146 i = find_dir_info (
".");
1148 if (i != m_dir_info_list.end ())
1155 package_info& l = get_package (pname);
1159 dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;
1161 for (
const auto& pkg_di : package_dir_map)
1163 std::string full_name = pkg_di.first;
1165 if (! pname.empty ())
1166 full_name = pname +
'.' + full_name;
1168 remove (pkg_di.second, full_name);
1176 const std::string key = sys::canonicalize_file_name (dir);
1180 conf_file = key + sys::file_ops::dir_sep_str () +
".oct-config";
1182 FILE *cfile = sys::fopen (conf_file,
"rb");
1189 std::string enc_val =
"delete";
1198 const std::string enc_prop =
"encoding";
1201 std::string conf_str =
fgets (cfile, eof);
1204 auto it = std::find_if_not (conf_str.begin (), conf_str.end (),
1205 [] (
unsigned char c)
1206 { return std::isblank (c); });
1207 conf_str.erase (conf_str.begin (), it);
1210 if (conf_str.compare (0, enc_prop.size (), enc_prop) == 0)
1213 std::size_t pos = conf_str.find_first_not_of (
" \t=:",
1215 if (pos == std::string::npos)
1218 std::string enc_val = conf_str.substr (pos);
1221 it = std::find_if_not (enc_val.begin (), enc_val.end (),
1222 [] (
unsigned char c)
1223 { return std::isalnum (c) || c ==
'-'; });
1224 enc_val.erase(it, enc_val.end ());
1226 if (enc_val.empty ())
1239 std::string enc_val =
"delete";
1245load_path::is_package (
const std::string& name)
const
1247 for (
const auto& di : m_dir_info_list)
1249 if (di.is_package (name))
1257load_path::add (
const dir_info& di,
bool at_end,
1258 const std::string& pname,
bool updating)
1260 package_info& l = get_package (pname);
1262 l.add (di, at_end, updating);
1264 dir_info::package_dir_map_type package_dir_map = di.m_package_dir_map;
1266 for (
const auto& pkg_di : package_dir_map)
1268 std::string full_name = pkg_di.first;
1270 if (! pname.empty ())
1271 full_name = pname +
'.' + full_name;
1273 add (pkg_di.second, at_end, full_name);
1278load_path::get_file_list (
const load_path::dir_info::fcn_file_map_type& lst)
const
1286 for (
const auto& nm_typ : lst)
1288 std::string nm = nm_typ.first;
1290 int types = nm_typ.second;
1299 retval[count++] = nm;
1309load_path::find_private_file (
const std::string& fname)
const
1326 std::string dir_name = curr_code->
dir_name ();
1328 if (! dir_name.empty ())
1330 std::string pfname = dir_name + sys::file_ops::dir_sep_str ()
1331 +
"private" + sys::file_ops::dir_sep_str ()
1334 if (sys::file_exists (pfname,
false))
1342load_path::dir_info::fcn_file_map_type
1345 load_path::dir_info::fcn_file_map_type retval;
1350 if (! sys::get_dirlist (
d, flist, msg))
1351 warning (
"load_path: %s: %s",
d.c_str (), msg.c_str ());
1358 std::string fname = flist[i];
1360 std::size_t pos = fname.rfind (
'.');
1362 if (pos != std::string::npos)
1364 std::string base = fname.substr (0, pos);
1365 std::string ext = fname.substr (pos);
1373 else if (ext ==
".oct")
1375 else if (ext ==
".mex")
1380 load_path::dir_info::fcn_file_map_iterator p
1381 = retval.find (base);
1383 if (p == retval.end ())
1397load_path::dir_info::update ()
1399#if defined (OCTAVE_USE_WINDOWS_API)
1402 if (! sys::dir_exists (m_dir_name, msg))
1405 sys::file_stat fs (m_dir_name);
1409 std::string msg = fs.error ();
1412 "load_path: %s: %s", m_dir_name.c_str (), msg.c_str ());
1421 std::string abs_name = sys::canonicalize_file_name (m_dir_name);
1423 const_abs_dir_cache_iterator p = s_abs_dir_cache.find (abs_name);
1425 if (p != s_abs_dir_cache.end ())
1432 const dir_info& di = p->second;
1434#if defined (OCTAVE_USE_WINDOWS_API)
1435 if ((sys::file_time (m_dir_name)
1437 if ((sys::file_time (fs.mtime ().unix_time ())
1439 + sys::file_time::time_resolution ()
1440 > di.m_dir_time_last_checked)
1441 || subdirs_modified (m_dir_name, m_dir_time_last_checked))
1447 m_abs_dir_name = di.m_abs_dir_name;
1448 m_dir_mtime = di.m_dir_mtime;
1449 m_dir_time_last_checked = di.m_dir_time_last_checked;
1450 m_all_files = di.m_all_files;
1451 m_fcn_files = di.m_fcn_files;
1452 m_private_file_map = di.m_private_file_map;
1453 m_method_file_map = di.m_method_file_map;
1454 m_package_dir_map = di.m_package_dir_map;
1474#if defined (OCTAVE_USE_WINDOWS_API)
1475 else if (sys::file_time (m_dir_name)
1477 else if (sys::file_time (fs.mtime ().unix_time ())
1479 + sys::file_time::time_resolution () > m_dir_time_last_checked
1480 || subdirs_modified (m_dir_name, m_dir_time_last_checked))
1487load_path::dir_info::is_package (
const std::string& name)
const
1489 std::size_t pos = name.find (
'.');
1491 if (pos == std::string::npos)
1492 return m_package_dir_map.find (name) != m_package_dir_map.end ();
1495 std::string name_head = name.substr (0, pos);
1496 std::string name_tail = name.substr (pos + 1);
1498 const_package_dir_map_iterator it = m_package_dir_map.find (name_head);
1500 if (it != m_package_dir_map.end ())
1501 return it->second.is_package (name_tail);
1508load_path::dir_info::initialize ()
1510 m_is_relative = ! sys::env::absolute_pathname (m_dir_name);
1512 m_dir_time_last_checked = sys::file_time (
static_cast<OCTAVE_TIME_T
> (0));
1514#if defined (OCTAVE_USE_WINDOWS_API)
1517 if (sys::dir_exists (m_dir_name, msg))
1519 sys::file_stat fs (m_dir_name);
1524 m_method_file_map.clear ();
1525 m_package_dir_map.clear ();
1527#if defined (OCTAVE_USE_WINDOWS_API)
1528 m_dir_mtime = sys::file_time (m_dir_name);
1530 m_dir_mtime = fs.mtime ().unix_time ();
1533 m_dir_time_last_checked = sys::file_time ();
1535 get_file_list (m_dir_name);
1539 m_abs_dir_name = sys::canonicalize_file_name (m_dir_name);
1545 s_abs_dir_cache[m_abs_dir_name] = *
this;
1559#if ! defined (OCTAVE_USE_WINDOWS_API)
1560 std::string msg = fs.error ();
1562 warning (
"load_path: %s: %s", m_dir_name.c_str (), msg.c_str ());
1567load_path::dir_info::get_file_list (
const std::string&
d)
1572 if (! sys::get_dirlist (
d, flist, msg))
1574 warning (
"load_path: %s: %s",
d.c_str (), msg.c_str ());
1580 m_all_files.resize (
len);
1581 m_fcn_files.resize (
len);
1588 std::string fname = flist[i];
1590 std::string full_name = sys::file_ops::concat (
d, fname);
1592 if (sys::dir_exists (full_name))
1594 if (fname ==
"private")
1595 get_private_file_map (full_name);
1596 else if (fname[0] ==
'@')
1597 get_method_file_map (full_name, fname.substr (1));
1598 else if (fname[0] ==
'+')
1599 get_package_dir (full_name, fname.substr (1));
1601 else if (sys::file_exists (full_name))
1603 m_all_files[all_files_count++] = fname;
1605 std::size_t pos = fname.rfind (
'.');
1607 if (pos != std::string::npos)
1609 std::string ext = fname.substr (pos);
1611 if (ext ==
".m" || ext ==
".oct" || ext ==
".mex")
1613 std::string base = fname.substr (0, pos);
1616 m_fcn_files[fcn_files_count++] = fname;
1622 m_all_files.resize (all_files_count);
1623 m_fcn_files.resize (fcn_files_count);
1627load_path::dir_info::get_private_file_map (
const std::string&
d)
1633load_path::dir_info::get_method_file_map (
const std::string&
d,
1634 const std::string& class_name)
1636 m_method_file_map[class_name].m_method_file_map =
get_fcn_files (
d);
1638 std::string pd = sys::file_ops::concat (
d,
"private");
1640 if (sys::dir_exists (pd))
1641 m_method_file_map[class_name].m_private_file_map =
get_fcn_files (pd);
1645load_path::dir_info::get_package_dir (
const std::string&
d,
1646 const std::string& package_name)
1648 m_package_dir_map[package_name] = dir_info (
d);
1652load_path::package_info::move (
const dir_info& di,
bool at_end)
1654 std::string dir_name = di.m_abs_dir_name;
1656 auto s = std::find (m_dir_list.begin (), m_dir_list.end (), dir_name);
1658 if (s != m_dir_list.end ())
1660 m_dir_list.erase (s);
1663 m_dir_list.push_back (dir_name);
1665 m_dir_list.push_front (dir_name);
1668 move_fcn_map (dir_name, di.m_fcn_files, at_end);
1672 move_method_map (dir_name, at_end);
1676load_path::package_info::remove (
const dir_info& di)
1678 std::string dir = di.m_abs_dir_name;
1682 m_dir_list.remove (dir);
1684 remove_fcn_map (dir, fcn_files);
1686 remove_private_fcn_map (dir);
1688 remove_method_map (dir);
1692load_path::package_info::display (std::ostream& os)
const
1694 os <<
"*** package_info: "
1695 << (m_package_name.empty () ?
"<top-level>" : m_package_name)
1698 for (
const auto& dir : m_dir_list)
1702 for (
const auto& dir_fnlst : m_private_fcn_map)
1704 os <<
"\n*** private functions in "
1705 << sys::file_ops::concat (dir_fnlst.first,
"private")
1708 print_fcn_list (os, dir_fnlst.second);
1711#if defined (OCTAVE_LOADPATH_DEBUG)
1713 for (
const auto& nm_filst : m_fcn_map)
1715 os << nm_filst.first <<
":\n";
1717 const file_info_list_type& file_info_list = nm_filst.second;
1719 for (
const auto& finfo : file_info_list)
1721 os <<
" " << finfo.dir_name <<
" (";
1723 print_types (os, finfo.types);
1729 for (
const auto& cls_fnmap : m_method_map)
1731 os <<
"CLASS " << cls_fnmap.first <<
":\n";
1733 const fcn_map_type& fm = cls_fnmap.second;
1735 for (
const auto& nm_fnlst : m_fcn_map)
1737 os <<
" " << nm_fnlst.first <<
":\n";
1739 const file_info_list_type& file_info_list = nm_fnlst.second;
1741 for (
const auto& finfo : file_info_list)
1743 os <<
" " << finfo.dir_name <<
" (";
1745 print_types (os, finfo.types);
1758load_path::package_info::find_fcn (
const std::string& fcn,
1759 std::string& dir_name,
1766 if (fcn.length () > 0 && fcn[0] ==
'@')
1768 std::size_t pos = fcn.find (
'/');
1770 if (pos != std::string::npos)
1772 std::string class_name = fcn.substr (1, pos-1);
1773 std::string meth = fcn.substr (pos+1);
1775 retval = find_method (class_name, meth, dir_name);
1783 const_fcn_map_iterator p = m_fcn_map.find (fcn);
1785 if (p != m_fcn_map.end ())
1787 const file_info_list_type& file_info_list = p->second;
1789 for (
const auto& fi : file_info_list)
1791 retval = sys::file_ops::concat (fi.m_dir_name, fcn);
1793 if (check_file_type (retval, type, fi.m_types,
1794 fcn,
"load_path::find_fcn"))
1796 dir_name = fi.m_dir_name;
1809load_path::package_info::find_private_fcn (
const std::string& dir,
1810 const std::string& fcn,
1817 const_private_fcn_map_iterator q = m_private_fcn_map.find (dir);
1819 if (q != m_private_fcn_map.end ())
1821 const dir_info::fcn_file_map_type& fcn_file_map = q->second;
1823 dir_info::const_fcn_file_map_iterator p = fcn_file_map.find (fcn);
1825 if (p != fcn_file_map.end ())
1828 = sys::file_ops::concat (sys::file_ops::concat (dir,
"private"),
1831 if (check_file_type (fname, type, p->second, fcn,
1832 "load_path::find_private_fcn"))
1841load_path::package_info::find_method (
const std::string& class_name,
1842 const std::string& meth,
1843 std::string& dir_name,
1853 const_method_map_iterator q = m_method_map.find (class_name);
1855 if (q != m_method_map.end ())
1857 const fcn_map_type& m = q->second;
1859 const_fcn_map_iterator p = m.find (meth);
1863 const file_info_list_type& file_info_list = p->second;
1865 for (
const auto& fi : file_info_list)
1867 retval = sys::file_ops::concat (fi.m_dir_name, meth);
1869 bool found = check_file_type (retval, type, fi.m_types,
1870 meth,
"load_path::find_method");
1874 dir_name = fi.m_dir_name;
1886std::list<std::string>
1887load_path::package_info::methods (
const std::string& class_name)
const
1889 std::list<std::string> retval;
1893 const_method_map_iterator mtd_map_it = m_method_map.find (class_name);
1895 if (mtd_map_it != m_method_map.end ())
1897 for (
const auto& nm_filst : mtd_map_it->second)
1898 retval.push_back (nm_filst.first);
1901 if (! retval.empty ())
1908load_path::package_info::overloads (
const std::string& meth,
1909 std::list<std::string>& l)
const
1911 for (
const auto& cls_fnmap : m_method_map)
1913 const fcn_map_type& m = cls_fnmap.second;
1915 if (m.find (meth) != m.end ())
1917 std::string class_name = cls_fnmap.first;
1919 if (! m_package_name.empty ())
1920 class_name = m_package_name +
'.' + class_name;
1922 l.push_back (class_name);
1928load_path::package_info::fcn_names ()
const
1930 std::size_t
len = m_fcn_map.size ();
1936 for (
const auto& nm_filst : m_fcn_map)
1937 retval[count++] = nm_filst.first;
1943load_path::package_info::add_to_fcn_map (
const dir_info& di,
1944 bool at_end,
bool updating)
1946 std::string dir_name = di.m_abs_dir_name;
1954 std::string fname = fcn_files[i];
1957 std::string base = fname;
1959 std::size_t pos = fname.rfind (
'.');
1961 if (pos != std::string::npos)
1963 base = fname.substr (0, pos);
1964 ext = fname.substr (pos);
1967 file_info_list_type& file_info_list = m_fcn_map[base];
1969 auto p = file_info_list.begin ();
1971 while (p != file_info_list.end ())
1973 if (p->m_dir_name == dir_name)
1982 else if (ext ==
".oct")
1984 else if (ext ==
".mex")
1987 if (p == file_info_list.end ())
1994 if (file_info_list.empty ())
2004 if (m_package_name.empty ()
2007 std::string fcn_path = sys::file_ops::concat (dir_name,
2011 "function %s shadows a built-in function",
2017 file_info& old = file_info_list.front ();
2026 if (fname !=
"Contents.m"
2027 && s_sys_path.find (old.m_dir_name) != std::string::npos
2028 && in_path_list (s_sys_path, old.m_dir_name))
2030 std::string fcn_path = sys::file_ops::concat (dir_name,
2034 "function %s shadows a core library function",
2043 file_info_list.push_back (fi);
2045 file_info_list.push_front (fi);
2057load_path::package_info::add_to_private_fcn_map (
const dir_info& di)
2059 dir_info::fcn_file_map_type private_file_map = di.m_private_file_map;
2061 if (! private_file_map.empty ())
2062 m_private_fcn_map[di.m_abs_dir_name] = private_file_map;
2066load_path::package_info::add_to_method_map (
const dir_info& di,
bool at_end)
2068 std::string dir_name = di.m_abs_dir_name;
2071 dir_info::method_file_map_type method_file_map = di.m_method_file_map;
2073 for (
const auto& cls_ci : method_file_map)
2075 std::string class_name = cls_ci.first;
2077 fcn_map_type& fm = m_method_map[class_name];
2079 std::string full_dir_name
2080 = sys::file_ops::concat (dir_name,
'@' + class_name);
2082 const dir_info::class_info& ci = cls_ci.second;
2085 const dir_info::fcn_file_map_type& m = ci.m_method_file_map;
2087 for (
const auto& nm_typ : m)
2089 std::string base = nm_typ.first;
2090 int types = nm_typ.second;
2092 file_info_list_type& file_info_list = fm[base];
2094 auto p2 = file_info_list.begin ();
2095 while (p2 != file_info_list.end ())
2097 if (p2->m_dir_name == full_dir_name)
2103 if (p2 == file_info_list.end ())
2108 file_info_list.push_back (fi);
2110 file_info_list.push_front (fi);
2122 dir_info::fcn_file_map_type private_file_map = ci.m_private_file_map;
2124 if (! private_file_map.empty ())
2125 m_private_fcn_map[full_dir_name] = private_file_map;
2130load_path::package_info::move_fcn_map (
const std::string& dir_name,
2138 std::string fname = fcn_files[k];
2141 std::string base = fname;
2143 std::size_t pos = fname.rfind (
'.');
2145 if (pos != std::string::npos)
2147 base = fname.substr (0, pos);
2148 ext = fname.substr (pos);
2151 file_info_list_type& file_info_list = m_fcn_map[base];
2153 if (file_info_list.size () == 1)
2157 for (
auto fi_it = file_info_list.begin ();
2158 fi_it != file_info_list.end ();
2161 if (fi_it->m_dir_name == dir_name)
2165 file_info_list.erase (fi_it);
2168 file_info_list.push_back (fi_tmp);
2170 file_info_list.push_front (fi_tmp);
2180load_path::package_info::move_method_map (
const std::string& dir_name,
2183 for (
auto& cls_fnmap : m_method_map)
2185 std::string class_name = cls_fnmap.first;
2187 fcn_map_type& fn_map = cls_fnmap.second;
2189 std::string full_dir_name
2190 = sys::file_ops::concat (dir_name,
'@' + class_name);
2192 for (
auto& nm_filst : fn_map)
2194 file_info_list_type& file_info_list = nm_filst.second;
2196 if (file_info_list.size () == 1)
2200 for (
auto fi_it = file_info_list.begin ();
2201 fi_it != file_info_list.end (); fi_it++)
2203 if (fi_it->m_dir_name == full_dir_name)
2207 file_info_list.erase (fi_it);
2210 file_info_list.push_back (fi_tmp);
2212 file_info_list.push_front (fi_tmp);
2223load_path::package_info::remove_fcn_map (
const std::string& dir,
2230 std::string fname = fcn_files[k];
2233 std::string base = fname;
2235 std::size_t pos = fname.rfind (
'.');
2237 if (pos != std::string::npos)
2239 base = fname.substr (0, pos);
2240 ext = fname.substr (pos);
2243 file_info_list_type& file_info_list = m_fcn_map[base];
2245 for (
auto fi_it = file_info_list.begin ();
2246 fi_it != file_info_list.end ();
2249 if (fi_it->m_dir_name == dir)
2251 file_info_list.erase (fi_it);
2253 if (file_info_list.empty ())
2254 m_fcn_map.erase (fname);
2263load_path::package_info::remove_private_fcn_map (
const std::string& dir)
2265 auto p = m_private_fcn_map.find (dir);
2267 if (p != m_private_fcn_map.end ())
2268 m_private_fcn_map.erase (p);
2272load_path::package_info::remove_method_map (
const std::string& dir)
2274 for (
auto& cls_fnmap : m_method_map)
2276 std::string class_name = cls_fnmap.first;
2278 fcn_map_type& fn_map = cls_fnmap.second;
2280 std::string full_dir_name
2281 = sys::file_ops::concat (dir,
'@' + class_name);
2283 for (
auto& nm_filst : fn_map)
2285 file_info_list_type& file_info_list = nm_filst.second;
2287 if (file_info_list.size () == 1)
2291 for (
auto fi_it = file_info_list.begin ();
2292 fi_it != file_info_list.end (); fi_it++)
2294 if (fi_it->m_dir_name == full_dir_name)
2296 file_info_list.erase (fi_it);
2310load_path::package_info::check_file_type (std::string& fname,
int type,
2312 const std::string& fcn,
2313 const char *who)
const
2315 bool retval =
false;
2400 error (
"%s: %s: invalid type code = %d", who, fcn.c_str (), type);
2406load_path::package_info::print_types (std::ostream& os,
int types)
const
2408 bool printed_type =
false;
2413 printed_type =
true;
2421 printed_type =
true;
2429 printed_type =
true;
2434load_path::package_info::print_fcn_list (std::ostream& os,
2435 const load_path::dir_info::fcn_file_map_type& lst)
const
2437 for (
const auto& nm_typ : lst)
2439 os <<
" " << nm_typ.first <<
" (";
2441 print_types (os, nm_typ.second);
2454 if (! sys::get_dirlist (
dirname, dirlist, msg))
2459 dirlist = dirlist.
sort (
false);
2465 std::string elt = dirlist[i];
2467 bool skip_p = (elt ==
"." || elt ==
".." || elt[0] ==
'@'
2474 skip_p = (elt == skip[j]);
2481 std::string nm = sys::file_ops::concat (
dirname, elt);
2483 if (sys::dir_exists (nm))
2508 int nargin = args.length ();
2517 std::string
dirname = args(0).xstring_value (
"genpath: DIR must be a string");
2523 std::string
dirname = args(0).xstring_value (
"genpath: all arguments must be strings");
2528 skip[i-1] = args(i).xstring_value (
"genpath: all arguments must be strings");
2542 load_path& lp = interp.get_load_path ();
2549DEFMETHOD (command_line_path, interp, args, ,
2558 if (! args.empty ())
2561 load_path& lp = interp.get_load_path ();
2566DEFMETHOD (restoredefaultpath, interp, args, ,
2575 if (! args.empty ())
2578 load_path& lp = interp.get_load_path ();
2597 load_path& lp = interp.get_load_path ();
2602 std::string sys_path = args(0).xstring_value (
"__pathorig__: SYS_PATH must be a string");
2605 return ovl (prev_sys_path);
2629 int nargin = args.length ();
2633 load_path& lp = interp.get_load_path ();
2637 std::string path = argv[1];
2639 for (
int i = 2; i <= nargin; i++)
2642 lp.
set (path,
true);
2649 else if (nargin == 0 && nargout == 0)
2652 "\nOctave's search path contains the following directories:\n\n";
2664DEFMETHOD (addpath, interp, args, nargout,
2699 int nargin = args.length ();
2704 load_path& lp = interp.get_load_path ();
2709 retval = lp.
path ();
2711 bool append =
false;
2719 if (option ==
"-end")
2724 else if (option ==
"-begin")
2729 int val = option_arg.
strict_int_value (
"addpath: OPTION must be '-begin'/0 or '-end'/1");
2739 error (
"addpath: OPTION must be '-begin'/0 or '-end'/1");
2742 bool need_to_update =
false;
2748 for (
int i = 0; i < arglist.
length (); i++)
2750 std::string arg = arglist(i).xstring_value (
"addpath: all arguments must be strings");
2752 std::list<std::string> dir_elts = split_path (arg);
2755 std::reverse (dir_elts.begin (), dir_elts.end ());
2757 for (
auto dir : dir_elts)
2760 auto it_start = dir.begin ();
2761#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
2765 dir.erase (std::unique
2766 (it_start, dir.end (),
2769 return l == r && sys::file_ops::is_dir_sep (l);
2773 auto pos = dir.find_last_of (sys::file_ops::dir_sep_chars ());
2774 if (pos == std::string::npos)
2776 if (! dir.empty () && dir[0] ==
'+')
2778 "addpath: package directories should not be "
2779 "added to path: %s\n", dir.c_str ());
2783 if (pos + 1 < dir.length () && dir[pos+1] ==
'+')
2785 "addpath: package directories should not be "
2786 "added to path: %s\n", dir.c_str ());
2794 need_to_update =
true;
2804DEFMETHOD (rmpath, interp, args, nargout,
2827 int nargin = args.
length ();
2834 load_path& lp = interp.get_load_path ();
2837 retval = lp.
path ();
2839 bool need_to_update =
false;
2841 for (
int i = 0; i < nargin; i++)
2843 std::string arg = args(i).xstring_value (
"rmpath: all arguments must be strings");
2844 std::list<std::string> dir_elts = split_path (arg);
2846 for (
const auto& dir : dir_elts)
2852 warning (
"rmpath: %s: not found", dir.c_str ());
2854 need_to_update =
true;
2864DEFMETHOD (__dump_load_path__, interp, , ,
2870 load_path& lp = interp.get_load_path ();
2877OCTAVE_END_NAMESPACE(octave)
static std::string path_sep_str()
static char path_sep_char()
Provides threadsafe access to octave.
void update_path_dialog()
int debug_cd_or_addpath_error(const std::string &file, const std::string &dir, bool addpath_option)
symbol_scope get_current_scope() const
int chdir(const std::string &dir)
void recover_from_exception()
event_manager & get_event_manager()
std::string find_first_of(const string_vector &files) const
string_vector files(const std::string &dir, bool omit_exts=false) const
string_vector find_matching_dirs(const std::string &dir) const
void set(const std::string &p, bool warn=false, bool is_init=false)
load_path(interpreter &interp)
bool contains_canonical(const std::string &dir_name) const
string_vector fcn_names() const
string_vector find_all_first_of(const string_vector &files) const
void prepend(const std::string &dir, bool warn=false)
void initialize(bool set_initial_path=false)
std::string find_file(const std::string &file) const
string_vector dirs() const
std::string system_path() const
void display(std::ostream &os) const
void read_dir_config(const std::string &dir) const
void execute_pkg_add(const std::string &dir)
bool remove(const std::string &dir)
std::string find_dir(const std::string &dir) const
std::list< std::string > overloads(const std::string &meth) const
bool contains_file_in_dir(const std::string &file_name, const std::string &dir_name)
void append(const std::string &dir, bool warn=false)
static const int OCT_FILE
void execute_pkg_del(const std::string &dir)
std::list< std::string > get_all_package_names(bool only_top_level=true) const
std::string get_command_line_path() const
std::list< std::string > dir_list() const
static const int MEX_FILE
std::string dir_name() const
octave_value_list & reverse()
octave_idx_type length() const
int strict_int_value(bool frc_str_conv=false) const
std::string string_value(bool force=false) const
octave_idx_type length() const
string_vector & sort(bool make_uniq=false)
void resize(octave_idx_type n, const std::string &rfv="")
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
octave_idx_type numel() const
octave_user_code * user_code() const
bool is_built_in_function_name(const std::string &name)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void warning(const char *fmt,...)
void warning_with_id(const char *id, const char *fmt,...)
void error(const char *fmt,...)
std::string dirname(const std::string &path)
symbol_table & __get_symbol_table__()
input_system & __get_input_system__()
interpreter & __get_interpreter__()
bool octave_interpreter_ready
std::string fgets(FILE *f)
std::string genpath(const std::string &dirname, const string_vector &skip)
load_path::dir_info::fcn_file_map_type get_fcn_files(const std::string &d)
void source_file(const std::string &file_name, const std::string &context, bool verbose, bool require_file)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
fcn_file_map_type m_method_file_map
bool valid_identifier(const char *s)