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