Bug Summary

File:libinterp/corefcn/load-path.cc
Location:line 1574, column 7
Description:Value stored to 'printed_type' is never read

Annotated Source Code

1/*
2
3Copyright (C) 2006-2013 John W. Eaton
4Copyright (C) 2010 VZLU Prague
5
6This file is part of Octave.
7
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with Octave; see the file COPYING. If not, see
20<http://www.gnu.org/licenses/>.
21
22*/
23
24#ifdef HAVE_CONFIG_H1
25#include <config.h>
26#endif
27
28#include <algorithm>
29
30#include "dir-ops.h"
31#include "file-ops.h"
32#include "file-stat.h"
33#include "oct-env.h"
34#include "pathsearch.h"
35#include "singleton-cleanup.h"
36
37#include "defaults.h"
38#include "defun.h"
39#include "input.h"
40#include "load-path.h"
41#include "pager.h"
42#include "parse.h"
43#include "toplev.h"
44#include "unwind-prot.h"
45#include "utils.h"
46
47load_path *load_path::instance = 0;
48load_path::hook_fcn_ptr load_path::add_hook = execute_pkg_add;
49load_path::hook_fcn_ptr load_path::remove_hook = execute_pkg_del;
50std::string load_path::command_line_path;
51std::string load_path::sys_path;
52load_path::abs_dir_cache_type load_path::abs_dir_cache;
53
54void
55load_path::dir_info::update (void)
56{
57 file_stat fs (dir_name);
58
59 if (fs)
60 {
61 if (is_relative)
62 {
63 try
64 {
65 std::string abs_name = octave_env::make_absolute (dir_name);
66
67 abs_dir_cache_iterator p = abs_dir_cache.find (abs_name);
68
69 if (p != abs_dir_cache.end ())
70 {
71 // The directory is in the cache of all directories
72 // we have visited (indexed by its absolute name).
73 // If it is out of date, initialize it. Otherwise,
74 // copy the info from the cache. By doing that, we
75 // avoid unnecessary calls to stat that can slow
76 // things down tremendously for large directories.
77
78 const dir_info& di = p->second;
79
80 if (fs.mtime () + fs.time_resolution ()
81 > di.dir_time_last_checked)
82 initialize ();
83 else
84 *this = di;
85 }
86 else
87 {
88 // We haven't seen this directory before.
89
90 initialize ();
91 }
92 }
93 catch (octave_execution_exception)
94 {
95 // Skip updating if we don't know where we are, but
96 // don't treat it as an error.
97
98 error_state = 0;
99 }
100 }
101 else if (fs.mtime () + fs.time_resolution () > dir_time_last_checked)
102 initialize ();
103 }
104 else
105 {
106 std::string msg = fs.error ();
107 warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
108 }
109}
110
111void
112load_path::dir_info::initialize (void)
113{
114 is_relative = ! octave_env::absolute_pathname (dir_name);
115
116 dir_time_last_checked = octave_time (static_cast<time_t> (0));
117
118 file_stat fs (dir_name);
119
120 if (fs)
121 {
122 method_file_map.clear ();
123
124 dir_mtime = fs.mtime ();
125 dir_time_last_checked = octave_time ();
126
127 get_file_list (dir_name);
128
129 try
130 {
131 std::string abs_name = octave_env::make_absolute (dir_name);
132
133 // FIXME: nothing is ever removed from this cache of
134 // directory information, so there could be some resource
135 // problems. Perhaps it should be pruned from time to time.
136
137 abs_dir_cache[abs_name] = *this;
138 }
139 catch (octave_execution_exception)
140 {
141 // Skip updating if we don't know where we are.
142 }
143 }
144 else
145 {
146 std::string msg = fs.error ();
147 warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ());
148 }
149}
150
151void
152load_path::dir_info::get_file_list (const std::string& d)
153{
154 dir_entry dir (d);
155
156 if (dir)
157 {
158 string_vector flist = dir.read ();
159
160 octave_idx_type len = flist.length ();
161
162 all_files.resize (len);
163 fcn_files.resize (len);
164
165 octave_idx_type all_files_count = 0;
166 octave_idx_type fcn_files_count = 0;
167
168 for (octave_idx_type i = 0; i < len; i++)
169 {
170 std::string fname = flist[i];
171
172 std::string full_name = file_ops::concat (d, fname);
173
174 file_stat fs (full_name);
175
176 if (fs)
177 {
178 if (fs.is_dir ())
179 {
180 if (fname == "private")
181 get_private_file_map (full_name);
182 else if (fname[0] == '@')
183 get_method_file_map (full_name, fname.substr (1));
184 }
185 else
186 {
187 all_files[all_files_count++] = fname;
188
189 size_t pos = fname.rfind ('.');
190
191 if (pos != std::string::npos)
192 {
193 std::string ext = fname.substr (pos);
194
195 if (ext == ".m" || ext == ".oct" || ext == ".mex")
196 {
197 std::string base = fname.substr (0, pos);
198
199 if (valid_identifier (base))
200 fcn_files[fcn_files_count++] = fname;
201 }
202 }
203 }
204 }
205 }
206
207 all_files.resize (all_files_count);
208 fcn_files.resize (fcn_files_count);
209 }
210 else
211 {
212 std::string msg = dir.error ();
213 warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
214 }
215}
216
217load_path::dir_info::fcn_file_map_type
218get_fcn_files (const std::string& d)
219{
220 load_path::dir_info::fcn_file_map_type retval;
221
222 dir_entry dir (d);
223
224 if (dir)
225 {
226 string_vector flist = dir.read ();
227
228 octave_idx_type len = flist.length ();
229
230 for (octave_idx_type i = 0; i < len; i++)
231 {
232 std::string fname = flist[i];
233
234 std::string ext;
235 std::string base = fname;
236
237 size_t pos = fname.rfind ('.');
238
239 if (pos != std::string::npos)
240 {
241 base = fname.substr (0, pos);
242 ext = fname.substr (pos);
243
244 if (valid_identifier (base))
245 {
246 int t = 0;
247
248 if (ext == ".m")
249 t = load_path::M_FILE;
250 else if (ext == ".oct")
251 t = load_path::OCT_FILE;
252 else if (ext == ".mex")
253 t = load_path::MEX_FILE;
254
255 retval[base] |= t;
256 }
257 }
258 }
259 }
260 else
261 {
262 std::string msg = dir.error ();
263 warning ("load_path: %s: %s", d.c_str (), msg.c_str ());
264 }
265
266 return retval;
267}
268
269void
270load_path::dir_info::get_private_file_map (const std::string& d)
271{
272 private_file_map = get_fcn_files (d);
273}
274
275void
276load_path::dir_info::get_method_file_map (const std::string& d,
277 const std::string& class_name)
278{
279 method_file_map[class_name].method_file_map = get_fcn_files (d);
280
281 std::string pd = file_ops::concat (d, "private");
282
283 file_stat fs (pd);
284
285 if (fs && fs.is_dir ())
286 method_file_map[class_name].private_file_map = get_fcn_files (pd);
287}
288
289bool
290load_path::instance_ok (void)
291{
292 bool retval = true;
293
294 if (! instance)
295 {
296 instance = new load_path ();
297
298 if (instance)
299 singleton_cleanup_list::add (cleanup_instance);
300 }
301
302 if (! instance)
303 {
304 ::error ("unable to create load path object!");
305
306 retval = false;
307 }
308
309 return retval;
310}
311
312// FIXME: maybe we should also maintain a map to speed up this method of access.
313
314load_path::const_dir_info_list_iterator
315load_path::find_dir_info (const std::string& dir_arg) const
316{
317 std::string dir = file_ops::tilde_expand (dir_arg);
318
319 const_dir_info_list_iterator retval = dir_info_list.begin ();
320
321 while (retval != dir_info_list.end ())
322 {
323 if (retval->dir_name == dir)
324 break;
325
326 retval++;
327 }
328
329 return retval;
330}
331
332load_path::dir_info_list_iterator
333load_path::find_dir_info (const std::string& dir_arg)
334{
335 std::string dir = file_ops::tilde_expand (dir_arg);
336
337 dir_info_list_iterator retval = dir_info_list.begin ();
338
339 while (retval != dir_info_list.end ())
340 {
341 if (retval->dir_name == dir)
342 break;
343
344 retval++;
345 }
346
347 return retval;
348}
349
350bool
351load_path::contains (const std::string& dir) const
352{
353 return find_dir_info (dir) != dir_info_list.end ();
354}
355
356bool
357load_path::do_contains_canonical (const std::string& dir) const
358{
359 bool retval = false;
360
361 for (const_dir_info_list_iterator i = dir_info_list.begin ();
362 i != dir_info_list.end ();
363 i++)
364 {
365 if (same_file (dir, i->dir_name))
366 {
367 retval = true;
368 break;
369 }
370 }
371
372 return retval;
373}
374
375void
376load_path::move_fcn_map (const std::string& dir_name,
377 const string_vector& fcn_files, bool at_end)
378{
379 octave_idx_type len = fcn_files.length ();
380
381 for (octave_idx_type k = 0; k < len; k++)
382 {
383 std::string fname = fcn_files[k];
384
385 std::string ext;
386 std::string base = fname;
387
388 size_t pos = fname.rfind ('.');
389
390 if (pos != std::string::npos)
391 {
392 base = fname.substr (0, pos);
393 ext = fname.substr (pos);
394 }
395
396 file_info_list_type& file_info_list = fcn_map[base];
397
398 if (file_info_list.size () == 1)
399 continue;
400 else
401 {
402 for (file_info_list_iterator p = file_info_list.begin ();
403 p != file_info_list.end ();
404 p++)
405 {
406 if (p->dir_name == dir_name)
407 {
408 file_info fi = *p;
409
410 file_info_list.erase (p);
411
412 if (at_end)
413 file_info_list.push_back (fi);
414 else
415 file_info_list.push_front (fi);
416
417 break;
418 }
419 }
420 }
421 }
422}
423
424void
425load_path::move_method_map (const std::string& dir_name, bool at_end)
426{
427 for (method_map_iterator i = method_map.begin ();
428 i != method_map.end ();
429 i++)
430 {
431 std::string class_name = i->first;
432
433 fcn_map_type& fm = i->second;
434
435 std::string full_dir_name
436 = file_ops::concat (dir_name, "@" + class_name);
437
438 for (fcn_map_iterator q = fm.begin (); q != fm.end (); q++)
439 {
440 file_info_list_type& file_info_list = q->second;
441
442 if (file_info_list.size () == 1)
443 continue;
444 else
445 {
446 for (file_info_list_iterator p = file_info_list.begin ();
447 p != file_info_list.end (); p++)
448 {
449 if (p->dir_name == full_dir_name)
450 {
451 file_info fi = *p;
452
453 file_info_list.erase (p);
454
455 if (at_end)
456 file_info_list.push_back (fi);
457 else
458 file_info_list.push_front (fi);
459
460 break;
461 }
462 }
463 }
464 }
465 }
466}
467
468void
469load_path::move (dir_info_list_iterator i, bool at_end)
470{
471 if (dir_info_list.size () > 1)
472 {
473 dir_info di = *i;
474
475 dir_info_list.erase (i);
476
477 if (at_end)
478 dir_info_list.push_back (di);
479 else
480 dir_info_list.push_front (di);
481
482 std::string dir_name = di.dir_name;
483
484 move_fcn_map (dir_name, di.fcn_files, at_end);
485
486 // No need to move elements of private function map.
487
488 move_method_map (dir_name, at_end);
489 }
490}
491
492static void
493maybe_add_path_elts (std::string& path, const std::string& dir)
494{
495 std::string tpath = genpath (dir);
496
497 if (! tpath.empty ())
498 {
499 if (path.empty ())
500 path = tpath;
501 else
502 path += dir_path::path_sep_str () + tpath;
503 }
504}
505
506void
507load_path::do_initialize (bool set_initial_path)
508{
509 sys_path = "";
510
511 if (set_initial_path)
512 {
513 maybe_add_path_elts (sys_path, Vlocal_ver_oct_file_dir);
514 maybe_add_path_elts (sys_path, Vlocal_api_oct_file_dir);
515 maybe_add_path_elts (sys_path, Vlocal_oct_file_dir);
516 maybe_add_path_elts (sys_path, Vlocal_ver_fcn_file_dir);
517 maybe_add_path_elts (sys_path, Vlocal_api_fcn_file_dir);
518 maybe_add_path_elts (sys_path, Vlocal_fcn_file_dir);
519 maybe_add_path_elts (sys_path, Voct_file_dir);
520 maybe_add_path_elts (sys_path, Vfcn_file_dir);
521 }
522
523 std::string tpath = load_path::command_line_path;
524
525 if (tpath.empty ())
526 tpath = octave_env::getenv ("OCTAVE_PATH");
527
528 std::string xpath;
529
530 if (! tpath.empty ())
531 {
532 xpath = tpath;
533
534 if (! sys_path.empty ())
535 xpath += dir_path::path_sep_str () + sys_path;
536 }
537 else
538 xpath = sys_path;
539
540 do_set (xpath, false, true);
541}
542
543void
544load_path::do_clear (void)
545{
546 dir_info_list.clear ();
547 fcn_map.clear ();
548 private_fcn_map.clear ();
549 method_map.clear ();
550}
551
552static std::list<std::string>
553split_path (const std::string& p)
554{
555 std::list<std::string> retval;
556
557 size_t beg = 0;
558 size_t end = p.find (dir_path::path_sep_char ());
559
560 size_t len = p.length ();
561
562 while (end != std::string::npos)
563 {
564 std::string elt = p.substr (beg, end-beg);
565
566 if (! elt.empty ())
567 retval.push_back (elt);
568
569 beg = end + 1;
570
571 if (beg == len)
572 break;
573
574 end = p.find (dir_path::path_sep_char (), beg);
575 }
576
577 std::string elt = p.substr (beg);
578
579 if (! elt.empty ())
580 retval.push_back (elt);
581
582 return retval;
583}
584
585void
586load_path::do_set (const std::string& p, bool warn, bool is_init)
587{
588 // Use a list when we need to preserve order.
589 std::list<std::string> elts = split_path (p);
590
591 // Use a set when we need to search and order is not important.
592 std::set<std::string> elts_set (elts.begin (), elts.end ());
593
594 if (is_init)
595 init_dirs = elts_set;
596 else
597 {
598 for (std::set<std::string>::const_iterator it = init_dirs.begin ();
599 it != init_dirs.end (); it++)
600 {
601 if (elts_set.find (*it) == elts_set.end ())
602 {
603 warning_with_id ("Octave:remove-init-dir",
604 "default load path altered. Some built-in functions may not be found. Try restoredefaultpath() to recover it.");
605 break;
606 }
607 }
608 }
609
610 // Temporarily disable add hook.
611
612 unwind_protect frame;
613 frame.protect_var (add_hook);
614
615 add_hook = 0;
616
617 do_clear ();
618
619 for (std::list<std::string>::const_iterator i = elts.begin ();
620 i != elts.end (); i++)
621 do_append (*i, warn);
622
623 // Restore add hook and execute for all newly added directories.
624 frame.run_first ();
625
626 for (dir_info_list_iterator i = dir_info_list.begin ();
627 i != dir_info_list.end ();
628 i++)
629 {
630 if (add_hook)
631 add_hook (i->dir_name);
632 }
633
634 // Always prepend current directory.
635 do_prepend (".", warn);
636}
637
638void
639load_path::do_append (const std::string& dir, bool warn)
640{
641 if (! dir.empty ())
642 do_add (dir, true, warn);
643}
644
645void
646load_path::do_prepend (const std::string& dir, bool warn)
647{
648 if (! dir.empty ())
649 do_add (dir, false, warn);
650}
651
652// Strip trailing directory separators.
653
654static std::string
655strip_trailing_separators (const std::string& dir_arg)
656{
657 std::string dir = dir_arg;
658
659 size_t k = dir.length ();
660
661 while (k > 1 && file_ops::is_dir_sep (dir[k-1]))
662 k--;
663
664 if (k < dir.length ())
665 dir.resize (k);
666
667 return dir;
668}
669
670void
671load_path::do_add (const std::string& dir_arg, bool at_end, bool warn)
672{
673 size_t len = dir_arg.length ();
674
675 if (len > 1 && dir_arg.substr (len-2) == "//")
676 warning_with_id ("Octave:recursive-path-search",
677 "trailing '//' is no longer special in search path elements");
678
679 std::string dir = file_ops::tilde_expand (dir_arg);
680
681 dir = strip_trailing_separators (dir);
682
683 dir_info_list_iterator i = find_dir_info (dir);
684
685 if (i != dir_info_list.end ())
686 move (i, at_end);
687 else
688 {
689 file_stat fs (dir);
690
691 if (fs)
692 {
693 if (fs.is_dir ())
694 {
695 dir_info di (dir);
696
697 if (! error_state)
698 {
699 if (at_end)
700 dir_info_list.push_back (di);
701 else
702 dir_info_list.push_front (di);
703
704 add_to_fcn_map (di, at_end);
705
706 add_to_private_fcn_map (di);
707
708 add_to_method_map (di, at_end);
709
710 if (add_hook)
711 add_hook (dir);
712 }
713 }
714 else if (warn)
715 warning ("addpath: %s: not a directory", dir_arg.c_str ());
716 }
717 else if (warn)
718 {
719 std::string msg = fs.error ();
720 warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ());
721 }
722 }
723
724 // FIXME: is there a better way to do this?
725
726 i = find_dir_info (".");
727
728 if (i != dir_info_list.end ())
729 move (i, false);
730}
731
732void
733load_path::remove_fcn_map (const std::string& dir,
734 const string_vector& fcn_files)
735{
736 octave_idx_type len = fcn_files.length ();
737
738 for (octave_idx_type k = 0; k < len; k++)
739 {
740 std::string fname = fcn_files[k];
741
742 std::string ext;
743 std::string base = fname;
744
745 size_t pos = fname.rfind ('.');
746
747 if (pos != std::string::npos)
748 {
749 base = fname.substr (0, pos);
750 ext = fname.substr (pos);
751 }
752
753 file_info_list_type& file_info_list = fcn_map[base];
754
755 for (file_info_list_iterator p = file_info_list.begin ();
756 p != file_info_list.end ();
757 p++)
758 {
759 if (p->dir_name == dir)
760 {
761 file_info_list.erase (p);
762
763 if (file_info_list.empty ())
764 fcn_map.erase (fname);
765
766 break;
767 }
768 }
769 }
770}
771
772void
773load_path::remove_private_fcn_map (const std::string& dir)
774{
775 private_fcn_map_iterator p = private_fcn_map.find (dir);
776
777 if (p != private_fcn_map.end ())
778 private_fcn_map.erase (p);
779}
780
781void
782load_path::remove_method_map (const std::string& dir)
783{
784 for (method_map_iterator i = method_map.begin ();
785 i != method_map.end ();
786 i++)
787 {
788 std::string class_name = i->first;
789
790 fcn_map_type& fm = i->second;
791
792 std::string full_dir_name = file_ops::concat (dir, "@" + class_name);
793
794 for (fcn_map_iterator q = fm.begin (); q != fm.end (); q++)
795 {
796 file_info_list_type& file_info_list = q->second;
797
798 if (file_info_list.size () == 1)
799 continue;
800 else
801 {
802 for (file_info_list_iterator p = file_info_list.begin ();
803 p != file_info_list.end (); p++)
804 {
805 if (p->dir_name == full_dir_name)
806 {
807 file_info_list.erase (p);
808
809 // FIXME: if there are no other elements, we
810 // should remove this element of fm but calling
811 // erase here would invalidate the iterator q.
812
813 break;
814 }
815 }
816 }
817 }
818 }
819}
820
821bool
822load_path::do_remove (const std::string& dir_arg)
823{
824 bool retval = false;
825
826 if (! dir_arg.empty ())
827 {
828 if (dir_arg == ".")
829 {
830 warning ("rmpath: can't remove \".\" from path");
831
832 // Avoid additional warnings.
833 retval = true;
834 }
835 else
836 {
837 std::string dir = file_ops::tilde_expand (dir_arg);
838
839 dir = strip_trailing_separators (dir);
840
841 dir_info_list_iterator i = find_dir_info (dir);
842
843 if (i != dir_info_list.end ())
844 {
845 retval = true;
846
847 if (remove_hook)
848 remove_hook (dir);
849
850 string_vector fcn_files = i->fcn_files;
851
852 dir_info_list.erase (i);
853
854 remove_fcn_map (dir, fcn_files);
855
856 remove_private_fcn_map (dir);
857
858 remove_method_map (dir);
859 }
860 }
861 }
862
863 return retval;
864}
865
866void
867load_path::do_update (void) const
868{
869 // I don't see a better way to do this because we need to
870 // preserve the correct directory ordering for new files that
871 // have appeared.
872
873 fcn_map.clear ();
874
875 private_fcn_map.clear ();
876
877 method_map.clear ();
878
879 for (dir_info_list_iterator p = dir_info_list.begin ();
880 p != dir_info_list.end ();
881 p++)
882 {
883 dir_info& di = *p;
884
885 di.update ();
886
887 add_to_fcn_map (di, true);
888
889 add_to_private_fcn_map (di);
890
891 add_to_method_map (di, true);
892 }
893}
894
895bool
896load_path::check_file_type (std::string& fname, int type, int possible_types,
897 const std::string& fcn, const char *who)
898{
899 bool retval = false;
900
901 if (type == load_path::OCT_FILE)
902 {
903 if ((type & possible_types) == load_path::OCT_FILE)
904 {
905 fname += ".oct";
906 retval = true;
907 }
908 }
909 else if (type == load_path::M_FILE)
910 {
911 if ((type & possible_types) == load_path::M_FILE)
912 {
913 fname += ".m";
914 retval = true;
915 }
916 }
917 else if (type == load_path::MEX_FILE)
918 {
919 if ((type & possible_types) == load_path::MEX_FILE)
920 {
921 fname += ".mex";
922 retval = true;
923 }
924 }
925 else if (type == (load_path::M_FILE | load_path::OCT_FILE))
926 {
927 if (possible_types & load_path::OCT_FILE)
928 {
929 fname += ".oct";
930 retval = true;
931 }
932 else if (possible_types & load_path::M_FILE)
933 {
934 fname += ".m";
935 retval = true;
936 }
937 }
938 else if (type == (load_path::M_FILE | load_path::MEX_FILE))
939 {
940 if (possible_types & load_path::MEX_FILE)
941 {
942 fname += ".mex";
943 retval = true;
944 }
945 else if (possible_types & load_path::M_FILE)
946 {
947 fname += ".m";
948 retval = true;
949 }
950 }
951 else if (type == (load_path::OCT_FILE | load_path::MEX_FILE))
952 {
953 if (possible_types & load_path::OCT_FILE)
954 {
955 fname += ".oct";
956 retval = true;
957 }
958 else if (possible_types & load_path::MEX_FILE)
959 {
960 fname += ".mex";
961 retval = true;
962 }
963 }
964 else if (type == (load_path::M_FILE | load_path::OCT_FILE
965 | load_path::MEX_FILE))
966 {
967 if (possible_types & load_path::OCT_FILE)
968 {
969 fname += ".oct";
970 retval = true;
971 }
972 else if (possible_types & load_path::MEX_FILE)
973 {
974 fname += ".mex";
975 retval = true;
976 }
977 else if (possible_types & load_path::M_FILE)
978 {
979 fname += ".m";
980 retval = true;
981 }
982 }
983 else
984 error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type);
985
986 return retval;
987}
988
989std::string
990load_path::do_find_fcn (const std::string& fcn, std::string& dir_name,
991 int type) const
992{
993 std::string retval;
994
995 // update ();
996
997 if (fcn.length () > 0 && fcn[0] == '@')
998 {
999 size_t pos = fcn.find ('/');
1000
1001 if (pos != std::string::npos)
1002 {
1003 std::string class_name = fcn.substr (1, pos-1);
1004 std::string meth = fcn.substr (pos+1);
1005
1006 retval = do_find_method (class_name, meth, dir_name);
1007 }
1008 else
1009 retval = std::string ();
1010 }
1011 else
1012 {
1013 dir_name = std::string ();
1014
1015 const_fcn_map_iterator p = fcn_map.find (fcn);
1016
1017 if (p != fcn_map.end ())
1018 {
1019 const file_info_list_type& file_info_list = p->second;
1020
1021 for (const_file_info_list_iterator i = file_info_list.begin ();
1022 i != file_info_list.end ();
1023 i++)
1024 {
1025 const file_info& fi = *i;
1026
1027 retval = file_ops::concat (fi.dir_name, fcn);
1028
1029 if (check_file_type (retval, type, fi.types,
1030 fcn, "load_path::do_find_fcn"))
1031 {
1032 dir_name = fi.dir_name;
1033 break;
1034 }
1035 else
1036 retval = std::string ();
1037 }
1038 }
1039 }
1040
1041 return retval;
1042}
1043
1044std::string
1045load_path::do_find_private_fcn (const std::string& dir,
1046 const std::string& fcn, int type) const
1047{
1048 std::string retval;
1049
1050 // update ();
1051
1052 const_private_fcn_map_iterator q = private_fcn_map.find (dir);
1053
1054 if (q != private_fcn_map.end ())
1055 {
1056 const dir_info::fcn_file_map_type& m = q->second;
1057
1058 dir_info::const_fcn_file_map_iterator p = m.find (fcn);
1059
1060 if (p != m.end ())
1061 {
1062 std::string fname
1063 = file_ops::concat (file_ops::concat (dir, "private"), fcn);
1064
1065 if (check_file_type (fname, type, p->second, fcn,
1066 "load_path::find_private_fcn"))
1067 retval = fname;
1068 }
1069 }
1070
1071 return retval;
1072}
1073
1074std::string
1075load_path::do_find_method (const std::string& class_name,
1076 const std::string& meth,
1077 std::string& dir_name, int type) const
1078{
1079 std::string retval;
1080
1081 // update ();
1082
1083 dir_name = std::string ();
1084
1085 const_method_map_iterator q = method_map.find (class_name);
1086
1087 if (q != method_map.end ())
1088 {
1089 const fcn_map_type& m = q->second;
1090
1091 const_fcn_map_iterator p = m.find (meth);
1092
1093 if (p != m.end ())
1094 {
1095 const file_info_list_type& file_info_list = p->second;
1096
1097 for (const_file_info_list_iterator i = file_info_list.begin ();
1098 i != file_info_list.end ();
1099 i++)
1100 {
1101 const file_info& fi = *i;
1102
1103 retval = file_ops::concat (fi.dir_name, meth);
1104
1105 bool found = check_file_type (retval, type, fi.types,
1106 meth, "load_path::do_find_method");
1107
1108 if (found)
1109 {
1110 dir_name = fi.dir_name;
1111 break;
1112 }
1113 else
1114 retval = std::string ();
1115 }
1116 }
1117 }
1118
1119 return retval;
1120}
1121
1122std::list<std::string>
1123load_path::do_methods (const std::string& class_name) const
1124{
1125 std::list<std::string> retval;
1126
1127 // update ();
1128
1129 const_method_map_iterator q = method_map.find (class_name);
1130
1131 if (q != method_map.end ())
1132 {
1133 const fcn_map_type& m = q->second;
1134
1135 for (const_fcn_map_iterator p = m.begin (); p != m.end (); p++)
1136 retval.push_back (p->first);
1137 }
1138
1139 if (! retval.empty ())
1140 retval.sort ();
1141
1142 return retval;
1143}
1144
1145std::list<std::string>
1146load_path::do_overloads (const std::string& meth) const
1147{
1148 std::list<std::string> retval;
1149
1150 // update ();
1151
1152 for (const_method_map_iterator q = method_map.begin ();
1153 q != method_map.end (); q++)
1154 {
1155 const fcn_map_type& m = q->second;
1156
1157 if (m.find (meth) != m.end ())
1158 retval.push_back (q->first);
1159 }
1160
1161 return retval;
1162}
1163
1164std::string
1165load_path::do_find_file (const std::string& file) const
1166{
1167 std::string retval;
1168
1169 if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos)
1170 {
1171 if (octave_env::absolute_pathname (file)
1172 || octave_env::rooted_relative_pathname (file))
1173 {
1174 file_stat fs (file);
1175
1176 if (fs.exists ())
1177 return file;
1178 }
1179 else
1180 {
1181 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1182 p != dir_info_list.end ();
1183 p++)
1184 {
1185 std::string tfile = file_ops::concat (p->dir_name, file);
1186
1187 file_stat fs (tfile);
1188
1189 if (fs.exists ())
1190 return tfile;
1191 }
1192 }
1193 }
1194 else
1195 {
1196 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1197 p != dir_info_list.end ();
1198 p++)
1199 {
1200 string_vector all_files = p->all_files;
1201
1202 octave_idx_type len = all_files.length ();
1203
1204 for (octave_idx_type i = 0; i < len; i++)
1205 {
1206 if (all_files[i] == file)
1207 return file_ops::concat (p->dir_name, file);
1208 }
1209 }
1210 }
1211
1212 return retval;
1213}
1214
1215std::string
1216load_path::do_find_dir (const std::string& dir) const
1217{
1218 std::string retval;
1219
1220 if (dir.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos
1221 && (octave_env::absolute_pathname (dir)
1222 || octave_env::rooted_relative_pathname (dir)))
1223 {
1224 file_stat fs (dir);
1225
1226 if (fs.exists () && fs.is_dir ())
1227 return dir;
1228 }
1229 else
1230 {
1231 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1232 p != dir_info_list.end ();
1233 p++)
1234 {
1235 std::string dname = octave_env::make_absolute (p->dir_name);
1236
1237 size_t dname_len = dname.length ();
1238
1239 if (dname.substr (dname_len - 1) == file_ops::dir_sep_str ())
1240 {
1241 dname = dname.substr (0, dname_len - 1);
1242 dname_len--;
1243 }
1244
1245 size_t dir_len = dir.length ();
1246
1247 if (dname_len >= dir_len
1248 && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
1249 && dir.compare (dname.substr (dname_len - dir_len)) == 0)
1250 {
1251 file_stat fs (p->dir_name);
1252
1253 if (fs.exists () && fs.is_dir ())
1254 return p->dir_name;
1255 }
1256 }
1257 }
1258
1259 return retval;
1260}
1261
1262string_vector
1263load_path::do_find_matching_dirs (const std::string& dir) const
1264{
1265 std::list<std::string> retlist;
1266
1267 if (dir.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos
1268 && (octave_env::absolute_pathname (dir)
1269 || octave_env::rooted_relative_pathname (dir)))
1270 {
1271 file_stat fs (dir);
1272
1273 if (fs.exists () && fs.is_dir ())
1274 retlist.push_back (dir);
1275 }
1276 else
1277 {
1278 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1279 p != dir_info_list.end ();
1280 p++)
1281 {
1282 std::string dname = octave_env::make_absolute (p->dir_name);
1283
1284 size_t dname_len = dname.length ();
1285
1286 if (dname.substr (dname_len - 1) == file_ops::dir_sep_str ())
1287 {
1288 dname = dname.substr (0, dname_len - 1);
1289 dname_len--;
1290 }
1291
1292 size_t dir_len = dir.length ();
1293
1294 if (dname_len >= dir_len
1295 && file_ops::is_dir_sep (dname[dname_len - dir_len - 1])
1296 && dir.compare (dname.substr (dname_len - dir_len)) == 0)
1297 {
1298 file_stat fs (p->dir_name);
1299
1300 if (fs.exists () && fs.is_dir ())
1301 retlist.push_back (p->dir_name);
1302 }
1303 }
1304 }
1305
1306 return retlist;
1307}
1308
1309std::string
1310load_path::do_find_first_of (const string_vector& flist) const
1311{
1312 std::string retval;
1313
1314 std::string dir_name;
1315 std::string file_name;
1316
1317 octave_idx_type flen = flist.length ();
1318 octave_idx_type rel_flen = 0;
1319
1320 string_vector rel_flist (flen);
1321
1322 for (octave_idx_type i = 0; i < flen; i++)
1323 {
1324 std::string file = flist[i];
1325
1326 if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos)
1327 {
1328 if (octave_env::absolute_pathname (file)
1329 || octave_env::rooted_relative_pathname (file))
1330 {
1331 file_stat fs (file);
1332
1333 if (fs.exists ())
1334 return file;
1335 }
1336 else
1337 {
1338 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1339 p != dir_info_list.end ();
1340 p++)
1341 {
1342 std::string tfile = file_ops::concat (p->dir_name, file);
1343
1344 file_stat fs (tfile);
1345
1346 if (fs.exists ())
1347 return tfile;
1348 }
1349 }
1350 }
1351 else
1352 rel_flist[rel_flen++] = file;
1353 }
1354
1355 rel_flist.resize (rel_flen);
1356
1357 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1358 p != dir_info_list.end ();
1359 p++)
1360 {
1361 string_vector all_files = p->all_files;
1362
1363 octave_idx_type len = all_files.length ();
1364
1365 for (octave_idx_type i = 0; i < len; i++)
1366 {
1367 for (octave_idx_type j = 0; j < rel_flen; j++)
1368 {
1369 if (all_files[i] == rel_flist[j])
1370 {
1371 dir_name = p->dir_name;
1372 file_name = rel_flist[j];
1373
1374 goto done;
1375 }
1376 }
1377 }
1378 }
1379
1380done:
1381
1382 if (! dir_name.empty ())
1383 retval = file_ops::concat (dir_name, file_name);
1384
1385 return retval;
1386}
1387
1388string_vector
1389load_path::do_find_all_first_of (const string_vector& flist) const
1390{
1391 std::list<std::string> retlist;
1392
1393 std::string dir_name;
1394 std::string file_name;
1395
1396 octave_idx_type flen = flist.length ();
1397 octave_idx_type rel_flen = 0;
1398
1399 string_vector rel_flist (flen);
1400
1401 for (octave_idx_type i = 0; i < flen; i++)
1402 {
1403 std::string file = flist[i];
1404
1405 if (file.find_first_of (file_ops::dir_sep_chars ()) != std::string::npos)
1406 {
1407 if (octave_env::absolute_pathname (file)
1408 || octave_env::rooted_relative_pathname (file))
1409 {
1410 file_stat fs (file);
1411
1412 if (fs.exists ())
1413 retlist.push_back (file);
1414 }
1415 else
1416 {
1417 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1418 p != dir_info_list.end ();
1419 p++)
1420 {
1421 std::string tfile = file_ops::concat (p->dir_name, file);
1422
1423 file_stat fs (tfile);
1424
1425 if (fs.exists ())
1426 retlist.push_back (tfile);
1427 }
1428 }
1429 }
1430 else
1431 rel_flist[rel_flen++] = file;
1432 }
1433
1434 rel_flist.resize (rel_flen);
1435
1436 for (const_dir_info_list_iterator p = dir_info_list.begin ();
1437 p != dir_info_list.end (); p++)
1438 {
1439 string_vector all_files = p->all_files;
1440
1441 octave_idx_type len = all_files.length ();
1442
1443 for (octave_idx_type i = 0; i < len; i++)
1444 {
1445 for (octave_idx_type j = 0; j < rel_flen; j++)
1446 {
1447 if (all_files[i] == rel_flist[j])
1448 retlist.push_back (file_ops::concat (p->dir_name,
1449 rel_flist[j]));
1450 }
1451 }
1452 }
1453
1454 return retlist;
1455}
1456
1457string_vector
1458load_path::do_dirs (void) const
1459{
1460 size_t len = dir_info_list.size ();
1461
1462 string_vector retval (len);
1463
1464 octave_idx_type k = 0;
1465
1466 for (const_dir_info_list_iterator i = dir_info_list.begin ();
1467 i != dir_info_list.end ();
1468 i++)
1469 retval[k++] = i->dir_name;
1470
1471 return retval;
1472}
1473
1474std::list<std::string>
1475load_path::do_dir_list (void) const
1476{
1477 std::list<std::string> retval;
1478
1479 for (const_dir_info_list_iterator i = dir_info_list.begin ();
1480 i != dir_info_list.end ();
1481 i++)
1482 retval.push_back (i->dir_name);
1483
1484 return retval;
1485}
1486
1487string_vector
1488load_path::do_files (const std::string& dir, bool omit_exts) const
1489{
1490 string_vector retval;
1491
1492 const_dir_info_list_iterator p = find_dir_info (dir);
1493
1494 if (p != dir_info_list.end ())
1495 retval = p->fcn_files;
1496
1497 if (omit_exts)
1498 {
1499 octave_idx_type len = retval.length ();
1500
1501 for (octave_idx_type i = 0; i < len; i++)
1502 {
1503 std::string fname = retval[i];
1504
1505 size_t pos = fname.rfind ('.');
1506
1507 if (pos != std::string::npos)
1508 retval[i] = fname.substr (0, pos);
1509 }
1510 }
1511
1512 return retval;
1513}
1514
1515string_vector
1516load_path::do_fcn_names (void) const
1517{
1518 size_t len = fcn_map.size ();
1519
1520 string_vector retval (len);
1521
1522 octave_idx_type count = 0;
1523
1524 for (const_fcn_map_iterator p = fcn_map.begin ();
1525 p != fcn_map.end ();
1526 p++)
1527 retval[count++] = p->first;
1528
1529 return retval;
1530}
1531
1532std::string
1533load_path::do_path (void) const
1534{
1535 std::string xpath;
1536
1537 string_vector xdirs = load_path::dirs ();
1538
1539 octave_idx_type len = xdirs.length ();
1540
1541 if (len > 0)
1542 xpath = xdirs[0];
1543
1544 for (octave_idx_type i = 1; i < len; i++)
1545 xpath += dir_path::path_sep_str () + xdirs[i];
1546
1547 return xpath;
1548}
1549
1550void
1551print_types (std::ostream& os, int types)
1552{
1553 bool printed_type = false;
1554
1555 if (types & load_path::OCT_FILE)
1556 {
1557 os << "oct";
1558 printed_type = true;
1559 }
1560
1561 if (types & load_path::MEX_FILE)
1562 {
1563 if (printed_type)
1564 os << "|";
1565 os << "mex";
1566 printed_type = true;
1567 }
1568
1569 if (types & load_path::M_FILE)
1570 {
1571 if (printed_type)
1572 os << "|";
1573 os << "m";
1574 printed_type = true;
Value stored to 'printed_type' is never read
1575 }
1576}
1577
1578void
1579print_fcn_list (std::ostream& os,
1580 const load_path::dir_info::fcn_file_map_type& lst)
1581{
1582 for (load_path::dir_info::const_fcn_file_map_iterator p = lst.begin ();
1583 p != lst.end ();
1584 p++)
1585 {
1586 os << " " << p->first << " (";
1587
1588 print_types (os, p->second);
1589
1590 os << ")\n";
1591 }
1592}
1593
1594string_vector
1595get_file_list (const load_path::dir_info::fcn_file_map_type& lst)
1596{
1597 octave_idx_type n = lst.size ();
1598
1599 string_vector retval (n);
1600
1601 octave_idx_type count = 0;
1602
1603 for (load_path::dir_info::const_fcn_file_map_iterator p = lst.begin ();
1604 p != lst.end ();
1605 p++)
1606 {
1607 std::string nm = p->first;
1608
1609 int types = p->second;
1610
1611 if (types & load_path::OCT_FILE)
1612 nm += ".oct";
1613 else if (types & load_path::MEX_FILE)
1614 nm += ".mex";
1615 else
1616 nm += ".m";
1617
1618 retval[count++] = nm;
1619 }
1620
1621 return retval;
1622}
1623
1624void
1625load_path::do_display (std::ostream& os) const
1626{
1627 for (const_dir_info_list_iterator i = dir_info_list.begin ();
1628 i != dir_info_list.end ();
1629 i++)
1630 {
1631 string_vector fcn_files = i->fcn_files;
1632
1633 if (! fcn_files.empty ())
1634 {
1635 os << "\n*** function files in " << i->dir_name << ":\n\n";
1636
1637 fcn_files.list_in_columns (os);
1638 }
1639
1640 const dir_info::method_file_map_type& method_file_map
1641 = i->method_file_map;
1642
1643 if (! method_file_map.empty ())
1644 {
1645 for (dir_info::const_method_file_map_iterator
1646 p = method_file_map.begin (); p != method_file_map.end (); p++)
1647 {
1648 os << "\n*** methods in " << i->dir_name
1649 << "/@" << p->first << ":\n\n";
1650
1651 const dir_info::class_info& ci = p->second;
1652
1653 string_vector method_files = get_file_list (ci.method_file_map);
1654
1655 method_files.list_in_columns (os);
1656 }
1657 }
1658 }
1659
1660 for (const_private_fcn_map_iterator i = private_fcn_map.begin ();
1661 i != private_fcn_map.end (); i++)
1662 {
1663 os << "\n*** private functions in "
1664 << file_ops::concat (i->first, "private") << ":\n\n";
1665
1666 print_fcn_list (os, i->second);
1667 }
1668
1669#if defined (DEBUG_LOAD_PATH)
1670
1671 for (const_fcn_map_iterator i = fcn_map.begin ();
1672 i != fcn_map.end ();
1673 i++)
1674 {
1675 os << i->first << ":\n";
1676
1677 const file_info_list_type& file_info_list = i->second;
1678
1679 for (const_file_info_list_iterator p = file_info_list.begin ();
1680 p != file_info_list.end ();
1681 p++)
1682 {
1683 os << " " << p->dir_name << " (";
1684
1685 print_types (os, p->types);
1686
1687 os << ")\n";
1688 }
1689 }
1690
1691 for (const_method_map_iterator i = method_map.begin ();
1692 i != method_map.end ();
1693 i++)
1694 {
1695 os << "CLASS " << i->first << ":\n";
1696
1697 const fcn_map_type& fm = i->second;
1698
1699 for (const_fcn_map_iterator q = fm.begin ();
1700 q != fm.end ();
1701 q++)
1702 {
1703 os << " " << q->first << ":\n";
1704
1705 const file_info_list_type& file_info_list = q->second;
1706
1707 for (const_file_info_list_iterator p = file_info_list.begin ();
1708 p != file_info_list.end ();
1709 p++)
1710 {
1711 os << " " << p->dir_name << " (";
1712
1713 print_types (os, p->types);
1714
1715 os << ")\n";
1716 }
1717 }
1718 }
1719
1720 os << "\n";
1721
1722#endif
1723}
1724
1725// True if a path is contained in a path list separated by path_sep_char
1726static bool
1727in_path_list (const std::string& path_list, const std::string& path)
1728{
1729 size_t ps = path.size ();
1730 size_t pls = path_list.size ();
1731 size_t pos = path_list.find (path);
1732 char psc = dir_path::path_sep_char ();
1733 while (pos != std::string::npos)
1734 {
1735 if ((pos == 0 || path_list[pos-1] == psc)
1736 && (pos + ps == pls || path_list[pos + ps] == psc))
1737 return true;
1738 else
1739 pos = path_list.find (path, pos + 1);
1740 }
1741
1742 return false;
1743}
1744
1745void
1746load_path::add_to_fcn_map (const dir_info& di, bool at_end) const
1747{
1748 std::string dir_name = di.dir_name;
1749
1750 string_vector fcn_files = di.fcn_files;
1751
1752 octave_idx_type len = fcn_files.length ();
1753
1754 for (octave_idx_type i = 0; i < len; i++)
1755 {
1756 std::string fname = fcn_files[i];
1757
1758 std::string ext;
1759 std::string base = fname;
1760
1761 size_t pos = fname.rfind ('.');
1762
1763 if (pos != std::string::npos)
1764 {
1765 base = fname.substr (0, pos);
1766 ext = fname.substr (pos);
1767 }
1768
1769 file_info_list_type& file_info_list = fcn_map[base];
1770
1771 file_info_list_iterator p = file_info_list.begin ();
1772
1773 while (p != file_info_list.end ())
1774 {
1775 if (p->dir_name == dir_name)
1776 break;
1777
1778 p++;
1779 }
1780
1781 int t = 0;
1782 if (ext == ".m")
1783 t = load_path::M_FILE;
1784 else if (ext == ".oct")
1785 t = load_path::OCT_FILE;
1786 else if (ext == ".mex")
1787 t = load_path::MEX_FILE;
1788
1789 if (p == file_info_list.end ())
1790 {
1791 file_info fi (dir_name, t);
1792
1793 if (at_end)
1794 file_info_list.push_back (fi);
1795 else
1796 {
1797 // Warn if a built-in or library function is being shadowed.
1798
1799 if (! file_info_list.empty ())
1800 {
1801 file_info& old = file_info_list.front ();
1802
1803 // FIXME: do we need to be more careful about the
1804 // way we look for old.dir_name in sys_path to avoid
1805 // partial matches?
1806
1807 // Don't warn about Contents.m files since we expect
1808 // more than one to exist in the load path.
1809
1810 if (fname != "Contents.m"
1811 && sys_path.find (old.dir_name) != std::string::npos
1812 && in_path_list (sys_path, old.dir_name))
1813 {
1814 std::string fcn_path = file_ops::concat (dir_name, fname);
1815
1816 warning_with_id ("Octave:shadowed-function",
1817 "function %s shadows a core library function",
1818 fcn_path.c_str ());
1819 }
1820 }
1821 else if (symbol_table::is_built_in_function_name (base))
1822 {
1823 std::string fcn_path = file_ops::concat (dir_name, fname);
1824 warning_with_id ("Octave:shadowed-function",
1825 "function %s shadows a built-in function",
1826 fcn_path.c_str ());
1827 }
1828
1829 file_info_list.push_front (fi);
1830 }
1831 }
1832 else
1833 {
1834 file_info& fi = *p;
1835
1836 fi.types |= t;
1837 }
1838 }
1839}
1840
1841void
1842load_path::add_to_private_fcn_map (const dir_info& di) const
1843{
1844 dir_info::fcn_file_map_type private_file_map = di.private_file_map;
1845
1846 if (! private_file_map.empty ())
1847 private_fcn_map[di.dir_name] = private_file_map;
1848}
1849
1850void
1851load_path::add_to_method_map (const dir_info& di, bool at_end) const
1852{
1853 std::string dir_name = di.dir_name;
1854
1855 // <CLASS_NAME, CLASS_INFO>
1856 dir_info::method_file_map_type method_file_map = di.method_file_map;
1857
1858 for (dir_info::const_method_file_map_iterator q = method_file_map.begin ();
1859 q != method_file_map.end ();
1860 q++)
1861 {
1862 std::string class_name = q->first;
1863
1864 fcn_map_type& fm = method_map[class_name];
1865
1866 std::string full_dir_name
1867 = file_ops::concat (dir_name, "@" + class_name);
1868
1869 const dir_info::class_info& ci = q->second;
1870
1871 // <FCN_NAME, TYPES>
1872 const dir_info::fcn_file_map_type& m = ci.method_file_map;
1873
1874 for (dir_info::const_fcn_file_map_iterator p = m.begin ();
1875 p != m.end ();
1876 p++)
1877 {
1878 std::string base = p->first;
1879
1880 int types = p->second;
1881
1882 file_info_list_type& file_info_list = fm[base];
1883
1884 file_info_list_iterator p2 = file_info_list.begin ();
1885
1886 while (p2 != file_info_list.end ())
1887 {
1888 if (p2->dir_name == full_dir_name)
1889 break;
1890
1891 p2++;
1892 }
1893
1894 if (p2 == file_info_list.end ())
1895 {
1896 file_info fi (full_dir_name, types);
1897
1898 if (at_end)
1899 file_info_list.push_back (fi);
1900 else
1901 file_info_list.push_front (fi);
1902 }
1903 else
1904 {
1905 // FIXME: is this possible?
1906
1907 file_info& fi = *p2;
1908
1909 fi.types = types;
1910 }
1911 }
1912
1913 // <FCN_NAME, TYPES>
1914 dir_info::fcn_file_map_type private_file_map = ci.private_file_map;
1915
1916 if (! private_file_map.empty ())
1917 private_fcn_map[full_dir_name] = private_file_map;
1918 }
1919}
1920
1921std::string
1922genpath (const std::string& dirname, const string_vector& skip)
1923{
1924 std::string retval;
1925
1926 dir_entry dir (dirname);
1927
1928 if (dir)
1929 {
1930 retval = dirname;
1931
1932 string_vector dirlist = dir.read ();
1933
1934 octave_idx_type len = dirlist.length ();
1935
1936 for (octave_idx_type i = 0; i < len; i++)
1937 {
1938 std::string elt = dirlist[i];
1939
1940 bool skip_p = (elt == "." || elt == ".." || elt[0] == '@');
1941
1942 if (! skip_p)
1943 {
1944 for (octave_idx_type j = 0; j < skip.length (); j++)
1945 {
1946 skip_p = (elt == skip[j]);
1947 if (skip_p)
1948 break;
1949 }
1950
1951 if (! skip_p)
1952 {
1953 std::string nm = file_ops::concat (dirname, elt);
1954
1955 file_stat fs (nm);
1956
1957 if (fs && fs.is_dir ())
1958 retval += dir_path::path_sep_str () + genpath (nm, skip);
1959 }
1960 }
1961 }
1962 }
1963
1964 return retval;
1965}
1966
1967static void
1968execute_pkg_add_or_del (const std::string& dir,
1969 const std::string& script_file)
1970{
1971 if (! octave_interpreter_ready)
1972 return;
1973
1974 unwind_protect frame;
1975
1976 std::string file = file_ops::concat (dir, script_file);
1977
1978 file_stat fs (file);
1979
1980 if (fs.exists ())
1981 source_file (file, "base");
1982}
1983
1984void
1985execute_pkg_add (const std::string& dir)
1986{
1987 execute_pkg_add_or_del (dir, "PKG_ADD");
1988}
1989
1990void
1991execute_pkg_del (const std::string& dir)
1992{
1993 execute_pkg_add_or_del (dir, "PKG_DEL");
1994}
1995
1996DEFUN (genpath, args, ,octave_value_list Fgenpath (const octave_value_list& args
, int )
1997 "-*- texinfo -*-\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
1998@deftypefn {Built-in Function} {} genpath (@var{dir})\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
1999@deftypefnx {Built-in Function} {} genpath (@var{dir}, @var{skip}, @dots{})\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
2000Return a path constructed from @var{dir} and all its subdirectories.\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
2001If additional string parameters are given, the resulting path will\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
2002exclude directories with those names.\n\octave_value_list Fgenpath (const octave_value_list& args
, int )
2003@end deftypefn")octave_value_list Fgenpath (const octave_value_list& args
, int )
2004{
2005 octave_value retval;
2006
2007 octave_idx_type nargin = args.length ();
2008
2009 if (nargin == 1)
2010 {
2011 std::string dirname = args(0).string_value ();
2012
2013 if (! error_state)
2014 retval = genpath (dirname);
2015 else
2016 error ("genpath: DIR must be a character string");
2017 }
2018 else if (nargin > 1)
2019 {
2020 std::string dirname = args(0).string_value ();
2021
2022 string_vector skip (nargin - 1);
2023
2024 for (octave_idx_type i = 1; i < nargin; i++)
2025 {
2026 skip[i-1] = args(i).string_value ();
2027
2028 if (error_state)
2029 break;
2030 }
2031
2032 if (! error_state)
2033 retval = genpath (dirname, skip);
2034 else
2035 error ("genpath: all arguments must be character strings");
2036 }
2037 else
2038 print_usage ();
2039
2040 return retval;
2041}
2042
2043static void
2044rehash_internal (void)
2045{
2046 load_path::update ();
2047
2048 // FIXME: maybe we should rename this variable since it is being
2049 // used for more than keeping track of the prompt time.
2050
2051 // This will force updated functions to be found.
2052 Vlast_prompt_time.stamp ();
2053}
2054
2055DEFUN (rehash, , ,octave_value_list Frehash (const octave_value_list& , int
)
2056 "-*- texinfo -*-\n\octave_value_list Frehash (const octave_value_list& , int
)
2057@deftypefn {Built-in Function} {} rehash ()\n\octave_value_list Frehash (const octave_value_list& , int
)
2058Reinitialize Octave's load path directory cache.\n\octave_value_list Frehash (const octave_value_list& , int
)
2059@end deftypefn")octave_value_list Frehash (const octave_value_list& , int
)
2060{
2061 octave_value_list retval;
2062
2063 rehash_internal ();
2064
2065 return retval;
2066}
2067
2068DEFUN (command_line_path, , ,octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2069 "-*- texinfo -*-\n\octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2070@deftypefn {Built-in Function} {} command_line_path (@dots{})\n\octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2071Return the command line path variable.\n\octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2072\n\octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2073@seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}\n\octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2074@end deftypefn")octave_value_list Fcommand_line_path (const octave_value_list
& , int )
2075{
2076 return octave_value (load_path::get_command_line_path ());
2077}
2078
2079DEFUN (restoredefaultpath, , ,octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2080 "-*- texinfo -*-\n\octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2081@deftypefn {Built-in Function} {} restoredefaultpath (@dots{})\n\octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2082Restore Octave's path to its initial state at startup.\n\octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2083\n\octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2084@seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}\n\octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2085@end deftypefn")octave_value_list Frestoredefaultpath (const octave_value_list
& , int )
2086{
2087 load_path::initialize (true);
2088
2089 return octave_value (load_path::system_path ());
2090}
2091
2092// Return Octave's original default list of directories in which to
2093// search for function files. This corresponds to the path that
2094// exists prior to running the system's octaverc file or the user's
2095// ~/.octaverc file
2096
2097DEFUN (__pathorig__, , ,octave_value_list F__pathorig__ (const octave_value_list&
, int )
2098 "-*- texinfo -*-\n\octave_value_list F__pathorig__ (const octave_value_list&
, int )
2099@deftypefn {Built-in Function} {@var{val} =} __pathorig__ ()\n\octave_value_list F__pathorig__ (const octave_value_list&
, int )
2100Undocumented internal function.\n\octave_value_list F__pathorig__ (const octave_value_list&
, int )
2101@end deftypefn")octave_value_list F__pathorig__ (const octave_value_list&
, int )
2102{
2103 return octave_value (load_path::system_path ());
2104}
2105
2106DEFUN (path, args, nargout,octave_value_list Fpath (const octave_value_list& args, int
nargout)
2107 "-*- texinfo -*-\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2108@deftypefn {Built-in Function} {} path (@dots{})\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2109Modify or display Octave's load path.\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2110\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2111If @var{nargin} and @var{nargout} are zero, display the elements of\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2112Octave's load path in an easy to read format.\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2113\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2114If @var{nargin} is zero and nargout is greater than zero, return the\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2115current load path.\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2116\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2117If @var{nargin} is greater than zero, concatenate the arguments,\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2118separating them with @code{pathsep}. Set the internal search path\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2119to the result and return it.\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2120\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2121No checks are made for duplicate elements.\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2122@seealso{addpath, rmpath, genpath, pathdef, savepath, pathsep}\n\octave_value_list Fpath (const octave_value_list& args, int
nargout)
2123@end deftypefn")octave_value_list Fpath (const octave_value_list& args, int
nargout)
2124{
2125 octave_value retval;
2126
2127 int argc = args.length () + 1;
2128
2129 string_vector argv = args.make_argv ("path");
2130
2131 if (! error_state)
2132 {
2133 if (argc > 1)
2134 {
2135 std::string path = argv[1];
2136
2137 for (int i = 2; i < argc; i++)
2138 path += dir_path::path_sep_str () + argv[i];
2139
2140 load_path::set (path, true);
2141
2142 rehash_internal ();
2143 }
2144
2145 if (nargout > 0)
2146 retval = load_path::path ();
2147 else if (argc == 1 && nargout == 0)
2148 {
2149 octave_stdout(octave_pager_stream::stream ()) <<
2150 "\nOctave's search path contains the following directories:\n\n";
2151
2152 string_vector dirs = load_path::dirs ();
2153
2154 dirs.list_in_columns (octave_stdout(octave_pager_stream::stream ()));
2155
2156 octave_stdout(octave_pager_stream::stream ()) << "\n";
2157 }
2158 }
2159
2160 return retval;
2161}
2162
2163DEFUN (addpath, args, nargout,octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2164 "-*- texinfo -*-\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2165@deftypefn {Built-in Function} {} addpath (@var{dir1}, @dots{})\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2166@deftypefnx {Built-in Function} {} addpath (@var{dir1}, @dots{}, @var{option})\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2167Add named directories to the function search path. If\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2168@var{option} is @qcode{\"-begin\"} or 0 (the default), prepend the\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2169directory name to the current path. If @var{option} is @qcode{\"-end\"}\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2170or 1, append the directory name to the current path.\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2171Directories added to the path must exist.\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2172\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2173In addition to accepting individual directory arguments, lists of\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2174directory names separated by @code{pathsep} are also accepted. For example:\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2175\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2176@example\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2177addpath (\"dir1:/dir2:~/dir3\")\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2178@end example\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2179@seealso{path, rmpath, genpath, pathdef, savepath, pathsep}\n\octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2180@end deftypefn")octave_value_list Faddpath (const octave_value_list& args
, int nargout)
2181{
2182 octave_value retval;
2183
2184 // Originally written by Bill Denney and Etienne Grossman. Heavily
2185 // modified and translated to C++ by jwe.
2186
2187 if (nargout > 0)
2188 retval = load_path::path ();
2189
2190 int nargin = args.length ();
2191
2192 if (nargin > 0)
2193 {
2194 bool append = false;
2195
2196 octave_value option_arg = args(nargin-1);
2197
2198 if (option_arg.is_string ())
2199 {
2200 std::string option = option_arg.string_value ();
2201
2202 if (option == "-end")
2203 {
2204 append = true;
2205 nargin--;
2206 }
2207 else if (option == "-begin")
2208 nargin--;
2209 }
2210 else if (option_arg.is_numeric_type ())
2211 {
2212 int val = option_arg.int_value ();
2213
2214 if (! error_state)
2215 {
2216 if (val == 0)
2217 nargin--;
2218 else if (val == 1)
2219 {
2220 append = true;
2221 nargin--;
2222 }
2223 else
2224 {
2225 error ("addpath: expecting final argument to be 1 or 0");
2226 return retval;
2227 }
2228 }
2229 else
2230 {
2231 error ("addpath: expecting final argument to be 1 or 0");
2232 return retval;
2233 }
2234 }
2235
2236 bool need_to_update = false;
2237
2238 for (int i = 0; i < nargin; i++)
2239 {
2240 std::string arg = args(i).string_value ();
2241
2242 if (! error_state)
2243 {
2244 std::list<std::string> dir_elts = split_path (arg);
2245
2246 if (! append)
2247 std::reverse (dir_elts.begin (), dir_elts.end ());
2248
2249 for (std::list<std::string>::const_iterator p = dir_elts.begin ();
2250 p != dir_elts.end ();
2251 p++)
2252 {
2253 std::string dir = *p;
2254
2255 //dir = regexprep (dir_elts{j}, '//+', "/");
2256 //dir = regexprep (dir, '/$', "");
2257
2258 if (append)
2259 load_path::append (dir, true);
2260 else
2261 load_path::prepend (dir, true);
2262
2263 need_to_update = true;
2264 }
2265 }
2266 else
2267 error ("addpath: all arguments must be character strings");
2268 }
2269
2270 if (need_to_update)
2271 rehash_internal ();
2272 }
2273 else
2274 print_usage ();
2275
2276 return retval;
2277}
2278
2279DEFUN (rmpath, args, nargout,octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2280 "-*- texinfo -*-\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2281@deftypefn {Built-in Function} {} rmpath (@var{dir1}, @dots{})\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2282Remove @var{dir1}, @dots{} from the current function search path.\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2283\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2284In addition to accepting individual directory arguments, lists of\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2285directory names separated by @code{pathsep} are also accepted. For example:\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2286\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2287@example\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2288rmpath (\"dir1:/dir2:~/dir3\")\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2289@end example\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2290@seealso{path, addpath, genpath, pathdef, savepath, pathsep}\n\octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2291@end deftypefn")octave_value_list Frmpath (const octave_value_list& args,
int nargout)
2292{
2293 // Originally by Etienne Grossmann. Heavily modified and translated
2294 // to C++ by jwe.
2295
2296 octave_value retval;
2297
2298 if (nargout > 0)
2299 retval = load_path::path ();
2300
2301 int nargin = args.length ();
2302
2303 if (nargin > 0)
2304 {
2305 bool need_to_update = false;
2306
2307 for (int i = 0; i < nargin; i++)
2308 {
2309 std::string arg = args(i).string_value ();
2310
2311 if (! error_state)
2312 {
2313 std::list<std::string> dir_elts = split_path (arg);
2314
2315 for (std::list<std::string>::const_iterator p = dir_elts.begin ();
2316 p != dir_elts.end ();
2317 p++)
2318 {
2319 std::string dir = *p;
2320
2321 //dir = regexprep (dir_elts{j}, '//+', "/");
2322 //dir = regexprep (dir, '/$', "");
2323
2324 if (! load_path::remove (dir))
2325 warning ("rmpath: %s: not found", dir.c_str ());
2326 else
2327 need_to_update = true;
2328 }
2329 }
2330 else
2331 error ("addpath: all arguments must be character strings");
2332 }
2333
2334 if (need_to_update)
2335 rehash_internal ();
2336 }
2337 else
2338 print_usage ();
2339
2340 return retval;
2341}