File: | libinterp/corefcn/load-path.cc |
Location: | line 1574, column 7 |
Description: | Value stored to 'printed_type' is never read |
1 | /* |
2 | |
3 | Copyright (C) 2006-2013 John W. Eaton |
4 | Copyright (C) 2010 VZLU Prague |
5 | |
6 | This file is part of Octave. |
7 | |
8 | Octave is free software; you can redistribute it and/or modify it |
9 | under the terms of the GNU General Public License as published by the |
10 | Free Software Foundation; either version 3 of the License, or (at your |
11 | option) any later version. |
12 | |
13 | Octave is distributed in the hope that it will be useful, but WITHOUT |
14 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
16 | for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along 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 | |
47 | load_path *load_path::instance = 0; |
48 | load_path::hook_fcn_ptr load_path::add_hook = execute_pkg_add; |
49 | load_path::hook_fcn_ptr load_path::remove_hook = execute_pkg_del; |
50 | std::string load_path::command_line_path; |
51 | std::string load_path::sys_path; |
52 | load_path::abs_dir_cache_type load_path::abs_dir_cache; |
53 | |
54 | void |
55 | load_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 | |
111 | void |
112 | load_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 | |
151 | void |
152 | load_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 | |
217 | load_path::dir_info::fcn_file_map_type |
218 | get_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 | |
269 | void |
270 | load_path::dir_info::get_private_file_map (const std::string& d) |
271 | { |
272 | private_file_map = get_fcn_files (d); |
273 | } |
274 | |
275 | void |
276 | load_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 | |
289 | bool |
290 | load_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 | |
314 | load_path::const_dir_info_list_iterator |
315 | load_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 | |
332 | load_path::dir_info_list_iterator |
333 | load_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 | |
350 | bool |
351 | load_path::contains (const std::string& dir) const |
352 | { |
353 | return find_dir_info (dir) != dir_info_list.end (); |
354 | } |
355 | |
356 | bool |
357 | load_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 | |
375 | void |
376 | load_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 | |
424 | void |
425 | load_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 | |
468 | void |
469 | load_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 | |
492 | static void |
493 | maybe_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 | |
506 | void |
507 | load_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 | |
543 | void |
544 | load_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 | |
552 | static std::list<std::string> |
553 | split_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 | |
585 | void |
586 | load_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 | |
638 | void |
639 | load_path::do_append (const std::string& dir, bool warn) |
640 | { |
641 | if (! dir.empty ()) |
642 | do_add (dir, true, warn); |
643 | } |
644 | |
645 | void |
646 | load_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 | |
654 | static std::string |
655 | strip_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 | |
670 | void |
671 | load_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 | |
732 | void |
733 | load_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 | |
772 | void |
773 | load_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 | |
781 | void |
782 | load_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 | |
821 | bool |
822 | load_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 | |
866 | void |
867 | load_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 | |
895 | bool |
896 | load_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 | |
989 | std::string |
990 | load_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 | |
1044 | std::string |
1045 | load_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 | |
1074 | std::string |
1075 | load_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 | |
1122 | std::list<std::string> |
1123 | load_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 | |
1145 | std::list<std::string> |
1146 | load_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 | |
1164 | std::string |
1165 | load_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 | |
1215 | std::string |
1216 | load_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 | |
1262 | string_vector |
1263 | load_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 | |
1309 | std::string |
1310 | load_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 | |
1380 | done: |
1381 | |
1382 | if (! dir_name.empty ()) |
1383 | retval = file_ops::concat (dir_name, file_name); |
1384 | |
1385 | return retval; |
1386 | } |
1387 | |
1388 | string_vector |
1389 | load_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 | |
1457 | string_vector |
1458 | load_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 | |
1474 | std::list<std::string> |
1475 | load_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 | |
1487 | string_vector |
1488 | load_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 | |
1515 | string_vector |
1516 | load_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 | |
1532 | std::string |
1533 | load_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 | |
1550 | void |
1551 | print_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 | |
1578 | void |
1579 | print_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 | |
1594 | string_vector |
1595 | get_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 | |
1624 | void |
1625 | load_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 |
1726 | static bool |
1727 | in_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 | |
1745 | void |
1746 | load_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 | |
1841 | void |
1842 | load_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 | |
1850 | void |
1851 | load_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 | |
1921 | std::string |
1922 | genpath (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 | |
1967 | static void |
1968 | execute_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 | |
1984 | void |
1985 | execute_pkg_add (const std::string& dir) |
1986 | { |
1987 | execute_pkg_add_or_del (dir, "PKG_ADD"); |
1988 | } |
1989 | |
1990 | void |
1991 | execute_pkg_del (const std::string& dir) |
1992 | { |
1993 | execute_pkg_add_or_del (dir, "PKG_DEL"); |
1994 | } |
1995 | |
1996 | DEFUN (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 ) |
2000 | Return a path constructed from @var{dir} and all its subdirectories.\n\octave_value_list Fgenpath (const octave_value_list& args , int ) |
2001 | If additional string parameters are given, the resulting path will\n\octave_value_list Fgenpath (const octave_value_list& args , int ) |
2002 | exclude 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 | |
2043 | static void |
2044 | rehash_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 | |
2055 | DEFUN (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 ) |
2058 | Reinitialize 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 | |
2068 | DEFUN (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 ) |
2071 | Return 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 | |
2079 | DEFUN (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 ) |
2082 | Restore 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 | |
2097 | DEFUN (__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 ) |
2100 | Undocumented 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 | |
2106 | DEFUN (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) |
2109 | Modify 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) |
2111 | If @var{nargin} and @var{nargout} are zero, display the elements of\n\octave_value_list Fpath (const octave_value_list& args, int nargout) |
2112 | Octave'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) |
2114 | If @var{nargin} is zero and nargout is greater than zero, return the\n\octave_value_list Fpath (const octave_value_list& args, int nargout) |
2115 | current 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) |
2117 | If @var{nargin} is greater than zero, concatenate the arguments,\n\octave_value_list Fpath (const octave_value_list& args, int nargout) |
2118 | separating them with @code{pathsep}. Set the internal search path\n\octave_value_list Fpath (const octave_value_list& args, int nargout) |
2119 | to 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) |
2121 | No 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 | |
2163 | DEFUN (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) |
2167 | Add 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) |
2169 | directory name to the current path. If @var{option} is @qcode{\"-end\"}\n\octave_value_list Faddpath (const octave_value_list& args , int nargout) |
2170 | or 1, append the directory name to the current path.\n\octave_value_list Faddpath (const octave_value_list& args , int nargout) |
2171 | Directories 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) |
2173 | In addition to accepting individual directory arguments, lists of\n\octave_value_list Faddpath (const octave_value_list& args , int nargout) |
2174 | directory 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) |
2177 | addpath (\"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 | |
2279 | DEFUN (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) |
2282 | Remove @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) |
2284 | In addition to accepting individual directory arguments, lists of\n\octave_value_list Frmpath (const octave_value_list& args, int nargout) |
2285 | directory 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) |
2288 | rmpath (\"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 | } |