GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
load-path.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2006-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <algorithm>
31 
32 #include "dir-ops.h"
33 #include "file-ops.h"
34 #include "file-stat.h"
35 #include "oct-env.h"
36 #include "pathsearch.h"
37 
38 #include "defaults.h"
39 #include "defun.h"
40 #include "input.h"
41 #include "interpreter-private.h"
42 #include "interpreter.h"
43 #include "load-path.h"
44 #include "ov-usr-fcn.h"
45 #include "pager.h"
46 #include "parse.h"
47 #include "sysdep.h"
48 #include "unwind-prot.h"
49 #include "utils.h"
50 
51 namespace octave
52 {
53  // Canonicalize file name (keeping the path relative) if it exists.
54  // Return it unmodified otherwise.
55 
56  static std::string
57  maybe_canonicalize (const std::string& dir_arg)
58  {
59  bool is_absolute_path = sys::env::absolute_pathname (dir_arg);
60 
61  std::string canonical_dir = sys::canonicalize_file_name (dir_arg);
62  std::string dir;
63  if (canonical_dir.empty ())
64  dir = dir_arg;
65  else
66  {
67  dir = canonical_dir;
68 
69  if (! is_absolute_path)
70  {
71  // Remove current path from absolute path generated by
72  // canonicalize_file_name.
73  std::string cwd = sys::canonicalize_file_name (".");
74  if (dir.compare (0, cwd.length (), cwd) == 0)
75  dir.erase (0, cwd.length ()+1);
76  if (dir.empty ())
77  dir = ".";
78  }
79  }
80 
81  return dir;
82  }
83 
84  static void
85  maybe_add_path_elts (std::string& path, const std::string& dir)
86  {
87  std::string tpath = genpath (maybe_canonicalize (dir));
88 
89  if (! tpath.empty ())
90  {
91  if (path.empty ())
92  path = tpath;
93  else
94  path += directory_path::path_sep_str () + tpath;
95  }
96  }
97 
98  static std::list<std::string>
99  split_path (const std::string& p)
100  {
101  std::list<std::string> retval;
102 
103  size_t beg = 0;
104  size_t end = p.find (directory_path::path_sep_char ());
105 
106  size_t len = p.length ();
107 
108  while (end != std::string::npos)
109  {
110  std::string elt = p.substr (beg, end-beg);
111 
112  if (! elt.empty ())
113  retval.push_back (elt);
114 
115  beg = end + 1;
116 
117  if (beg == len)
118  break;
119 
120  end = p.find (directory_path::path_sep_char (), beg);
121  }
122 
123  std::string elt = p.substr (beg);
124 
125  if (! elt.empty ())
126  retval.push_back (elt);
127 
128  return retval;
129  }
130 
131  // Strip trailing directory separators.
132 
133  static std::string
134  strip_trailing_separators (const std::string& dir_arg)
135  {
136  std::string dir = dir_arg;
137 
138  size_t k = dir.length ();
139 
140  while (k > 1 && sys::file_ops::is_dir_sep (dir[k-1]))
141  k--;
142 
143  if (k < dir.length ())
144  dir.resize (k);
145 
146  return dir;
147  }
148 
149  // Should we cache all files in private directories, or is it OK to just
150  // look them up each time as needed?
151 
152  static std::string
153  find_private_file (const std::string& fname)
154  {
155  std::string retval;
156 
157  // Look in private directory corresponding to current function (if
158  // any).
159 
160  symbol_scope scope = __get_current_scope__ ("find_private_file");
161 
162  octave_user_code *curr_code = scope ? scope.user_code () : nullptr;
163 
164  if (curr_code)
165  {
166  // Even for private functions, dir_name doesn't contain the
167  // "private" directory component so we append it here in all
168  // cases.
169 
170  std::string dir_name = curr_code->dir_name ();
171 
172  if (! dir_name.empty ())
173  {
174  std::string pfname = dir_name + sys::file_ops::dir_sep_str ()
175  + "private" + sys::file_ops::dir_sep_str ()
176  + fname;
177 
178  sys::file_stat fs (pfname);
179 
180  if (fs.exists () && fs.is_reg ())
181  retval = pfname;
182  }
183  }
184 
185  return retval;
186  }
187 
188  // True if a path is contained in a path list separated by path_sep_char
189 
190  static bool
191  in_path_list (const std::string& path_list, const std::string& path)
192  {
193  size_t ps = path.size ();
194  size_t pls = path_list.size ();
195  size_t pos = path_list.find (path);
196  char psc = directory_path::path_sep_char ();
197  while (pos != std::string::npos)
198  {
199  if ((pos == 0 || path_list[pos-1] == psc)
200  && (pos + ps == pls || path_list[pos + ps] == psc))
201  return true;
202  else
203  pos = path_list.find (path, pos + 1);
204  }
205 
206  return false;
207  }
208 
209  static void
211  {
212  load_path& lp = __get_load_path__ ("rehash_internal");
213 
214  lp.update ();
215 
216  // Signal the GUI allowing updating the load path dialog
217  event_manager& evmgr = __get_event_manager__ ("rehash_internal");
218  evmgr.update_path_dialog ();
219 
220  // FIXME: maybe we should rename this variable since it is being
221  // used for more than keeping track of the prompt time.
222 
223  // This will force updated functions to be found.
225  }
226 
227  std::string load_path::sys_path;
229 
231  : m_interpreter (interp), package_map (), top_level_package (),
232  dir_info_list (), init_dirs (), m_command_line_path (),
233  add_hook ([this] (const std::string& dir) { this->execute_pkg_add (dir); }),
234  remove_hook ([this] (const std::string& dir) { this->execute_pkg_del (dir); })
235  { }
236 
237  void
238  load_path::initialize (bool set_initial_path)
239  {
240  sys_path = "";
241 
242  if (set_initial_path)
243  {
253  }
254 
255  std::string tpath = load_path::m_command_line_path;
256 
257  if (tpath.empty ())
258  tpath = sys::env::getenv ("OCTAVE_PATH");
259 
260  std::string xpath;
261 
262  if (! tpath.empty ())
263  {
264  xpath = tpath;
265 
266  if (! sys_path.empty ())
268  }
269  else
270  xpath = sys_path;
271 
272  set (xpath, false, true);
273  }
274 
275  void
277  {
278  dir_info_list.clear ();
279 
281 
282  package_map.clear ();
283  }
284 
285  void
286  load_path::set (const std::string& p, bool warn, bool is_init)
287  {
288  // Use a list when we need to preserve order.
289  std::list<std::string> elts = split_path (p);
290 
291  for (auto& elt : elts)
292  elt = maybe_canonicalize (elt);
293 
294  // Use a set when we need to search and order is not important.
295  std::set<std::string> elts_set (elts.begin (), elts.end ());
296 
297  if (is_init)
298  init_dirs = elts_set;
299  else
300  {
301  for (const auto& init_dir : init_dirs)
302  {
303  if (elts_set.find (init_dir) == elts_set.end ())
304  {
305  warning_with_id ("Octave:remove-init-dir",
306  "default load path altered. Some built-in functions may not be found. Try restoredefaultpath() to recover it.");
307  break;
308  }
309  }
310  }
311 
312  // Temporarily disable add hook.
313 
314  unwind_protect frame;
315  frame.protect_var (add_hook);
316 
317  add_hook = nullptr;
318 
319  clear ();
320 
321  for (const auto& elt : elts)
322  append (elt, warn);
323 
324  // Restore add hook and execute for all newly added directories.
325  frame.run_first ();
326 
327  // FIXME: Shouldn't the test for add_hook be outside the for loop?
328  // Why not use const here? Does add_hook change dir_info_list?
329  for (auto& di : dir_info_list)
330  {
331  if (add_hook)
332  add_hook (di.dir_name);
333  }
334 
335  // Always prepend current directory.
336  prepend (".", warn);
337  }
338 
339  void
340  load_path::append (const std::string& dir, bool warn)
341  {
342  if (! dir.empty ())
343  add (dir, true, warn);
344  }
345 
346  void
347  load_path::prepend (const std::string& dir, bool warn)
348  {
349  if (! dir.empty ())
350  add (dir, false, warn);
351  }
352 
353  bool
354  load_path::remove (const std::string& dir_arg)
355  {
356  bool retval = false;
357 
358  if (! dir_arg.empty ())
359  {
360  if (dir_arg == ".")
361  {
362  warning (R"(rmpath: can't remove "." from path)");
363 
364  // Avoid additional warnings.
365  retval = true;
366  }
367  else
368  {
369  std::string dir = sys::file_ops::tilde_expand (dir_arg);
370 
371  dir = strip_trailing_separators (dir);
372 
373  auto i = find_dir_info (dir);
374 
375  if (i != dir_info_list.end ())
376  {
377  retval = true;
378 
379  if (remove_hook)
380  remove_hook (dir);
381 
382  dir_info& di = *i;
383 
384  remove (di);
385 
386  dir_info_list.erase (i);
387  }
388  }
389  }
390 
391  return retval;
392  }
393 
394  void
395  load_path::update (void) const
396  {
397  // I don't see a better way to do this because we need to
398  // preserve the correct directory ordering for new files that
399  // have appeared.
400 
402 
403  package_map.clear ();
404 
405  for (auto& di : dir_info_list)
406  {
407  bool ok = di.update ();
408 
409  if (! ok)
410  warning ("load-path: update failed for '%s', removing from path",
411  di.dir_name.c_str ());
412  else
413  add (di, true, "", true);
414  }
415  }
416 
417  bool
418  load_path::contains_canonical (const std::string& dir) const
419  {
420  bool retval = false;
421 
422  for (const auto& d : dir_info_list)
423  {
424  if (same_file (dir, d.dir_name))
425  {
426  retval = true;
427  break;
428  }
429  }
430 
431  return retval;
432  }
433 
434  bool
435  load_path::contains_file_in_dir (const std::string& file,
436  const std::string& dir)
437  {
438  bool ok = false;
439  bool addpath_option = true;
440 
441  std::string curr_dir = sys::env::get_current_directory ();
442 
443  if (same_file (curr_dir, dir))
444  ok = true;
445  else
446  {
447  bool dir_in_load_path = contains_canonical (dir);
448 
449  // get base name, allowing "@class/method.m" (bug #41514)
450  std::string base_file = (file.length () > dir.length ())
451  ? file.substr (dir.length () + 1)
452  : sys::env::base_pathname (file);
453 
454  std::string lp_file = find_file (base_file);
455 
456  if (dir_in_load_path)
457  {
458  if (same_file (lp_file, file))
459  ok = true;
460  }
461  else
462  {
463  // File directory is not in path. Is the file in the path in
464  // the current directory? If so, then changing the current
465  // directory will be needed. Adding directory to path is
466  // not enough because the file in the current directory would
467  // still be found.
468 
469  if (same_file (lp_file, base_file))
470  {
471  if (same_file (curr_dir, dir))
472  ok = true;
473  else
474  addpath_option = false;
475  }
476  }
477  }
478 
479  if (! ok)
480  {
482 
483  int action
484  = evmgr.debug_cd_or_addpath_error (file, dir, addpath_option);
485 
486  switch (action)
487  {
488  case 1:
489  m_interpreter.chdir (dir);
490  ok = true;
491  break;
492 
493  case 2:
494  {
495  prepend (dir);
496  ok = true;
497  }
498  break;
499 
500  default:
501  break;
502  }
503  }
504 
505  return ok;
506  }
507 
508  std::list<std::string>
509  load_path::overloads (const std::string& meth) const
510  {
511  std::list<std::string> retval;
512 
513  // update ();
514 
516 
517  for (const auto& nm_ldr : package_map)
518  nm_ldr.second.overloads (meth, retval);
519 
520  return retval;
521  }
522 
523  std::list<std::string>
524  load_path::get_all_package_names (bool only_top_level) const
525  {
526  std::list<std::string> retval;
527 
528  for (const auto& dir_ldr : package_map)
529  {
530  if (! only_top_level || dir_ldr.first.find ('.') == std::string::npos)
531  retval.push_back (dir_ldr.first);
532  }
533 
534  return retval;
535  }
536 
537  std::string
538  load_path::find_file (const std::string& file) const
539  {
540  std::string retval;
541 
542  if (sys::env::absolute_pathname (file)
544  {
545  sys::file_stat fs (file);
546 
547  return fs.exists () ? file : retval;
548  }
549  else
550  {
551  std::string tfile = find_private_file (file);
552 
553  if (! tfile.empty ())
554  return tfile;
555  }
556 
557  if (file.find_first_of (sys::file_ops::dir_sep_chars ())
558  != std::string::npos)
559  {
560  // Given name has a directory separator, so append it to each
561  // element of the load path in turn.
562  for (const auto& di : dir_info_list)
563  {
564  std::string tfile = sys::file_ops::concat (di.abs_dir_name, file);
565 
566  sys::file_stat fs (tfile);
567 
568  if (fs.exists ())
569  return tfile;
570  }
571  }
572  else
573  {
574  // Look in cache.
575  for (const auto & di : dir_info_list)
576  {
577  string_vector all_files = di.all_files;
578 
579  octave_idx_type len = all_files.numel ();
580 
581  for (octave_idx_type i = 0; i < len; i++)
582  {
583  if (all_files[i] == file)
584  return sys::file_ops::concat (di.abs_dir_name, file);
585  }
586  }
587  }
588 
589  return retval;
590  }
591 
592  std::string
593  load_path::find_dir (const std::string& dir) const
594  {
595  std::string retval;
596 
597  if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos
600  {
601  sys::file_stat fs (dir);
602 
603  if (fs.exists () && fs.is_dir ())
604  return dir;
605  }
606  else
607  {
608  std::string canon_dir = maybe_canonicalize (dir);
609  for (const auto& di : dir_info_list)
610  {
611  std::string dname = di.abs_dir_name;
612 
613  size_t dname_len = dname.length ();
614 
615  if (dname.substr (dname_len - 1)
617  {
618  dname = dname.substr (0, dname_len - 1);
619  dname_len--;
620  }
621 
622  size_t dir_len = canon_dir.length ();
623 
624  if (dname_len > dir_len
625  && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
626  && canon_dir == dname.substr (dname_len - dir_len))
627  {
628  sys::file_stat fs (di.dir_name);
629 
630  if (fs.exists () && fs.is_dir ())
631  return di.abs_dir_name;
632  }
633  }
634  }
635 
636  return retval;
637  }
638 
640  load_path::find_matching_dirs (const std::string& dir) const
641  {
642  std::list<std::string> retlist;
643 
644  if (dir.find_first_of (sys::file_ops::dir_sep_chars ()) != std::string::npos
647  {
648  sys::file_stat fs (dir);
649 
650  if (fs.exists () && fs.is_dir ())
651  retlist.push_back (dir);
652  }
653  else
654  {
655  std::string canon_dir = maybe_canonicalize (dir);
656  for (const auto& di : dir_info_list)
657  {
658  std::string dname = di.abs_dir_name;
659 
660  size_t dname_len = dname.length ();
661 
662  if (dname.substr (dname_len - 1)
664  {
665  dname = dname.substr (0, dname_len - 1);
666  dname_len--;
667  }
668 
669  size_t dir_len = canon_dir.length ();
670 
671  if (dname_len > dir_len
672  && sys::file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
673  && canon_dir == dname.substr (dname_len - dir_len))
674  {
675  sys::file_stat fs (di.dir_name);
676 
677  if (fs.exists () && fs.is_dir ())
678  retlist.push_back (di.abs_dir_name);
679  }
680  }
681  }
682 
683  return retlist;
684  }
685 
686  std::string
688  {
689  std::string retval;
690 
691  std::string dir_name;
692  std::string file_name;
693 
694  octave_idx_type flen = flist.numel ();
695  octave_idx_type rel_flen = 0;
696 
697  string_vector rel_flist (flen);
698 
699  for (octave_idx_type i = 0; i < flen; i++)
700  {
701  std::string file = flist[i];
702 
703  if (file.find_first_of (sys::file_ops::dir_sep_chars ())
704  != std::string::npos)
705  {
706  if (sys::env::absolute_pathname (file)
708  {
709  sys::file_stat fs (file);
710 
711  if (fs.exists ())
712  return file;
713  }
714  else
715  {
716  for (const auto& di : dir_info_list)
717  {
718  std::string tfile;
719  tfile = sys::file_ops::concat (di.abs_dir_name, file);
720 
721  sys::file_stat fs (tfile);
722 
723  if (fs.exists ())
724  return tfile;
725  }
726  }
727  }
728  else
729  rel_flist[rel_flen++] = file;
730  }
731 
732  rel_flist.resize (rel_flen);
733 
734  for (const auto& di : dir_info_list)
735  {
736  string_vector all_files = di.all_files;
737 
738  octave_idx_type len = all_files.numel ();
739 
740  for (octave_idx_type i = 0; i < len; i++)
741  {
742  for (octave_idx_type j = 0; j < rel_flen; j++)
743  {
744  if (all_files[i] == rel_flist[j])
745  {
746  dir_name = di.abs_dir_name;
747  file_name = rel_flist[j];
748 
749  goto done;
750  }
751  }
752  }
753  }
754 
755  done:
756 
757  if (! dir_name.empty ())
758  retval = sys::file_ops::concat (dir_name, file_name);
759 
760  return retval;
761  }
762 
765  {
766  std::list<std::string> retlist;
767 
768  std::string dir_name;
769  std::string file_name;
770 
771  octave_idx_type flen = flist.numel ();
772  octave_idx_type rel_flen = 0;
773 
774  string_vector rel_flist (flen);
775 
776  for (octave_idx_type i = 0; i < flen; i++)
777  {
778  std::string file = flist[i];
779 
780  if (file.find_first_of (sys::file_ops::dir_sep_chars ())
781  != std::string::npos)
782  {
783  if (sys::env::absolute_pathname (file)
785  {
786  sys::file_stat fs (file);
787 
788  if (fs.exists ())
789  retlist.push_back (file);
790  }
791  else
792  {
793  for (const auto& di : dir_info_list)
794  {
795  std::string tfile;
796  tfile = sys::file_ops::concat (di.abs_dir_name, file);
797 
798  sys::file_stat fs (tfile);
799 
800  if (fs.exists ())
801  retlist.push_back (tfile);
802  }
803  }
804  }
805  else
806  rel_flist[rel_flen++] = file;
807  }
808 
809  rel_flist.resize (rel_flen);
810 
811  for (const auto& di : dir_info_list)
812  {
813  string_vector all_files = di.all_files;
814 
815  octave_idx_type len = all_files.numel ();
816 
817  for (octave_idx_type i = 0; i < len; i++)
818  {
819  for (octave_idx_type j = 0; j < rel_flen; j++)
820  {
821  if (all_files[i] == rel_flist[j])
822  retlist.push_back (sys::file_ops::concat (di.abs_dir_name,
823  rel_flist[j]));
824  }
825  }
826  }
827 
828  return retlist;
829  }
830 
832  load_path::dirs (void) const
833  {
834  size_t len = dir_info_list.size ();
835 
837 
838  octave_idx_type k = 0;
839 
840  for (const auto& di : dir_info_list)
841  retval[k++] = di.dir_name;
842 
843  return retval;
844  }
845 
846  std::list<std::string>
847  load_path::dir_list (void) const
848  {
849  std::list<std::string> retval;
850 
851  for (const auto& di : dir_info_list)
852  retval.push_back (di.dir_name);
853 
854  return retval;
855  }
856 
858  load_path::files (const std::string& dir, bool omit_exts) const
859  {
861 
863 
864  if (p != dir_info_list.end ())
865  retval = p->fcn_files;
866 
867  if (omit_exts)
868  {
870 
871  for (octave_idx_type i = 0; i < len; i++)
872  {
873  std::string fname = retval[i];
874 
875  size_t pos = fname.rfind ('.');
876 
877  if (pos != std::string::npos)
878  retval[i] = fname.substr (0, pos);
879  }
880  }
881 
882  return retval;
883  }
884 
886  load_path::fcn_names (void) const
887  {
888  return top_level_package.fcn_names ();
889  }
890 
891  std::string
892  load_path::path (void) const
893  {
894  std::string xpath;
895 
896  string_vector xdirs = load_path::dirs ();
897 
898  octave_idx_type len = xdirs.numel ();
899 
900  if (len > 0)
901  xpath = xdirs[0];
902 
903  for (octave_idx_type i = 1; i < len; i++)
904  xpath += directory_path::path_sep_str () + xdirs[i];
905 
906  return xpath;
907  }
908 
909  void
910  load_path::display (std::ostream& os) const
911  {
912  for (const auto& di : dir_info_list)
913  {
914  string_vector fcn_files = di.fcn_files;
915 
916  if (! fcn_files.empty ())
917  {
918  os << "\n*** function files in " << di.dir_name << ":\n\n";
919 
920  fcn_files.list_in_columns (os);
921  }
922 
923  const dir_info::method_file_map_type& method_file_map
924  = di.method_file_map;
925 
926  if (! method_file_map.empty ())
927  {
928  for (const auto& cls_ci : method_file_map)
929  {
930  os << "\n*** methods in " << di.dir_name
931  << "/@" << cls_ci.first << ":\n\n";
932 
933  const dir_info::class_info& ci = cls_ci.second;
934 
935  string_vector method_files = get_file_list (ci.method_file_map);
936 
937  method_files.list_in_columns (os);
938  }
939  }
940  }
941 
943 
944  for (const auto& nm_ldr : package_map)
945  nm_ldr.second.display (os);
946  }
947 
948  void
949  load_path::execute_pkg_add (const std::string& dir)
950  {
951  execute_pkg_add_or_del (dir, "PKG_ADD");
952  }
953 
954  void
955  load_path::execute_pkg_del (const std::string& dir)
956  {
957  execute_pkg_add_or_del (dir, "PKG_DEL");
958  }
959 
960  void load_path::execute_pkg_add_or_del (const std::string& dir,
961  const std::string& script_file)
962  {
964  return;
965 
966  unwind_protect frame;
967 
968  std::string file = sys::file_ops::concat (dir, script_file);
969 
970  sys::file_stat fs (file);
971 
972  if (fs.exists ())
973  source_file (file, "base");
974  }
975 
976  // FIXME: maybe we should also maintain a map to speed up this method of access.
977 
979  load_path::find_dir_info (const std::string& dir_arg) const
980  {
981  std::string dir = sys::file_ops::tilde_expand (dir_arg);
982 
983  dir = maybe_canonicalize (dir);
984 
985  auto retval = dir_info_list.cbegin ();
986 
987  while (retval != dir_info_list.cend ())
988  {
989  if (retval->dir_name == dir)
990  break;
991 
992  retval++;
993  }
994 
995  return retval;
996  }
997 
999  load_path::find_dir_info (const std::string& dir_arg)
1000  {
1001  std::string dir = sys::file_ops::tilde_expand (dir_arg);
1002 
1003  dir = maybe_canonicalize (dir);
1004 
1005  auto retval = dir_info_list.begin ();
1006 
1007  while (retval != dir_info_list.end ())
1008  {
1009  if (retval->dir_name == dir)
1010  break;
1011 
1012  retval++;
1013  }
1014 
1015  return retval;
1016  }
1017 
1018  bool
1019  load_path::contains (const std::string& dir) const
1020  {
1021  return find_dir_info (dir) != dir_info_list.end ();
1022  }
1023 
1024  void
1026  {
1027  if (dir_info_list.size () > 1)
1028  {
1029  dir_info di = *i;
1030 
1031  dir_info_list.erase (i);
1032 
1033  if (at_end)
1034  dir_info_list.push_back (di);
1035  else
1036  dir_info_list.push_front (di);
1037 
1038  move (di, at_end);
1039  }
1040  }
1041 
1042  void
1043  load_path::move (const dir_info& di, bool at_end, const std::string& pname)
1044  {
1045  package_info& l = get_package (pname);
1046 
1047  l.move (di, at_end);
1048 
1049  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
1050 
1051  for (const auto& pkg_di : package_dir_map)
1052  {
1053  std::string full_name = pkg_di.first;
1054 
1055  if (! pname.empty ())
1056  full_name = pname + '.' + full_name;
1057 
1058  move (pkg_di.second, at_end, full_name);
1059  }
1060  }
1061 
1062  void
1063  load_path::add (const std::string& dir_arg, bool at_end, bool warn)
1064  {
1065  size_t len = dir_arg.length ();
1066 
1067  if (len > 1 && dir_arg.substr (len-2) == "//")
1068  warning_with_id ("Octave:recursive-path-search",
1069  "trailing '//' is no longer special in search path elements");
1070 
1071  std::string dir = sys::file_ops::tilde_expand (dir_arg);
1072 
1073  dir = strip_trailing_separators (dir);
1074 
1075  dir = maybe_canonicalize (dir);
1076 
1077  auto i = find_dir_info (dir);
1078 
1079  if (i != dir_info_list.end ())
1080  move (i, at_end);
1081  else
1082  {
1083  sys::file_stat fs (dir);
1084 
1085  if (fs)
1086  {
1087  if (fs.is_dir ())
1088  {
1089  dir_info di (dir);
1090 
1091  if (at_end)
1092  dir_info_list.push_back (di);
1093  else
1094  dir_info_list.push_front (di);
1095 
1096  add (di, at_end);
1097 
1098  if (add_hook)
1099  add_hook (dir);
1100  }
1101  else if (warn)
1102  warning ("addpath: %s: not a directory", dir_arg.c_str ());
1103  }
1104  else if (warn)
1105  {
1106  std::string msg = fs.error ();
1107  warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
1108  }
1109  }
1110 
1111  // FIXME: is there a better way to do this?
1112 
1113  i = find_dir_info (".");
1114 
1115  if (i != dir_info_list.end ())
1116  move (i, false);
1117  }
1118 
1119  void
1120  load_path::remove (const dir_info& di, const std::string& pname)
1121  {
1122  package_info& l = get_package (pname);
1123 
1124  l.remove (di);
1125 
1126  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
1127 
1128  for (const auto& pkg_di : package_dir_map)
1129  {
1130  std::string full_name = pkg_di.first;
1131 
1132  if (! pname.empty ())
1133  full_name = pname + '.' + full_name;
1134 
1135  remove (pkg_di.second, full_name);
1136  }
1137  }
1138 
1139  bool
1140  load_path::is_package (const std::string& name) const
1141  {
1142  for (const auto& di : dir_info_list)
1143  {
1144  if (di.is_package (name))
1145  return true;
1146  }
1147 
1148  return false;
1149  }
1150 
1151  void
1152  load_path::add (const dir_info& di, bool at_end,
1153  const std::string& pname, bool updating) const
1154  {
1155  package_info& l = get_package (pname);
1156 
1157  l.add (di, at_end, updating);
1158 
1159  dir_info::package_dir_map_type package_dir_map = di.package_dir_map;
1160 
1161  for (const auto& pkg_di : package_dir_map)
1162  {
1163  std::string full_name = pkg_di.first;
1164 
1165  if (! pname.empty ())
1166  full_name = pname + '.' + full_name;
1167 
1168  add (pkg_di.second, at_end, full_name);
1169  }
1170  }
1171 
1174  {
1175  octave_idx_type n = lst.size ();
1176 
1178 
1179  octave_idx_type count = 0;
1180 
1181  for (const auto& nm_typ : lst)
1182  {
1183  std::string nm = nm_typ.first;
1184 
1185  int types = nm_typ.second;
1186 
1187  if (types & load_path::OCT_FILE)
1188  nm += ".oct";
1189  else if (types & load_path::MEX_FILE)
1190  nm += ".mex";
1191  else
1192  nm += ".m";
1193 
1194  retval[count++] = nm;
1195  }
1196 
1197  return retval;
1198  }
1199 
1201  get_fcn_files (const std::string& d)
1202  {
1204 
1205  string_vector flist;
1206  std::string msg;
1207 
1208  if (! sys::get_dirlist (d, flist, msg))
1209  warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
1210  else
1211  {
1212  octave_idx_type len = flist.numel ();
1213 
1214  for (octave_idx_type i = 0; i < len; i++)
1215  {
1216  std::string fname = flist[i];
1217 
1218  size_t pos = fname.rfind ('.');
1219 
1220  if (pos != std::string::npos)
1221  {
1222  std::string base = fname.substr (0, pos);
1223  std::string ext = fname.substr (pos);
1224 
1225  if (valid_identifier (base))
1226  {
1227  int t = 0;
1228 
1229  if (ext == ".m")
1230  t = load_path::M_FILE;
1231  else if (ext == ".oct")
1232  t = load_path::OCT_FILE;
1233  else if (ext == ".mex")
1234  t = load_path::MEX_FILE;
1235 
1236  if (t)
1237  {
1239  = retval.find (base);
1240 
1241  if (p == retval.end ())
1242  retval[base] = t;
1243  else
1244  p->second |= t;
1245  }
1246  }
1247  }
1248  }
1249  }
1250 
1251  return retval;
1252  }
1253 
1254  bool
1256  {
1257  sys::file_stat fs (dir_name);
1258 
1259  if (! fs)
1260  {
1261  std::string msg = fs.error ();
1262  warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
1263  return false;
1264  }
1265 
1266  sys::file_stat pfs (sys::file_ops::concat (dir_name, "private"));
1267  bool has_private_dir = pfs && pfs.is_dir ();
1268 
1269  if (is_relative)
1270  {
1271  try
1272  {
1273  std::string abs_name = sys::canonicalize_file_name (dir_name);
1274 
1275  const_abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
1276 
1277  if (p != abs_dir_cache.end ())
1278  {
1279  // The directory is in the cache of all directories we have
1280  // visited (indexed by absolute name). If it is out of date,
1281  // initialize it. Otherwise, copy the info from the cache.
1282  // By doing that, we avoid unnecessary calls to stat that can
1283  // slow things down tremendously for large directories.
1284  const dir_info& di = p->second;
1285 
1286  if ((fs.mtime () + fs.time_resolution ()
1287  > di.dir_time_last_checked)
1288  || (has_private_dir
1289  && (pfs.mtime () + pfs.time_resolution ()
1291  initialize ();
1292  else
1293  {
1294  // Copy over info from cache, but leave dir_name and
1295  // is_relative unmodified.
1297  dir_mtime = di.dir_mtime;
1299  all_files = di.all_files;
1300  fcn_files = di.fcn_files;
1304  }
1305  }
1306  else
1307  {
1308  // We haven't seen this directory before.
1309  initialize ();
1310  }
1311  }
1312  catch (const execution_exception& ee)
1313  {
1314  // Skip updating if we don't know where we are, but don't
1315  // treat it as an error.
1316 
1317  interpreter& interp
1318  = __get_interpreter__ ("load_path::dir_info::update");
1319 
1320  interp.recover_from_exception ();
1321  }
1322  }
1323  // Absolute path, check timestamp to see whether it requires re-caching
1324  else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked
1325  || (has_private_dir
1326  && (pfs.mtime () + pfs.time_resolution ()
1328  initialize ();
1329 
1330  return true;
1331  }
1332 
1333  bool
1334  load_path::dir_info::is_package (const std::string& name) const
1335  {
1336  size_t pos = name.find ('.');
1337 
1338  if (pos == std::string::npos)
1339  return package_dir_map.find (name) != package_dir_map.end ();
1340  else
1341  {
1342  std::string name_head = name.substr (0, pos);
1343  std::string name_tail = name.substr (pos + 1);
1344 
1345  const_package_dir_map_iterator it = package_dir_map.find (name_head);
1346 
1347  if (it != package_dir_map.end ())
1348  return it->second.is_package (name_tail);
1349  else
1350  return false;
1351  }
1352  }
1353 
1354  void
1356  {
1357  is_relative = ! sys::env::absolute_pathname (dir_name);
1358 
1359  dir_time_last_checked = sys::time (static_cast<time_t> (0));
1360 
1361  sys::file_stat fs (dir_name);
1362 
1363  if (fs)
1364  {
1365  method_file_map.clear ();
1366  package_dir_map.clear ();
1367 
1368  dir_mtime = fs.mtime ();
1369  dir_time_last_checked = sys::time ();
1370 
1371  get_file_list (dir_name);
1372 
1373  try
1374  {
1375  abs_dir_name = sys::canonicalize_file_name (dir_name);
1376 
1377  // FIXME: nothing is ever removed from this cache of
1378  // directory information, so there could be some resource
1379  // problems. Perhaps it should be pruned from time to time.
1380 
1381  abs_dir_cache[abs_dir_name] = *this;
1382  }
1383  catch (const execution_exception&)
1384  {
1385  // Skip updating if we don't know where we are but don't treat
1386  // it as an error.
1387 
1388  interpreter& interp
1389  = __get_interpreter__ ("load_path::dir_info::initialize");
1390 
1391  interp.recover_from_exception ();
1392  }
1393  }
1394  else
1395  {
1396  std::string msg = fs.error ();
1397  warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
1398  }
1399  }
1400 
1401  void
1403  {
1404  string_vector flist;
1405  std::string msg;
1406 
1407  if (! sys::get_dirlist (d, flist, msg))
1408  {
1409  warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
1410  return;
1411  }
1412 
1413  octave_idx_type len = flist.numel ();
1414 
1415  all_files.resize (len);
1416  fcn_files.resize (len);
1417 
1418  octave_idx_type all_files_count = 0;
1419  octave_idx_type fcn_files_count = 0;
1420 
1421  for (octave_idx_type i = 0; i < len; i++)
1422  {
1423  std::string fname = flist[i];
1424 
1425  std::string full_name = sys::file_ops::concat (d, fname);
1426 
1427  sys::file_stat fs (full_name);
1428 
1429  if (fs)
1430  {
1431  if (fs.is_dir ())
1432  {
1433  if (fname == "private")
1434  get_private_file_map (full_name);
1435  else if (fname[0] == '@')
1436  get_method_file_map (full_name, fname.substr (1));
1437  else if (fname[0] == '+')
1438  get_package_dir (full_name, fname.substr (1));
1439  }
1440  else
1441  {
1442  all_files[all_files_count++] = fname;
1443 
1444  size_t pos = fname.rfind ('.');
1445 
1446  if (pos != std::string::npos)
1447  {
1448  std::string ext = fname.substr (pos);
1449 
1450  if (ext == ".m" || ext == ".oct" || ext == ".mex")
1451  {
1452  std::string base = fname.substr (0, pos);
1453 
1454  if (valid_identifier (base))
1455  fcn_files[fcn_files_count++] = fname;
1456  }
1457  }
1458  }
1459  }
1460  }
1461 
1462  all_files.resize (all_files_count);
1463  fcn_files.resize (fcn_files_count);
1464  }
1465 
1466  void
1468  {
1469  private_file_map = get_fcn_files (d);
1470  }
1471 
1472  void
1474  const std::string& class_name)
1475  {
1476  method_file_map[class_name].method_file_map = get_fcn_files (d);
1477 
1478  std::string pd = sys::file_ops::concat (d, "private");
1479 
1480  sys::file_stat fs (pd);
1481 
1482  if (fs && fs.is_dir ())
1483  method_file_map[class_name].private_file_map = get_fcn_files (pd);
1484  }
1485 
1486  void
1488  const std::string& package_name)
1489  {
1490  package_dir_map[package_name] = dir_info (d);
1491  }
1492 
1493  void
1494  load_path::package_info::move (const dir_info& di, bool at_end)
1495  {
1496  std::string dir_name = di.abs_dir_name;
1497 
1498  auto s = std::find (dir_list.begin (), dir_list.end (), dir_name);
1499 
1500  if (s != dir_list.end ())
1501  {
1502  dir_list.erase (s);
1503 
1504  if (at_end)
1505  dir_list.push_back (dir_name);
1506  else
1507  dir_list.push_front (dir_name);
1508  }
1509 
1510  move_fcn_map (dir_name, di.fcn_files, at_end);
1511 
1512  // No need to move elements of private function map.
1513 
1514  move_method_map (dir_name, at_end);
1515  }
1516 
1517  void
1519  {
1520  std::string dir = di.abs_dir_name;
1521 
1522  string_vector fcn_files = di.fcn_files;
1523 
1524  dir_list.remove (dir);
1525 
1526  remove_fcn_map (dir, fcn_files);
1527 
1528  remove_private_fcn_map (dir);
1529 
1530  remove_method_map (dir);
1531  }
1532 
1533  void
1534  load_path::package_info::display (std::ostream& os) const
1535  {
1536  os << "*** package_info: "
1537  << (m_package_name.empty () ? "<top-level>" : m_package_name)
1538  << "\n\n";
1539 
1540  for (const auto& dir : dir_list)
1541  os << dir << "\n";
1542  os << "\n";
1543 
1544  for (const auto& dir_fnlst : private_fcn_map)
1545  {
1546  os << "\n*** private functions in "
1547  << sys::file_ops::concat (dir_fnlst.first, "private")
1548  << ":\n\n";
1549 
1550  print_fcn_list (os, dir_fnlst.second);
1551  }
1552 
1553 #if defined (DEBUG_LOAD_PATH)
1554 
1555  for (const auto& nm_filst : fcn_map)
1556  {
1557  os << nm_filst.first << ":\n";
1558 
1559  const file_info_list_type& file_info_list = nm_filst.second;
1560 
1561  for (const auto& finfo : file_info_list)
1562  {
1563  os << " " << finfo.dir_name << " (";
1564 
1565  print_types (os, finfo.types);
1566 
1567  os << ")\n";
1568  }
1569  }
1570 
1571  for (const auto& cls_fnmap : method_map)
1572  {
1573  os << "CLASS " << cls_fnmap.first << ":\n";
1574 
1575  const fcn_map_type& fm = cls_fnmap.second;
1576 
1577  for (const auto& nm_fnlst : fcn_map)
1578  {
1579  os << " " << nm_fnlst.first << ":\n";
1580 
1581  const file_info_list_type& file_info_list = nm_fnlst.second;
1582 
1583  for (const auto& finfo : file_info_list)
1584  {
1585  os << " " << finfo.dir_name << " (";
1586 
1587  print_types (os, finfo.types);
1588 
1589  os << ")\n";
1590  }
1591  }
1592  }
1593 
1594  os << "\n";
1595 
1596 #endif
1597  }
1598 
1599  std::string
1600  load_path::package_info::find_fcn (const std::string& fcn,
1601  std::string& dir_name,
1602  int type) const
1603  {
1604  std::string retval;
1605 
1606  // update ();
1607 
1608  if (fcn.length () > 0 && fcn[0] == '@')
1609  {
1610  size_t pos = fcn.find ('/');
1611 
1612  if (pos != std::string::npos)
1613  {
1614  std::string class_name = fcn.substr (1, pos-1);
1615  std::string meth = fcn.substr (pos+1);
1616 
1617  retval = find_method (class_name, meth, dir_name);
1618  }
1619  else
1620  retval = "";
1621  }
1622  else
1623  {
1624  dir_name = "";
1625 
1626  const_fcn_map_iterator p = fcn_map.find (fcn);
1627 
1628  if (p != fcn_map.end ())
1629  {
1630  const file_info_list_type& file_info_list = p->second;
1631 
1632  for (const auto& fi : file_info_list)
1633  {
1634  retval = sys::file_ops::concat (fi.dir_name, fcn);
1635 
1636  if (check_file_type (retval, type, fi.types,
1637  fcn, "load_path::find_fcn"))
1638  {
1639  dir_name = fi.dir_name;
1640  break;
1641  }
1642  else
1643  retval = "";
1644  }
1645  }
1646  }
1647 
1648  return retval;
1649  }
1650 
1651  std::string
1653  const std::string& fcn,
1654  int type) const
1655  {
1656  std::string retval;
1657 
1658  // update ();
1659 
1660  const_private_fcn_map_iterator q = private_fcn_map.find (dir);
1661 
1662  if (q != private_fcn_map.end ())
1663  {
1664  const dir_info::fcn_file_map_type& fcn_file_map = q->second;
1665 
1666  dir_info::const_fcn_file_map_iterator p = fcn_file_map.find (fcn);
1667 
1668  if (p != fcn_file_map.end ())
1669  {
1670  std::string fname
1671  = sys::file_ops::concat (sys::file_ops::concat (dir, "private"), fcn);
1672 
1673  if (check_file_type (fname, type, p->second, fcn,
1674  "load_path::find_private_fcn"))
1675  retval = fname;
1676  }
1677  }
1678 
1679  return retval;
1680  }
1681 
1682  std::string
1683  load_path::package_info::find_method (const std::string& class_name,
1684  const std::string& meth,
1685  std::string& dir_name,
1686  int type) const
1687  {
1688  std::string retval;
1689 
1690  // update ();
1691 
1692  dir_name = "";
1693 
1694  const_method_map_iterator q = method_map.find (class_name);
1695 
1696  if (q != method_map.end ())
1697  {
1698  const fcn_map_type& m = q->second;
1699 
1700  const_fcn_map_iterator p = m.find (meth);
1701 
1702  if (p != m.end ())
1703  {
1704  const file_info_list_type& file_info_list = p->second;
1705 
1706  for (const auto& fi : file_info_list)
1707  {
1708  retval = sys::file_ops::concat (fi.dir_name, meth);
1709 
1710  bool found = check_file_type (retval, type, fi.types,
1711  meth, "load_path::find_method");
1712 
1713  if (found)
1714  {
1715  dir_name = fi.dir_name;
1716  break;
1717  }
1718  else
1719  retval = "";
1720  }
1721  }
1722  }
1723 
1724  return retval;
1725  }
1726 
1727  std::list<std::string>
1728  load_path::package_info::methods (const std::string& class_name) const
1729  {
1730  std::list<std::string> retval;
1731 
1732  // update ();
1733 
1734  const_method_map_iterator mtd_map_it = method_map.find (class_name);
1735 
1736  if (mtd_map_it != method_map.end ())
1737  {
1738  for (const auto& nm_filst : mtd_map_it->second)
1739  retval.push_back (nm_filst.first);
1740  }
1741 
1742  if (! retval.empty ())
1743  retval.sort ();
1744 
1745  return retval;
1746  }
1747 
1748  void
1749  load_path::package_info::overloads (const std::string& meth,
1750  std::list<std::string>& l) const
1751  {
1752  for (const auto& cls_fnmap : method_map)
1753  {
1754  const fcn_map_type& m = cls_fnmap.second;
1755 
1756  if (m.find (meth) != m.end ())
1757  {
1758  std::string class_name = cls_fnmap.first;
1759 
1760  if (! m_package_name.empty ())
1761  class_name = m_package_name + '.' + class_name;
1762 
1763  l.push_back (class_name);
1764  }
1765  }
1766  }
1767 
1770  {
1771  size_t len = fcn_map.size ();
1772 
1774 
1775  octave_idx_type count = 0;
1776 
1777  for (const auto& nm_filst : fcn_map)
1778  retval[count++] = nm_filst.first;
1779 
1780  return retval;
1781  }
1782 
1783  void
1785  bool at_end, bool updating)
1786  {
1787  std::string dir_name = di.abs_dir_name;
1788 
1789  string_vector fcn_files = di.fcn_files;
1790 
1791  octave_idx_type len = fcn_files.numel ();
1792 
1793  for (octave_idx_type i = 0; i < len; i++)
1794  {
1795  std::string fname = fcn_files[i];
1796 
1797  std::string ext;
1798  std::string base = fname;
1799 
1800  size_t pos = fname.rfind ('.');
1801 
1802  if (pos != std::string::npos)
1803  {
1804  base = fname.substr (0, pos);
1805  ext = fname.substr (pos);
1806  }
1807 
1808  file_info_list_type& file_info_list = fcn_map[base];
1809 
1810  auto p = file_info_list.begin ();
1811 
1812  while (p != file_info_list.end ())
1813  {
1814  if (p->dir_name == dir_name)
1815  break;
1816 
1817  p++;
1818  }
1819 
1820  int t = 0;
1821  if (ext == ".m")
1822  t = load_path::M_FILE;
1823  else if (ext == ".oct")
1824  t = load_path::OCT_FILE;
1825  else if (ext == ".mex")
1826  t = load_path::MEX_FILE;
1827 
1828  if (p == file_info_list.end ())
1829  {
1830  // Warn if a built-in or library function is being shadowed,
1831  // but not if we are just updating (rehashing) the list.
1832 
1833  if (! updating)
1834  {
1835  if (file_info_list.empty ())
1836  {
1837  symbol_table& symtab
1838  = __get_symbol_table__ ("load_path::package_info::add_to_fcn_map");
1839 
1840  if (symtab.is_built_in_function_name (base))
1841  {
1842  std::string fcn_path = sys::file_ops::concat (dir_name, fname);
1843 
1844  warning_with_id ("Octave:shadowed-function",
1845  "function %s shadows a built-in function",
1846  fcn_path.c_str ());
1847  }
1848  }
1849  else if (! at_end)
1850  {
1851  file_info& old = file_info_list.front ();
1852 
1853  // FIXME: do we need to be more careful about the
1854  // way we look for old.dir_name in sys_path to avoid
1855  // partial matches?
1856 
1857  // Don't warn about Contents.m files since we expect
1858  // more than one to exist in the load path.
1859 
1860  if (fname != "Contents.m"
1861  && sys_path.find (old.dir_name) != std::string::npos
1862  && in_path_list (sys_path, old.dir_name))
1863  {
1864  std::string fcn_path = sys::file_ops::concat (dir_name, fname);
1865 
1866  warning_with_id ("Octave:shadowed-function",
1867  "function %s shadows a core library function",
1868  fcn_path.c_str ());
1869  }
1870  }
1871  }
1872 
1873  file_info fi (dir_name, t);
1874 
1875  if (at_end)
1876  file_info_list.push_back (fi);
1877  else
1878  file_info_list.push_front (fi);
1879  }
1880  else
1881  {
1882  file_info& fi = *p;
1883 
1884  fi.types |= t;
1885  }
1886  }
1887  }
1888 
1889  void
1891  {
1892  dir_info::fcn_file_map_type private_file_map = di.private_file_map;
1893 
1894  if (! private_file_map.empty ())
1895  private_fcn_map[di.abs_dir_name] = private_file_map;
1896  }
1897 
1898  void
1900  {
1901  std::string dir_name = di.abs_dir_name;
1902 
1903  // <CLASS_NAME, CLASS_INFO>
1904  dir_info::method_file_map_type method_file_map = di.method_file_map;
1905 
1906  for (const auto& cls_ci : method_file_map)
1907  {
1908  std::string class_name = cls_ci.first;
1909 
1910  fcn_map_type& fm = method_map[class_name];
1911 
1912  std::string full_dir_name
1913  = sys::file_ops::concat (dir_name, '@' + class_name);
1914 
1915  const dir_info::class_info& ci = cls_ci.second;
1916 
1917  // <FCN_NAME, TYPES>
1919 
1920  for (const auto& nm_typ : m)
1921  {
1922  std::string base = nm_typ.first;
1923  int types = nm_typ.second;
1924 
1925  file_info_list_type& file_info_list = fm[base];
1926 
1927  auto p2 = file_info_list.begin ();
1928  while (p2 != file_info_list.end ())
1929  {
1930  if (p2->dir_name == full_dir_name)
1931  break;
1932 
1933  p2++;
1934  }
1935 
1936  if (p2 == file_info_list.end ())
1937  {
1938  file_info fi (full_dir_name, types);
1939 
1940  if (at_end)
1941  file_info_list.push_back (fi);
1942  else
1943  file_info_list.push_front (fi);
1944  }
1945  else
1946  {
1947  // FIXME: is this possible?
1948  file_info& fi = *p2;
1949 
1950  fi.types = types;
1951  }
1952  }
1953 
1954  // <FCN_NAME, TYPES>
1955  dir_info::fcn_file_map_type private_file_map = ci.private_file_map;
1956 
1957  if (! private_file_map.empty ())
1958  private_fcn_map[full_dir_name] = private_file_map;
1959  }
1960  }
1961 
1962  void
1963  load_path::package_info::move_fcn_map (const std::string& dir_name,
1964  const string_vector& fcn_files, bool at_end)
1965  {
1966  octave_idx_type len = fcn_files.numel ();
1967 
1968  for (octave_idx_type k = 0; k < len; k++)
1969  {
1970  std::string fname = fcn_files[k];
1971 
1972  std::string ext;
1973  std::string base = fname;
1974 
1975  size_t pos = fname.rfind ('.');
1976 
1977  if (pos != std::string::npos)
1978  {
1979  base = fname.substr (0, pos);
1980  ext = fname.substr (pos);
1981  }
1982 
1983  file_info_list_type& file_info_list = fcn_map[base];
1984 
1985  if (file_info_list.size () == 1)
1986  continue;
1987  else
1988  {
1989  for (auto fi_it = file_info_list.begin ();
1990  fi_it != file_info_list.end ();
1991  fi_it++)
1992  {
1993  if (fi_it->dir_name == dir_name)
1994  {
1995  file_info fi_tmp = *fi_it;
1996 
1997  file_info_list.erase (fi_it);
1998 
1999  if (at_end)
2000  file_info_list.push_back (fi_tmp);
2001  else
2002  file_info_list.push_front (fi_tmp);
2003 
2004  break;
2005  }
2006  }
2007  }
2008  }
2009  }
2010 
2011  void
2012  load_path::package_info::move_method_map (const std::string& dir_name,
2013  bool at_end)
2014  {
2015  for (auto& cls_fnmap : method_map)
2016  {
2017  std::string class_name = cls_fnmap.first;
2018 
2019  fcn_map_type& fn_map = cls_fnmap.second;
2020 
2021  std::string full_dir_name
2022  = sys::file_ops::concat (dir_name, '@' + class_name);
2023 
2024  for (auto& nm_filst : fn_map)
2025  {
2026  file_info_list_type& file_info_list = nm_filst.second;
2027 
2028  if (file_info_list.size () == 1)
2029  continue;
2030  else
2031  {
2032  for (auto fi_it = file_info_list.begin ();
2033  fi_it != file_info_list.end (); fi_it++)
2034  {
2035  if (fi_it->dir_name == full_dir_name)
2036  {
2037  file_info fi_tmp = *fi_it;
2038 
2039  file_info_list.erase (fi_it);
2040 
2041  if (at_end)
2042  file_info_list.push_back (fi_tmp);
2043  else
2044  file_info_list.push_front (fi_tmp);
2045 
2046  break;
2047  }
2048  }
2049  }
2050  }
2051  }
2052  }
2053 
2054  void
2056  const string_vector& fcn_files)
2057  {
2058  octave_idx_type len = fcn_files.numel ();
2059 
2060  for (octave_idx_type k = 0; k < len; k++)
2061  {
2062  std::string fname = fcn_files[k];
2063 
2064  std::string ext;
2065  std::string base = fname;
2066 
2067  size_t pos = fname.rfind ('.');
2068 
2069  if (pos != std::string::npos)
2070  {
2071  base = fname.substr (0, pos);
2072  ext = fname.substr (pos);
2073  }
2074 
2075  file_info_list_type& file_info_list = fcn_map[base];
2076 
2077  for (auto fi_it = file_info_list.begin ();
2078  fi_it != file_info_list.end ();
2079  fi_it++)
2080  {
2081  if (fi_it->dir_name == dir)
2082  {
2083  file_info_list.erase (fi_it);
2084 
2085  if (file_info_list.empty ())
2086  fcn_map.erase (fname);
2087 
2088  break;
2089  }
2090  }
2091  }
2092  }
2093 
2094  void
2096  {
2097  auto p = private_fcn_map.find (dir);
2098 
2099  if (p != private_fcn_map.end ())
2100  private_fcn_map.erase (p);
2101  }
2102 
2103  void
2105  {
2106  for (auto& cls_fnmap : method_map)
2107  {
2108  std::string class_name = cls_fnmap.first;
2109 
2110  fcn_map_type& fn_map = cls_fnmap.second;
2111 
2112  std::string full_dir_name
2113  = sys::file_ops::concat (dir, '@' + class_name);
2114 
2115  for (auto& nm_filst : fn_map)
2116  {
2117  file_info_list_type& file_info_list = nm_filst.second;
2118 
2119  if (file_info_list.size () == 1)
2120  continue;
2121  else
2122  {
2123  for (auto fi_it = file_info_list.begin ();
2124  fi_it != file_info_list.end (); fi_it++)
2125  {
2126  if (fi_it->dir_name == full_dir_name)
2127  {
2128  file_info_list.erase (fi_it);
2129  // FIXME: if there are no other elements, we
2130  // should remove this element of fn_map but calling
2131  // erase here would invalidate the iterator fi_it.
2132 
2133  break;
2134  }
2135  }
2136  }
2137  }
2138  }
2139  }
2140 
2141  bool
2143  int possible_types,
2144  const std::string& fcn,
2145  const char *who) const
2146  {
2147  bool retval = false;
2148 
2149  if (type == load_path::OCT_FILE)
2150  {
2151  if ((type & possible_types) == load_path::OCT_FILE)
2152  {
2153  fname += ".oct";
2154  retval = true;
2155  }
2156  }
2157  else if (type == load_path::M_FILE)
2158  {
2159  if ((type & possible_types) == load_path::M_FILE)
2160  {
2161  fname += ".m";
2162  retval = true;
2163  }
2164  }
2165  else if (type == load_path::MEX_FILE)
2166  {
2167  if ((type & possible_types) == load_path::MEX_FILE)
2168  {
2169  fname += ".mex";
2170  retval = true;
2171  }
2172  }
2173  else if (type == (load_path::M_FILE | load_path::OCT_FILE))
2174  {
2175  if (possible_types & load_path::OCT_FILE)
2176  {
2177  fname += ".oct";
2178  retval = true;
2179  }
2180  else if (possible_types & load_path::M_FILE)
2181  {
2182  fname += ".m";
2183  retval = true;
2184  }
2185  }
2186  else if (type == (load_path::M_FILE | load_path::MEX_FILE))
2187  {
2188  if (possible_types & load_path::MEX_FILE)
2189  {
2190  fname += ".mex";
2191  retval = true;
2192  }
2193  else if (possible_types & load_path::M_FILE)
2194  {
2195  fname += ".m";
2196  retval = true;
2197  }
2198  }
2200  {
2201  if (possible_types & load_path::OCT_FILE)
2202  {
2203  fname += ".oct";
2204  retval = true;
2205  }
2206  else if (possible_types & load_path::MEX_FILE)
2207  {
2208  fname += ".mex";
2209  retval = true;
2210  }
2211  }
2214  {
2215  if (possible_types & load_path::OCT_FILE)
2216  {
2217  fname += ".oct";
2218  retval = true;
2219  }
2220  else if (possible_types & load_path::MEX_FILE)
2221  {
2222  fname += ".mex";
2223  retval = true;
2224  }
2225  else if (possible_types & load_path::M_FILE)
2226  {
2227  fname += ".m";
2228  retval = true;
2229  }
2230  }
2231  else
2232  error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type);
2233 
2234  return retval;
2235  }
2236 
2237  void
2238  load_path::package_info::print_types (std::ostream& os, int types) const
2239  {
2240  bool printed_type = false;
2241 
2242  if (types & load_path::OCT_FILE)
2243  {
2244  os << "oct";
2245  printed_type = true;
2246  }
2247 
2248  if (types & load_path::MEX_FILE)
2249  {
2250  if (printed_type)
2251  os << '|';
2252  os << "mex";
2253  printed_type = true;
2254  }
2255 
2256  if (types & load_path::M_FILE)
2257  {
2258  if (printed_type)
2259  os << '|';
2260  os << 'm';
2261  printed_type = true;
2262  }
2263  }
2264 
2265  void
2267  const load_path::dir_info::fcn_file_map_type& lst) const
2268  {
2269  for (const auto& nm_typ : lst)
2270  {
2271  os << " " << nm_typ.first << " (";
2272 
2273  print_types (os, nm_typ.second);
2274 
2275  os << ")\n";
2276  }
2277  }
2278 
2279  std::string
2280  genpath (const std::string& dirname, const string_vector& skip)
2281  {
2282  std::string retval;
2283  string_vector dirlist;
2284  std::string msg;
2285 
2286  if (! sys::get_dirlist (dirname, dirlist, msg))
2287  return retval;
2288 
2289  retval = dirname;
2290 
2291  dirlist = dirlist.sort (false);
2292 
2293  octave_idx_type len = dirlist.numel ();
2294 
2295  for (octave_idx_type i = 0; i < len; i++)
2296  {
2297  std::string elt = dirlist[i];
2298 
2299  bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'
2300  || elt[0] == '+');
2301 
2302  if (! skip_p)
2303  {
2304  for (octave_idx_type j = 0; j < skip.numel (); j++)
2305  {
2306  skip_p = (elt == skip[j]);
2307  if (skip_p)
2308  break;
2309  }
2310 
2311  if (! skip_p)
2312  {
2313  std::string nm = sys::file_ops::concat (dirname, elt);
2314 
2315  sys::file_stat fs (nm);
2316 
2317  if (fs && fs.is_dir ())
2318  retval += directory_path::path_sep_str () + genpath (nm, skip);
2319  }
2320  }
2321  }
2322 
2323  return retval;
2324  }
2325 }
2326 
2327 DEFUN (genpath, args, ,
2328  doc: /* -*- texinfo -*-
2329 @deftypefn {} {} genpath (@var{dir})
2330 @deftypefnx {} {} genpath (@var{dir}, @var{skip}, @dots{})
2331 Return a path constructed from @var{dir} and all its subdirectories.
2332 
2333 The path does not include package directories (beginning with @samp{+}),
2334 old-style class directories (beginning with @samp{@@}), @file{private}
2335 directories, or any subdirectories of these types.
2336 
2337 If additional string parameters are given, the resulting path will exclude
2338 directories with those names.
2339 @seealso{path, addpath}
2340 @end deftypefn */)
2341 {
2342  int nargin = args.length ();
2343 
2344  if (nargin == 0)
2345  print_usage ();
2346 
2348 
2349  if (nargin == 1)
2350  {
2351  std::string dirname = args(0).xstring_value ("genpath: DIR must be a string");
2352 
2354  }
2355  else
2356  {
2357  std::string dirname = args(0).xstring_value ("genpath: all arguments must be strings");
2358 
2359  string_vector skip (nargin - 1);
2360 
2361  for (octave_idx_type i = 1; i < nargin; i++)
2362  skip[i-1] = args(i).xstring_value ("genpath: all arguments must be strings");
2363 
2364  retval = octave::genpath (dirname, skip);
2365  }
2366 
2367  return retval;
2368 }
2369 
2370 DEFUN (rehash, , ,
2371  doc: /* -*- texinfo -*-
2372 @deftypefn {} {} rehash ()
2373 Reinitialize Octave's load path directory cache.
2374 @end deftypefn */)
2375 {
2377 
2378  return ovl ();
2379 }
2380 
2381 DEFMETHOD (command_line_path, interp, args, ,
2382  doc: /* -*- texinfo -*-
2383 @deftypefn {} {} command_line_path ()
2384 Return the command line path variable.
2385 
2386 @seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}
2387 @end deftypefn */)
2388 {
2389  if (! args.empty ())
2390  print_usage ();
2391 
2392  octave::load_path& lp = interp.get_load_path ();
2393 
2394  return ovl (lp.get_command_line_path ());
2395 }
2396 
2397 DEFMETHOD (restoredefaultpath, interp, args, ,
2398  doc: /* -*- texinfo -*-
2399 @deftypefn {} {} restoredefaultpath ()
2400 Restore Octave's path to its initial state at startup.
2401 
2402 @seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}
2403 @end deftypefn */)
2404 {
2405  if (! args.empty ())
2406  print_usage ();
2407 
2408  octave::load_path& lp = interp.get_load_path ();
2409 
2410  lp.initialize (true);
2411 
2412  return ovl (lp.system_path ());
2413 }
2414 
2415 // Return Octave's original default list of directories in which to
2416 // search for function files. This corresponds to the path that
2417 // exists prior to running the system's octaverc file or the user's
2418 // ~/.octaverc file
2419 
2420 DEFMETHOD (__pathorig__, interp, , ,
2421  doc: /* -*- texinfo -*-
2422 @deftypefn {} {@var{val} =} __pathorig__ ()
2423 Undocumented internal function.
2424 @end deftypefn */)
2425 {
2426  octave::load_path& lp = interp.get_load_path ();
2427 
2428  return ovl (lp.system_path ());
2429 }
2430 
2431 DEFMETHOD (path, interp, args, nargout,
2432  doc: /* -*- texinfo -*-
2433 @deftypefn {} {} path ()
2434 @deftypefnx {} {@var{str} =} path ()
2435 @deftypefnx {} {@var{str} =} path (@var{path1}, @dots{})
2436 Modify or display Octave's load path.
2437 
2438 If @var{nargin} and @var{nargout} are zero, display the elements of
2439 Octave's load path in an easy to read format.
2440 
2441 If @var{nargin} is zero and nargout is greater than zero, return the
2442 current load path.
2443 
2444 If @var{nargin} is greater than zero, concatenate the arguments,
2445 separating them with @code{pathsep}. Set the internal search path
2446 to the result and return it.
2447 
2448 No checks are made for duplicate elements.
2449 @seealso{addpath, rmpath, genpath, pathdef, savepath, pathsep}
2450 @end deftypefn */)
2451 {
2452  int nargin = args.length ();
2453 
2454  string_vector argv = args.make_argv ("path");
2455 
2456  octave::load_path& lp = interp.get_load_path ();
2457 
2458  if (nargin > 0)
2459  {
2460  std::string path = argv[1];
2461 
2462  for (int i = 2; i <= nargin; i++)
2464 
2465  lp.set (path, true);
2466 
2468  }
2469 
2470  if (nargout > 0)
2471  return ovl (lp.path ());
2472  else if (nargin == 0 && nargout == 0)
2473  {
2474  octave_stdout <<
2475  "\nOctave's search path contains the following directories:\n\n";
2476 
2477  string_vector dirs = lp.dirs ();
2478 
2480 
2481  octave_stdout << "\n";
2482  }
2483 
2484  return ovl ();
2485 }
2486 
2487 DEFMETHOD (addpath, interp, args, nargout,
2488  doc: /* -*- texinfo -*-
2489 @deftypefn {} {} addpath (@var{dir1}, @dots{})
2490 @deftypefnx {} {} addpath (@var{dir1}, @dots{}, @var{option})
2491 Add named directories to the function search path.
2492 
2493 If @var{option} is @qcode{"-begin"} or 0 (the default), prepend the directory
2494 name(s) to the current path. If @var{option} is @qcode{"-end"} or 1, append
2495 the directory name(s) to the current path. Directories added to the path must
2496 exist.
2497 
2498 In addition to accepting individual directory arguments, lists of
2499 directory names separated by @code{pathsep} are also accepted. For example:
2500 
2501 @example
2502 addpath ("dir1:/dir2:~/dir3")
2503 @end example
2504 
2505 The newly added paths appear in the load path in the same order that they
2506 appear in the arguments of @code{addpath}. When extending the load path to
2507 the front, the last path in the list of arguments is added first. When
2508 extending the load path to the end, the first path in the list of arguments
2509 is added first.
2510 
2511 For each directory that is added, and that was not already in the path,
2512 @code{addpath} checks for the existence of a file named @file{PKG_ADD}
2513 (note lack of .m extension) and runs it if it exists.
2514 
2515 @seealso{path, rmpath, genpath, pathdef, savepath, pathsep}
2516 @end deftypefn */)
2517 {
2518  // Originally written by Bill Denney and Etienne Grossman.
2519  // Heavily modified and translated to C++ by jwe.
2520 
2521  int nargin = args.length ();
2522 
2523  if (nargin == 0)
2524  print_usage ();
2525 
2526  octave::load_path& lp = interp.get_load_path ();
2527 
2529 
2530  if (nargout > 0)
2531  retval = lp.path ();
2532 
2533  bool append = false;
2534 
2535  octave_value option_arg = args(nargin-1);
2536 
2537  if (option_arg.is_string ())
2538  {
2539  std::string option = option_arg.string_value ();
2540 
2541  if (option == "-end")
2542  {
2543  append = true;
2544  nargin--;
2545  }
2546  else if (option == "-begin")
2547  nargin--;
2548  }
2549  else if (option_arg.isnumeric ())
2550  {
2551  int val = option_arg.xint_value ("addpath: OPTION must be '-begin'/0 or '-end'/1");
2552 
2553  if (val == 0)
2554  nargin--;
2555  else if (val == 1)
2556  {
2557  append = true;
2558  nargin--;
2559  }
2560  else
2561  error ("addpath: OPTION must be '-begin'/0 or '-end'/1");
2562  }
2563 
2564  bool need_to_update = false;
2565 
2566  octave_value_list arglist (args.slice (0, nargin));
2567  if (! append)
2568  arglist.reverse ();
2569 
2570  for (int i = 0; i < arglist.length (); i++)
2571  {
2572  std::string arg = arglist(i).xstring_value ("addpath: all arguments must be strings");
2573 
2574  std::list<std::string> dir_elts = octave::split_path (arg);
2575 
2576  if (! append)
2577  std::reverse (dir_elts.begin (), dir_elts.end ());
2578 
2579  for (auto dir : dir_elts)
2580  {
2581  // Remove duplicate directory separators
2582  auto it_start = dir.begin ();
2583 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
2584  // In Windows, start check at second character (for UNC paths).
2585  it_start++;
2586 #endif
2587  dir.erase (std::unique
2588  (it_start, dir.end (),
2589  [] (char l, char r)
2590  {
2591  return l == r && octave::sys::file_ops::is_dir_sep (l);
2592  }),
2593  dir.end ());
2594 
2595  auto pos = dir.find_last_of (octave::sys::file_ops::dir_sep_chars ());
2596  if (pos == std::string::npos)
2597  {
2598  if (! dir.empty () && dir[0] == '+')
2599  warning_with_id ("Octave:addpath-pkg",
2600  "addpath: package directories should not be "
2601  "added to path: %s\n", dir.c_str ());
2602  }
2603  else
2604  {
2605  if (pos + 1 < dir.length () && dir[pos+1] == '+')
2606  warning_with_id ("Octave:addpath-pkg",
2607  "addpath: package directories should not be "
2608  "added to path: %s\n", dir.c_str ());
2609  }
2610 
2611  if (append)
2612  lp.append (dir, true);
2613  else
2614  lp.prepend (dir, true);
2615 
2616  need_to_update = true;
2617  }
2618  }
2619 
2620  if (need_to_update)
2622 
2623  return retval;
2624 }
2625 
2626 DEFMETHOD (rmpath, interp, args, nargout,
2627  doc: /* -*- texinfo -*-
2628 @deftypefn {} {} rmpath (@var{dir1}, @dots{})
2629 Remove @var{dir1}, @dots{} from the current function search path.
2630 
2631 In addition to accepting individual directory arguments, lists of
2632 directory names separated by @code{pathsep} are also accepted. For example:
2633 
2634 @example
2635 rmpath ("dir1:/dir2:~/dir3")
2636 @end example
2637 
2638 For each directory that is removed, @code{rmpath} checks for the
2639 existence of a file named @file{PKG_DEL} (note lack of .m extension)
2640 and runs it if it exists.
2641 
2642 @seealso{path, addpath, genpath, pathdef, savepath, pathsep}
2643 @end deftypefn */)
2644 {
2645  // Originally written by Etienne Grossmann. Heavily modified and translated
2646  // to C++ by jwe.
2647 
2648  int nargin = args.length ();
2649 
2650  if (nargin == 0)
2651  print_usage ();
2652 
2654 
2655  octave::load_path& lp = interp.get_load_path ();
2656 
2657  if (nargout > 0)
2658  retval = lp.path ();
2659 
2660  bool need_to_update = false;
2661 
2662  for (int i = 0; i < nargin; i++)
2663  {
2664  std::string arg = args(i).xstring_value ("rmpath: all arguments must be strings");
2665  std::list<std::string> dir_elts = octave::split_path (arg);
2666 
2667  for (const auto& dir : dir_elts)
2668  {
2669  //dir = regexprep (dir_elts{j}, '//+', "/");
2670  //dir = regexprep (dir, '/$', "");
2671 
2672  if (! lp.remove (dir))
2673  warning ("rmpath: %s: not found", dir.c_str ());
2674  else
2675  need_to_update = true;
2676  }
2677  }
2678 
2679  if (need_to_update)
2681 
2682  return retval;
2683 }
2684 
2685 DEFMETHOD (__dump_load_path__, interp, , ,
2686  doc: /* -*- texinfo -*-
2687 @deftypefn {} {} __dump_load_path__ ()
2688 Undocumented internal function.
2689 @end deftypefn */)
2690 {
2691  octave::load_path& lp = interp.get_load_path ();
2692 
2693  lp.display (octave_stdout);
2694 
2695  return ovl ();
2696 }
Array< T > sort(int dim=0, sortmode mode=ASCENDING) const
Size of the specified dimension.
Definition: Array.cc:1757
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:377
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
Definition: Array.cc:2225
static char path_sep_char(void)
Definition: pathsearch.cc:122
static std::string path_sep_str(void)
Definition: pathsearch.cc:127
Provides threadsafe access to octave.
int debug_cd_or_addpath_error(const std::string &file, const std::string &dir, bool addpath_option)
void update_path_dialog(void)
void recover_from_exception(void)
int chdir(const std::string &dir)
event_manager & get_event_manager(void)
Definition: interpreter.h:290
void get_package_dir(const std::string &d, const std::string &package_name)
Definition: load-path.cc:1487
void get_private_file_map(const std::string &d)
Definition: load-path.cc:1467
package_dir_map_type package_dir_map
Definition: load-path.h:295
fcn_file_map_type private_file_map
Definition: load-path.h:293
fcn_file_map_type::const_iterator const_fcn_file_map_iterator
Definition: load-path.h:225
std::map< std::string, class_info > method_file_map_type
Definition: load-path.h:254
package_dir_map_type::const_iterator const_package_dir_map_iterator
Definition: load-path.h:262
void get_file_list(const std::string &d)
Definition: load-path.cc:1402
void get_method_file_map(const std::string &d, const std::string &class_name)
Definition: load-path.cc:1473
std::map< std::string, int > fcn_file_map_type
Definition: load-path.h:223
std::map< std::string, dir_info > package_dir_map_type
Definition: load-path.h:260
bool is_package(const std::string &name) const
Definition: load-path.cc:1334
fcn_file_map_type::iterator fcn_file_map_iterator
Definition: load-path.h:226
method_file_map_type method_file_map
Definition: load-path.h:294
void add_to_private_fcn_map(const dir_info &di)
Definition: load-path.cc:1890
std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, int type=M_FILE|OCT_FILE|MEX_FILE) const
Definition: load-path.cc:1683
bool check_file_type(std::string &fname, int type, int possible_types, const std::string &fcn, const char *who) const
Definition: load-path.cc:2142
void add_to_method_map(const dir_info &di, bool at_end)
Definition: load-path.cc:1899
void move(const dir_info &di, bool at_end)
Definition: load-path.cc:1494
void display(std::ostream &out) const
Definition: load-path.cc:1534
std::string find_private_fcn(const std::string &dir, const std::string &fcn, int type=M_FILE|OCT_FILE|MEX_FILE) const
Definition: load-path.cc:1652
void add(const dir_info &di, bool at_end, bool updating)
Definition: load-path.h:420
void print_types(std::ostream &os, int types) const
Definition: load-path.cc:2238
void remove_method_map(const std::string &dir)
Definition: load-path.cc:2104
void print_fcn_list(std::ostream &os, const dir_info::fcn_file_map_type &lst) const
Definition: load-path.cc:2266
void remove_fcn_map(const std::string &dir, const string_vector &fcn_files)
Definition: load-path.cc:2055
std::string find_fcn(const std::string &fcn, std::string &dir_name, int type=M_FILE|OCT_FILE|MEX_FILE) const
Definition: load-path.cc:1600
void remove_private_fcn_map(const std::string &dir)
Definition: load-path.cc:2095
string_vector fcn_names(void) const
Definition: load-path.cc:1769
void move_method_map(const std::string &dir, bool at_end)
Definition: load-path.cc:2012
void move_fcn_map(const std::string &dir, const string_vector &fcn_files, bool at_end)
Definition: load-path.cc:1963
void add_to_fcn_map(const dir_info &di, bool at_end, bool updating)
Definition: load-path.cc:1784
void overloads(const std::string &meth, std::list< std::string > &l) const
Definition: load-path.cc:1749
std::list< std::string > methods(const std::string &class_name) const
Definition: load-path.cc:1728
void remove(const dir_info &di)
Definition: load-path.cc:1518
abs_dir_cache_type::const_iterator const_abs_dir_cache_iterator
Definition: load-path.h:362
std::string find_first_of(const string_vector &files) const
Definition: load-path.cc:687
void prepend(const std::string &dir, bool warn=false)
Definition: load-path.cc:347
static std::string sys_path
Definition: load-path.h:527
std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:79
string_vector dirs(void) const
Definition: load-path.cc:832
static const int MEX_FILE
Definition: load-path.h:214
std::string m_command_line_path
Definition: load-path.h:525
std::set< std::string > init_dirs
Definition: load-path.h:523
static const int M_FILE
Definition: load-path.h:212
package_info & get_package(const std::string &name) const
Definition: load-path.h:556
void execute_pkg_del(const std::string &dir)
Definition: load-path.cc:955
std::list< std::string > get_all_package_names(bool only_top_level=true) const
Definition: load-path.cc:524
void initialize(bool set_initial_path=false)
Definition: load-path.cc:238
string_vector find_all_first_of(const string_vector &files) const
Definition: load-path.cc:764
void add(const std::string &dir, bool at_end, bool warn)
Definition: load-path.cc:1063
bool is_package(const std::string &name) const
Definition: load-path.cc:1140
string_vector files(const std::string &dir, bool omit_exts=false) const
Definition: load-path.cc:858
bool contains_canonical(const std::string &dir_name) const
Definition: load-path.cc:418
load_path(interpreter &interp)
Definition: load-path.cc:230
std::string path(void) const
Definition: load-path.cc:892
void move(dir_info_list_iterator i, bool at_end)
Definition: load-path.cc:1025
friend dir_info::fcn_file_map_type get_fcn_files(const std::string &d)
Definition: load-path.cc:1201
std::map< std::string, dir_info > abs_dir_cache_type
Definition: load-path.h:360
string_vector find_matching_dirs(const std::string &dir) const
Definition: load-path.cc:640
string_vector get_file_list(const dir_info::fcn_file_map_type &lst) const
Definition: load-path.cc:1173
void execute_pkg_add_or_del(const std::string &dir, const std::string &script_file)
Definition: load-path.cc:960
std::list< std::string > overloads(const std::string &meth) const
Definition: load-path.cc:509
const_dir_info_list_iterator find_dir_info(const std::string &dir) const
Definition: load-path.cc:979
std::map< std::string, file_info_list_type > fcn_map_type
Definition: load-path.h:371
private_fcn_map_type::const_iterator const_private_fcn_map_iterator
Definition: load-path.h:380
std::string system_path(void) const
Definition: load-path.h:210
bool contains_file_in_dir(const std::string &file_name, const std::string &dir_name)
Definition: load-path.cc:435
dir_info_list_type dir_info_list
Definition: load-path.h:521
string_vector fcn_names(void) const
Definition: load-path.cc:886
std::string get_command_line_path(void) const
Definition: load-path.h:205
bool remove(const std::string &dir)
Definition: load-path.cc:354
std::list< std::string > dir_list(void) const
Definition: load-path.cc:847
std::string find_dir(const std::string &dir) const
Definition: load-path.cc:593
void display(std::ostream &os) const
Definition: load-path.cc:910
void update(void) const
Definition: load-path.cc:395
static abs_dir_cache_type abs_dir_cache
Definition: load-path.h:529
dir_info_list_type::const_iterator const_dir_info_list_iterator
Definition: load-path.h:357
bool contains(const std::string &dir) const
Definition: load-path.cc:1019
dir_info_list_type::iterator dir_info_list_iterator
Definition: load-path.h:358
std::string find_file(const std::string &file) const
Definition: load-path.cc:538
interpreter & m_interpreter
Definition: load-path.h:515
package_info top_level_package
Definition: load-path.h:519
void append(const std::string &dir, bool warn=false)
Definition: load-path.cc:340
method_map_type::const_iterator const_method_map_iterator
Definition: load-path.h:386
static const int OCT_FILE
Definition: load-path.h:213
std::function< void(const std::string &)> add_hook
Definition: load-path.h:531
package_map_type package_map
Definition: load-path.h:517
void clear(void)
Definition: load-path.cc:276
fcn_map_type::const_iterator const_fcn_map_iterator
Definition: load-path.h:373
std::function< void(const std::string &)> remove_hook
Definition: load-path.h:533
void execute_pkg_add(const std::string &dir)
Definition: load-path.cc:949
std::list< file_info > file_info_list_type
Definition: load-path.h:365
void set(const std::string &p, bool warn=false, bool is_init=false)
Definition: load-path.cc:286
octave_user_code * user_code(void) const
Definition: symscope.h:612
bool is_built_in_function_name(const std::string &name)
Definition: symtab.cc:67
sys::time mtime(void) const
Definition: file-stat.h:131
std::string error(void) const
Definition: file-stat.h:149
sys::time time_resolution(void) const
Definition: file-stat.h:89
bool is_reg(void) const
Definition: file-stat.cc:83
bool is_dir(void) const
Definition: file-stat.cc:65
bool exists(void) const
Definition: file-stat.h:147
static bool rooted_relative_pathname(const std::string &s)
Definition: oct-env.cc:119
static std::string base_pathname(const std::string &s)
Definition: oct-env.cc:126
static std::string getenv(const std::string &name)
Definition: oct-env.cc:271
static bool absolute_pathname(const std::string &s)
Definition: oct-env.cc:112
static std::string get_current_directory(void)
Definition: oct-env.cc:140
void stamp(void)
Definition: oct-time.cc:109
std::string dir_name(void) const
Definition: ov-fcn.h:173
octave_idx_type length(void) const
Definition: ovl.h:113
octave_value_list & reverse(void)
Definition: ovl.cc:124
bool isnumeric(void) const
Definition: ov.h:703
bool is_string(void) const
Definition: ov.h:593
std::string string_value(bool force=false) const
Definition: ov.h:927
int xint_value(const char *fmt,...) const
string_vector & sort(bool make_uniq=false)
Definition: str-vec.cc:77
void resize(octave_idx_type n, const std::string &rfv="")
Definition: str-vec.h:95
std::ostream & list_in_columns(std::ostream &, int width=0, const std::string &prefix="") const
Definition: str-vec.cc:201
octave_idx_type numel(void) const
Definition: str-vec.h:100
bool empty(void) const
Definition: str-vec.h:77
static octave_idx_type find(octave_idx_type i, octave_idx_type *pp)
Definition: colamd.cc:104
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition: defun.h:138
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void warning(const char *fmt,...)
Definition: error.cc:1050
void warning_with_id(const char *id, const char *fmt,...)
Definition: error.cc:1065
void error(const char *fmt,...)
Definition: error.cc:968
QString path
QString name
octave::sys::time Vlast_prompt_time
Definition: input.cc:83
bool octave_interpreter_ready
Definition: interpreter.cc:89
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::string local_ver_oct_file_dir(void)
Definition: defaults.cc:259
std::string local_fcn_file_dir(void)
Definition: defaults.cc:307
std::string oct_data_dir(void)
Definition: defaults.cc:323
std::string oct_file_dir(void)
Definition: defaults.cc:283
std::string local_oct_file_dir(void)
Definition: defaults.cc:275
std::string local_api_oct_file_dir(void)
Definition: defaults.cc:267
std::string local_api_fcn_file_dir(void)
Definition: defaults.cc:299
std::string fcn_file_dir(void)
Definition: defaults.cc:315
std::string local_ver_fcn_file_dir(void)
Definition: defaults.cc:291
std::string dirname(const std::string &path)
Definition: file-ops.cc:363
std::string dir_sep_str(void)
Definition: file-ops.cc:243
bool is_dir_sep(char c)
Definition: file-ops.cc:280
std::string tilde_expand(const std::string &name)
Definition: file-ops.cc:286
std::string concat(const std::string &dir, const std::string &file)
Definition: file-ops.cc:354
std::string dir_sep_chars(void)
Definition: file-ops.cc:252
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:693
bool get_dirlist(const std::string &dirname, string_vector &dirlist, std::string &msg)
Definition: lo-sysdep.cc:101
static std::string maybe_canonicalize(const std::string &dir_arg)
Definition: load-path.cc:57
static bool in_path_list(const std::string &path_list, const std::string &path)
Definition: load-path.cc:191
static std::string find_private_file(const std::string &fname)
Definition: load-path.cc:153
bool valid_identifier(const char *s)
Definition: utils.cc:77
static std::string strip_trailing_separators(const std::string &dir_arg)
Definition: load-path.cc:134
interpreter & __get_interpreter__(const std::string &who)
load_path::dir_info::fcn_file_map_type get_fcn_files(const std::string &d)
Definition: load-path.cc:1201
static void rehash_internal(void)
Definition: load-path.cc:210
event_manager & __get_event_manager__(const std::string &who)
static void maybe_add_path_elts(std::string &path, const std::string &dir)
Definition: load-path.cc:85
symbol_scope __get_current_scope__(const std::string &who)
symbol_table & __get_symbol_table__(const std::string &who)
void source_file(const std::string &file_name, const std::string &context, bool verbose, bool require_file)
Definition: oct-parse.cc:9526
static double fi[256]
Definition: randmtzig.cc:447
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:138
static std::list< std::string > split_path(const std::string &p)
Definition: load-path.cc:99
std::string genpath(const std::string &dirname, const string_vector &skip)
Definition: load-path.cc:2280
load_path & __get_load_path__(const std::string &who)
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
#define octave_stdout
Definition: pager.h:313
F77_RET_T len
Definition: xerbla.cc:61