Mercurial > octave-nkf
annotate src/load-path.cc @ 7961:a5d1e27ee1f4 ss-3-1-51
3.1.51 snapshot
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 22 Jul 2008 11:40:48 -0400 |
parents | 37ff0c21c17d |
children | dd5cc5016487 |
rev | line source |
---|---|
5832 | 1 /* |
2 | |
7017 | 3 Copyright (C) 2006, 2007 John W. Eaton |
5832 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
5832 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
5832 | 20 |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <algorithm> | |
28 | |
29 #include "dir-ops.h" | |
30 #include "file-ops.h" | |
31 #include "file-stat.h" | |
32 #include "oct-env.h" | |
33 #include "pathsearch.h" | |
34 | |
35 #include "defaults.h" | |
36 #include "defun.h" | |
37 #include "input.h" | |
38 #include "load-path.h" | |
39 #include "pager.h" | |
40 #include "parse.h" | |
41 #include "toplev.h" | |
42 #include "unwind-prot.h" | |
43 #include "utils.h" | |
44 | |
45 load_path *load_path::instance = 0; | |
7336 | 46 load_path::hook_fcn_ptr load_path::add_hook = execute_pkg_add; |
47 load_path::hook_fcn_ptr load_path::remove_hook = execute_pkg_del; | |
5832 | 48 std::string load_path::command_line_path; |
6630 | 49 std::string load_path::sys_path; |
5832 | 50 |
51 void | |
52 load_path::dir_info::update (void) | |
53 { | |
54 if (is_relative) | |
55 initialize (); | |
56 else | |
57 { | |
58 file_stat fs (dir_name); | |
59 | |
60 if (fs) | |
61 { | |
62 if (fs.mtime () != dir_mtime) | |
63 initialize (); | |
64 } | |
65 else | |
66 { | |
67 std::string msg = fs.error (); | |
68 warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ()); | |
69 } | |
70 } | |
71 } | |
72 | |
73 void | |
74 load_path::dir_info::initialize (void) | |
75 { | |
76 is_relative = ! octave_env::absolute_pathname (dir_name); | |
77 | |
78 file_stat fs (dir_name); | |
79 | |
80 if (fs) | |
81 { | |
82 dir_mtime = fs.mtime (); | |
83 | |
7336 | 84 get_file_list (dir_name); |
5832 | 85 } |
86 else | |
87 { | |
88 std::string msg = fs.error (); | |
89 warning ("load_path: %s: %s", dir_name.c_str (), msg.c_str ()); | |
90 } | |
91 } | |
92 | |
7336 | 93 void |
5832 | 94 load_path::dir_info::get_file_list (const std::string& d) |
95 { | |
96 dir_entry dir (d); | |
97 | |
98 if (dir) | |
99 { | |
100 string_vector flist = dir.read (); | |
101 | |
102 octave_idx_type len = flist.length (); | |
103 | |
104 all_files.resize (len); | |
105 fcn_files.resize (len); | |
106 | |
107 octave_idx_type all_files_count = 0; | |
108 octave_idx_type fcn_files_count = 0; | |
109 | |
110 for (octave_idx_type i = 0; i < len; i++) | |
111 { | |
112 std::string fname = flist[i]; | |
113 | |
7272 | 114 std::string full_name = file_ops::concat (d, fname); |
5832 | 115 |
116 file_stat fs (full_name); | |
117 | |
118 if (fs) | |
119 { | |
120 if (fs.is_dir ()) | |
121 { | |
7336 | 122 if (fname == "private") |
123 get_private_file_map (full_name); | |
124 else if (fname[0] == '@') | |
125 get_method_file_map (full_name, fname.substr (1)); | |
5832 | 126 } |
127 else | |
128 { | |
129 all_files[all_files_count++] = fname; | |
130 | |
131 size_t pos = fname.rfind ('.'); | |
132 | |
133 if (pos != NPOS) | |
134 { | |
135 std::string ext = fname.substr (pos); | |
136 | |
5864 | 137 if (ext == ".m" || ext == ".oct" || ext == ".mex") |
5832 | 138 { |
139 std::string base = fname.substr (0, pos); | |
140 | |
141 if (valid_identifier (base)) | |
142 fcn_files[fcn_files_count++] = fname; | |
143 } | |
144 } | |
145 } | |
146 } | |
147 } | |
148 | |
149 all_files.resize (all_files_count); | |
150 fcn_files.resize (fcn_files_count); | |
151 } | |
152 else | |
153 { | |
154 std::string msg = dir.error (); | |
155 warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); | |
156 } | |
157 } | |
158 | |
7336 | 159 load_path::dir_info::fcn_file_map_type |
160 get_fcn_files (const std::string& d) | |
5832 | 161 { |
7336 | 162 load_path::dir_info::fcn_file_map_type retval; |
163 | |
5832 | 164 dir_entry dir (d); |
165 | |
166 if (dir) | |
167 { | |
168 string_vector flist = dir.read (); | |
169 | |
170 octave_idx_type len = flist.length (); | |
171 | |
172 for (octave_idx_type i = 0; i < len; i++) | |
173 { | |
174 std::string fname = flist[i]; | |
175 | |
176 std::string ext; | |
177 std::string base = fname; | |
178 | |
179 size_t pos = fname.rfind ('.'); | |
180 | |
181 if (pos != NPOS) | |
182 { | |
183 base = fname.substr (0, pos); | |
184 ext = fname.substr (pos); | |
185 | |
186 if (valid_identifier (base)) | |
187 { | |
188 int t = 0; | |
189 | |
190 if (ext == ".m") | |
191 t = load_path::M_FILE; | |
192 else if (ext == ".oct") | |
193 t = load_path::OCT_FILE; | |
5864 | 194 else if (ext == ".mex") |
195 t = load_path::MEX_FILE; | |
5832 | 196 |
7336 | 197 retval[base] |= t; |
5832 | 198 } |
199 } | |
200 } | |
201 } | |
202 else | |
203 { | |
204 std::string msg = dir.error (); | |
205 warning ("load_path: %s: %s", d.c_str (), msg.c_str ()); | |
206 } | |
7336 | 207 |
208 return retval; | |
209 } | |
210 | |
211 void | |
212 load_path::dir_info::get_private_file_map (const std::string& d) | |
213 { | |
214 private_file_map = get_fcn_files (d); | |
215 } | |
216 | |
217 void | |
218 load_path::dir_info::get_method_file_map (const std::string& d, | |
219 const std::string& class_name) | |
220 { | |
221 method_file_map[class_name] = get_fcn_files (d); | |
5832 | 222 } |
223 | |
224 bool | |
225 load_path::instance_ok (void) | |
226 { | |
227 bool retval = true; | |
228 | |
229 if (! instance) | |
230 instance = new load_path (); | |
231 | |
232 if (! instance) | |
233 { | |
234 ::error ("unable to create load path object!"); | |
235 | |
236 retval = false; | |
237 } | |
238 | |
239 return retval; | |
240 } | |
241 | |
7336 | 242 // FIXME -- maybe we should also maintain a map to speed up this |
243 // method of access. | |
244 | |
5832 | 245 load_path::const_dir_info_list_iterator |
5919 | 246 load_path::find_dir_info (const std::string& dir_arg) const |
5832 | 247 { |
5919 | 248 std::string dir = file_ops::tilde_expand (dir_arg); |
249 | |
5832 | 250 const_dir_info_list_iterator retval = dir_info_list.begin (); |
251 | |
252 while (retval != dir_info_list.end ()) | |
253 { | |
254 if (retval->dir_name == dir) | |
255 break; | |
256 | |
257 retval++; | |
258 } | |
259 | |
260 return retval; | |
261 } | |
262 | |
263 load_path::dir_info_list_iterator | |
5919 | 264 load_path::find_dir_info (const std::string& dir_arg) |
5832 | 265 { |
5919 | 266 std::string dir = file_ops::tilde_expand (dir_arg); |
267 | |
5832 | 268 dir_info_list_iterator retval = dir_info_list.begin (); |
269 | |
270 while (retval != dir_info_list.end ()) | |
271 { | |
272 if (retval->dir_name == dir) | |
273 break; | |
274 | |
275 retval++; | |
276 } | |
277 | |
278 return retval; | |
279 } | |
280 | |
281 bool | |
282 load_path::contains (const std::string& dir) const | |
283 { | |
284 return find_dir_info (dir) != dir_info_list.end (); | |
285 } | |
286 | |
287 void | |
7336 | 288 load_path::move_fcn_map (const std::string& dir_name, |
289 const string_vector& fcn_files, bool at_end) | |
5832 | 290 { |
7336 | 291 octave_idx_type len = fcn_files.length (); |
292 | |
293 for (octave_idx_type k = 0; k < len; k++) | |
5832 | 294 { |
7336 | 295 std::string fname = fcn_files[k]; |
5832 | 296 |
7336 | 297 std::string ext; |
298 std::string base = fname; | |
299 | |
300 size_t pos = fname.rfind ('.'); | |
5832 | 301 |
7336 | 302 if (pos != NPOS) |
303 { | |
304 base = fname.substr (0, pos); | |
305 ext = fname.substr (pos); | |
306 } | |
5832 | 307 |
7336 | 308 file_info_list_type& file_info_list = fcn_map[base]; |
5832 | 309 |
7336 | 310 if (file_info_list.size () == 1) |
311 continue; | |
312 else | |
5832 | 313 { |
7336 | 314 for (file_info_list_iterator p = file_info_list.begin (); |
315 p != file_info_list.end (); | |
316 p++) | |
317 { | |
318 if (p->dir_name == dir_name) | |
319 { | |
320 file_info fi = *p; | |
5832 | 321 |
7336 | 322 file_info_list.erase (p); |
323 | |
324 if (at_end) | |
325 file_info_list.push_back (fi); | |
326 else | |
327 file_info_list.push_front (fi); | |
5832 | 328 |
7336 | 329 break; |
330 } | |
331 } | |
332 } | |
333 } | |
334 } | |
5832 | 335 |
7336 | 336 void |
337 load_path::move_method_map (const std::string& dir_name, bool at_end) | |
338 { | |
339 for (method_map_iterator i = method_map.begin (); | |
340 i != method_map.end (); | |
341 i++) | |
342 { | |
343 std::string class_name = i->first; | |
5832 | 344 |
7336 | 345 fcn_map_type& fm = i->second; |
346 | |
347 std::string full_dir_name | |
348 = file_ops::concat (dir_name, "@" + class_name); | |
349 | |
350 for (fcn_map_iterator q = fm.begin (); q != fm.end (); q++) | |
351 { | |
352 file_info_list_type& file_info_list = q->second; | |
5832 | 353 |
354 if (file_info_list.size () == 1) | |
355 continue; | |
356 else | |
357 { | |
7336 | 358 for (file_info_list_iterator p = file_info_list.begin (); |
359 p != file_info_list.end (); | |
360 p++) | |
5832 | 361 { |
7336 | 362 if (p->dir_name == full_dir_name) |
5832 | 363 { |
6149 | 364 file_info fi = *p; |
5832 | 365 |
366 file_info_list.erase (p); | |
367 | |
368 if (at_end) | |
369 file_info_list.push_back (fi); | |
370 else | |
371 file_info_list.push_front (fi); | |
372 | |
373 break; | |
374 } | |
375 } | |
376 } | |
377 } | |
378 } | |
379 } | |
380 | |
7336 | 381 void |
382 load_path::move (dir_info_list_iterator i, bool at_end) | |
383 { | |
384 if (dir_info_list.size () > 1) | |
385 { | |
386 dir_info di = *i; | |
387 | |
388 dir_info_list.erase (i); | |
389 | |
390 if (at_end) | |
391 dir_info_list.push_back (di); | |
392 else | |
393 dir_info_list.push_front (di); | |
394 | |
395 std::string dir_name = di.dir_name; | |
396 | |
397 move_fcn_map (dir_name, di.fcn_files, at_end); | |
398 | |
399 // No need to move elements of private function map. | |
400 | |
401 move_method_map (dir_name, at_end); | |
402 } | |
403 } | |
404 | |
5832 | 405 static void |
406 maybe_add_path_elts (std::string& path, const std::string& dir) | |
407 { | |
408 std::string tpath = genpath (dir); | |
409 | |
410 if (! tpath.empty ()) | |
7374 | 411 { |
412 if (path.empty ()) | |
413 path = tpath; | |
414 else | |
415 path += dir_path::path_sep_str + tpath; | |
416 } | |
5832 | 417 } |
418 | |
419 void | |
6365 | 420 load_path::do_initialize (bool set_initial_path) |
5832 | 421 { |
7374 | 422 sys_path = ""; |
5832 | 423 |
6365 | 424 if (set_initial_path) |
425 { | |
6626 | 426 maybe_add_path_elts (sys_path, Vlocal_ver_oct_file_dir); |
427 maybe_add_path_elts (sys_path, Vlocal_api_oct_file_dir); | |
428 maybe_add_path_elts (sys_path, Vlocal_oct_file_dir); | |
429 maybe_add_path_elts (sys_path, Vlocal_ver_fcn_file_dir); | |
430 maybe_add_path_elts (sys_path, Vlocal_api_fcn_file_dir); | |
431 maybe_add_path_elts (sys_path, Vlocal_fcn_file_dir); | |
432 maybe_add_path_elts (sys_path, Voct_file_dir); | |
433 maybe_add_path_elts (sys_path, Vfcn_file_dir); | |
6365 | 434 } |
5832 | 435 |
436 std::string tpath = load_path::command_line_path; | |
437 | |
438 if (tpath.empty ()) | |
439 tpath = octave_env::getenv ("OCTAVE_LOADPATH"); | |
440 | |
441 std::string xpath = "."; | |
442 | |
443 if (! tpath.empty ()) | |
444 xpath += dir_path::path_sep_str + tpath; | |
445 | |
7374 | 446 if (! sys_path.empty ()) |
7786
37ff0c21c17d
load-path.cc (load_path::initialize): include separator when appending sys_path
Kim Hansen
parents:
7391
diff
changeset
|
447 xpath += dir_path::path_sep_str + sys_path; |
5832 | 448 |
6119 | 449 do_set (xpath, false); |
5832 | 450 } |
451 | |
452 void | |
453 load_path::do_clear (void) | |
454 { | |
455 dir_info_list.clear (); | |
456 fcn_map.clear (); | |
7336 | 457 private_fcn_map.clear (); |
458 method_map.clear (); | |
5867 | 459 |
460 do_append (".", false); | |
5832 | 461 } |
462 | |
463 static std::list<std::string> | |
464 split_path (const std::string& p) | |
465 { | |
466 std::list<std::string> retval; | |
467 | |
468 size_t beg = 0; | |
469 size_t end = p.find (dir_path::path_sep_char); | |
470 | |
471 size_t len = p.length (); | |
472 | |
473 while (end != NPOS) | |
474 { | |
475 std::string elt = p.substr (beg, end-beg); | |
476 | |
477 if (! elt.empty ()) | |
478 retval.push_back (elt); | |
479 | |
480 beg = end + 1; | |
481 | |
482 if (beg == len) | |
483 break; | |
484 | |
485 end = p.find (dir_path::path_sep_char, beg); | |
486 } | |
487 | |
488 std::string elt = p.substr (beg); | |
489 | |
490 if (! elt.empty ()) | |
491 retval.push_back (elt); | |
492 | |
493 return retval; | |
494 } | |
495 | |
496 void | |
5867 | 497 load_path::do_set (const std::string& p, bool warn) |
5832 | 498 { |
499 do_clear (); | |
500 | |
501 std::list<std::string> elts = split_path (p); | |
502 | |
503 // Temporarily disable add hook. | |
504 | |
5854 | 505 unwind_protect_fptr (add_hook); |
5832 | 506 |
507 add_hook = 0; | |
508 | |
509 for (std::list<std::string>::const_iterator i = elts.begin (); | |
510 i != elts.end (); | |
511 i++) | |
5867 | 512 do_append (*i, warn); |
5832 | 513 |
514 // Restore add hook and execute for all newly added directories. | |
515 | |
516 unwind_protect::run (); | |
517 | |
518 for (dir_info_list_iterator i = dir_info_list.begin (); | |
519 i != dir_info_list.end (); | |
520 i++) | |
521 { | |
522 if (add_hook) | |
523 add_hook (i->dir_name); | |
524 } | |
525 } | |
526 | |
527 void | |
5867 | 528 load_path::do_append (const std::string& dir, bool warn) |
5832 | 529 { |
530 if (! dir.empty ()) | |
5867 | 531 do_add (dir, true, warn); |
532 } | |
5832 | 533 |
5867 | 534 void |
535 load_path::do_prepend (const std::string& dir, bool warn) | |
536 { | |
537 if (! dir.empty ()) | |
538 do_add (dir, false, warn); | |
5832 | 539 } |
540 | |
541 void | |
5919 | 542 load_path::do_add (const std::string& dir_arg, bool at_end, bool warn) |
5832 | 543 { |
5919 | 544 size_t len = dir_arg.length (); |
5911 | 545 |
5919 | 546 if (len > 1 && dir_arg.substr (len-2) == "//") |
5911 | 547 warning_with_id ("Octave:recursive-path-search", |
548 "trailing `//' is no longer special in search path elements"); | |
549 | |
5919 | 550 std::string dir = file_ops::tilde_expand (dir_arg); |
551 | |
5867 | 552 dir_info_list_iterator i = find_dir_info (dir); |
553 | |
554 if (i != dir_info_list.end ()) | |
555 move (i, at_end); | |
556 else | |
5832 | 557 { |
5867 | 558 file_stat fs (dir); |
5832 | 559 |
5867 | 560 if (fs) |
5832 | 561 { |
5867 | 562 if (fs.is_dir ()) |
563 { | |
564 dir_info di (dir); | |
5832 | 565 |
5867 | 566 if (! error_state) |
567 { | |
568 if (at_end) | |
569 dir_info_list.push_back (di); | |
570 else | |
571 dir_info_list.push_front (di); | |
572 | |
573 add_to_fcn_map (di, true); | |
5832 | 574 |
7336 | 575 add_to_private_fcn_map (di); |
576 | |
577 add_to_method_map (di, true); | |
578 | |
5867 | 579 if (add_hook) |
580 add_hook (dir); | |
581 } | |
5832 | 582 } |
5867 | 583 else if (warn) |
5919 | 584 warning ("addpath: %s: not a directory", dir_arg.c_str ()); |
5832 | 585 } |
5867 | 586 else if (warn) |
587 { | |
588 std::string msg = fs.error (); | |
5919 | 589 warning ("addpath: %s: %s", dir_arg.c_str (), msg.c_str ()); |
5867 | 590 } |
591 } | |
5832 | 592 |
5867 | 593 // FIXME -- is there a better way to do this? |
5832 | 594 |
5867 | 595 i = find_dir_info ("."); |
5832 | 596 |
5867 | 597 if (i != dir_info_list.end ()) |
5871 | 598 move (i, false); |
5867 | 599 else |
600 panic_impossible (); | |
5832 | 601 } |
602 | |
7336 | 603 void |
604 load_path::remove_fcn_map (const std::string& dir, | |
605 const string_vector& fcn_files) | |
606 { | |
607 octave_idx_type len = fcn_files.length (); | |
608 | |
609 for (octave_idx_type k = 0; k < len; k++) | |
610 { | |
611 std::string fname = fcn_files[k]; | |
612 | |
613 std::string ext; | |
614 std::string base = fname; | |
615 | |
616 size_t pos = fname.rfind ('.'); | |
617 | |
618 if (pos != NPOS) | |
619 { | |
620 base = fname.substr (0, pos); | |
621 ext = fname.substr (pos); | |
622 } | |
623 | |
624 file_info_list_type& file_info_list = fcn_map[base]; | |
625 | |
626 for (file_info_list_iterator p = file_info_list.begin (); | |
627 p != file_info_list.end (); | |
628 p++) | |
629 { | |
630 if (p->dir_name == dir) | |
631 { | |
632 file_info_list.erase (p); | |
633 | |
634 if (file_info_list.empty ()) | |
635 fcn_map.erase (fname); | |
636 | |
637 break; | |
638 } | |
639 } | |
640 } | |
641 } | |
642 | |
643 void | |
644 load_path::remove_private_fcn_map (const std::string& dir) | |
645 { | |
646 private_fcn_map_iterator p = private_fcn_map.find (dir); | |
647 | |
648 if (p != private_fcn_map.end ()) | |
649 private_fcn_map.erase (p); | |
650 } | |
651 | |
652 void | |
653 load_path::remove_method_map (const std::string& dir) | |
654 { | |
655 for (method_map_iterator i = method_map.begin (); | |
656 i != method_map.end (); | |
657 i++) | |
658 { | |
659 std::string class_name = i->first; | |
660 | |
661 fcn_map_type& fm = i->second; | |
662 | |
663 std::string full_dir_name = file_ops::concat (dir, "@" + class_name); | |
664 | |
665 for (fcn_map_iterator q = fm.begin (); q != fm.end (); q++) | |
666 { | |
667 file_info_list_type& file_info_list = q->second; | |
668 | |
669 if (file_info_list.size () == 1) | |
670 continue; | |
671 else | |
672 { | |
673 for (file_info_list_iterator p = file_info_list.begin (); | |
674 p != file_info_list.end (); | |
675 p++) | |
676 { | |
677 if (p->dir_name == full_dir_name) | |
678 { | |
679 file_info_list.erase (p); | |
680 | |
681 // FIXME -- if there are no other elements, we | |
682 // should remove this element of fm but calling | |
683 // erase here would invalidate the iterator q. | |
684 | |
685 break; | |
686 } | |
687 } | |
688 } | |
689 } | |
690 } | |
691 } | |
692 | |
5832 | 693 bool |
5919 | 694 load_path::do_remove (const std::string& dir_arg) |
5832 | 695 { |
696 bool retval = false; | |
697 | |
5919 | 698 if (! dir_arg.empty ()) |
5832 | 699 { |
5919 | 700 if (dir_arg == ".") |
5867 | 701 { |
702 warning ("rmpath: can't remove \".\" from path"); | |
5832 | 703 |
5867 | 704 // Avoid additional warnings. |
5832 | 705 retval = true; |
5867 | 706 } |
707 else | |
708 { | |
5919 | 709 std::string dir = file_ops::tilde_expand (dir_arg); |
710 | |
5867 | 711 dir_info_list_iterator i = find_dir_info (dir); |
5832 | 712 |
5867 | 713 if (i != dir_info_list.end ()) |
714 { | |
715 retval = true; | |
5832 | 716 |
6825 | 717 if (remove_hook) |
718 remove_hook (dir); | |
719 | |
5867 | 720 string_vector fcn_files = i->fcn_files; |
721 | |
722 dir_info_list.erase (i); | |
5832 | 723 |
7336 | 724 remove_fcn_map (dir, fcn_files); |
5867 | 725 |
7336 | 726 remove_private_fcn_map (dir); |
5832 | 727 |
7336 | 728 remove_method_map (dir); |
5832 | 729 } |
730 } | |
731 } | |
732 | |
733 return retval; | |
734 } | |
735 | |
736 void | |
737 load_path::do_update (void) const | |
738 { | |
739 // I don't see a better way to do this because we need to | |
740 // preserve the correct directory ordering for new files that | |
741 // have appeared. | |
742 | |
743 fcn_map.clear (); | |
744 | |
7336 | 745 private_fcn_map.clear (); |
746 | |
747 method_map.clear (); | |
748 | |
5832 | 749 for (dir_info_list_iterator p = dir_info_list.begin (); |
750 p != dir_info_list.end (); | |
751 p++) | |
752 { | |
753 dir_info& di = *p; | |
754 | |
755 di.update (); | |
756 | |
757 add_to_fcn_map (di, true); | |
7336 | 758 |
759 add_to_private_fcn_map (di); | |
760 | |
761 add_to_method_map (di, true); | |
5832 | 762 } |
763 } | |
764 | |
7336 | 765 bool |
766 load_path::check_file_type (std::string& fname, int type, int possible_types, | |
767 const std::string& fcn, const char *who) | |
768 { | |
769 bool retval = false; | |
770 | |
771 if (type == load_path::OCT_FILE) | |
772 { | |
773 if ((type & possible_types) == load_path::OCT_FILE) | |
774 { | |
775 fname += ".oct"; | |
776 retval = true; | |
777 } | |
778 } | |
779 else if (type == load_path::M_FILE) | |
780 { | |
781 if ((type & possible_types) == load_path::M_FILE) | |
782 { | |
783 fname += ".m"; | |
784 retval = true; | |
785 } | |
786 } | |
787 else if (type == load_path::MEX_FILE) | |
788 { | |
789 if ((type & possible_types) == load_path::MEX_FILE) | |
790 { | |
791 fname += ".mex"; | |
792 retval = true; | |
793 } | |
794 } | |
795 else if (type == (load_path::M_FILE | load_path::OCT_FILE)) | |
796 { | |
797 if (possible_types & load_path::OCT_FILE) | |
798 { | |
799 fname += ".oct"; | |
800 retval = true; | |
801 } | |
802 else if (possible_types & load_path::M_FILE) | |
803 { | |
804 fname += ".m"; | |
805 retval = true; | |
806 } | |
807 } | |
808 else if (type == (load_path::M_FILE | load_path::MEX_FILE)) | |
809 { | |
810 if (possible_types & load_path::MEX_FILE) | |
811 { | |
812 fname += ".mex"; | |
813 retval = true; | |
814 } | |
815 else if (possible_types & load_path::M_FILE) | |
816 { | |
817 fname += ".m"; | |
818 retval = true; | |
819 } | |
820 } | |
821 else if (type == (load_path::OCT_FILE | load_path::MEX_FILE)) | |
822 { | |
823 if (possible_types & load_path::OCT_FILE) | |
824 { | |
825 fname += ".oct"; | |
826 retval = true; | |
827 } | |
828 else if (possible_types & load_path::MEX_FILE) | |
829 { | |
830 fname += ".mex"; | |
831 retval = true; | |
832 } | |
833 } | |
834 else if (type == (load_path::M_FILE | load_path::OCT_FILE | |
835 | load_path::MEX_FILE)) | |
836 { | |
837 if (possible_types & load_path::OCT_FILE) | |
838 { | |
839 fname += ".oct"; | |
840 retval = true; | |
841 } | |
842 else if (possible_types & load_path::MEX_FILE) | |
843 { | |
844 fname += ".mex"; | |
845 retval = true; | |
846 } | |
847 else if (possible_types & load_path::M_FILE) | |
848 { | |
849 fname += ".m"; | |
850 retval = true; | |
851 } | |
852 } | |
853 else | |
854 error ("%s: %s: invalid type code = %d", who, fcn.c_str (), type); | |
855 | |
856 return retval; | |
857 } | |
858 | |
5832 | 859 std::string |
7336 | 860 load_path::do_find_fcn (const std::string& fcn, std::string& dir_name, |
861 int type) const | |
5832 | 862 { |
863 std::string retval; | |
7336 | 864 |
865 // update (); | |
5832 | 866 |
7336 | 867 dir_name = std::string (); |
5832 | 868 |
869 const_fcn_map_iterator p = fcn_map.find (fcn); | |
870 | |
871 if (p != fcn_map.end ()) | |
872 { | |
7336 | 873 const file_info_list_type& file_info_list = p->second; |
5832 | 874 |
875 for (const_file_info_list_iterator i = file_info_list.begin (); | |
876 i != file_info_list.end (); | |
877 i++) | |
878 { | |
879 const file_info& fi = *i; | |
880 | |
7272 | 881 retval = file_ops::concat (fi.dir_name, fcn); |
5832 | 882 |
7336 | 883 if (check_file_type (retval, type, fi.types, |
884 fcn, "load_path::do_find_fcn")) | |
5832 | 885 { |
7336 | 886 dir_name = fi.dir_name; |
887 break; | |
5832 | 888 } |
7336 | 889 else |
890 retval = std::string (); | |
891 } | |
892 } | |
893 | |
894 return retval; | |
895 } | |
896 | |
897 std::string | |
898 load_path::do_find_private_fcn (const std::string& dir, | |
899 const std::string& fcn, int type) const | |
900 { | |
901 std::string retval; | |
902 | |
903 // update (); | |
904 | |
905 const_private_fcn_map_iterator q = private_fcn_map.find (dir); | |
906 | |
907 if (q != private_fcn_map.end ()) | |
908 { | |
909 const dir_info::fcn_file_map_type& m = q->second; | |
910 | |
911 dir_info::const_fcn_file_map_iterator p = m.find (fcn); | |
912 | |
913 if (p != m.end ()) | |
914 { | |
915 std::string fname | |
916 = file_ops::concat (file_ops::concat (dir, "private"), fcn); | |
917 | |
918 if (check_file_type (fname, type, p->second, fcn, | |
919 "load_path::find_private_fcn")) | |
920 retval = fname; | |
921 } | |
922 } | |
923 | |
924 return retval; | |
925 } | |
926 | |
927 std::string | |
928 load_path::do_find_method (const std::string& class_name, | |
929 const std::string& meth, | |
930 std::string& dir_name, int type) const | |
931 { | |
932 std::string retval; | |
933 | |
934 // update (); | |
935 | |
936 dir_name = std::string (); | |
937 | |
938 const_method_map_iterator q = method_map.find (class_name); | |
939 | |
940 if (q != method_map.end ()) | |
941 { | |
942 const fcn_map_type& m = q->second; | |
943 | |
944 const_fcn_map_iterator p = m.find (meth); | |
945 | |
946 if (p != m.end ()) | |
947 { | |
948 const file_info_list_type& file_info_list = p->second; | |
949 | |
950 for (const_file_info_list_iterator i = file_info_list.begin (); | |
951 i != file_info_list.end (); | |
952 i++) | |
5864 | 953 { |
7336 | 954 const file_info& fi = *i; |
955 | |
956 retval = file_ops::concat (fi.dir_name, meth); | |
957 | |
958 bool found = check_file_type (retval, type, fi.types, | |
959 meth, "load_path::do_find_method"); | |
960 | |
961 if (found) | |
5864 | 962 { |
7336 | 963 dir_name = fi.dir_name; |
5832 | 964 break; |
965 } | |
7336 | 966 else |
967 retval = std::string (); | |
5864 | 968 } |
5832 | 969 } |
970 } | |
971 | |
972 return retval; | |
973 } | |
974 | |
7336 | 975 std::list<std::string> |
976 load_path::do_methods (const std::string& class_name) const | |
977 { | |
978 std::list<std::string> retval; | |
979 | |
980 // update (); | |
981 | |
982 const_method_map_iterator q = method_map.find (class_name); | |
983 | |
984 if (q != method_map.end ()) | |
985 { | |
986 const fcn_map_type& m = q->second; | |
987 | |
988 for (const_fcn_map_iterator p = m.begin (); p != m.end (); p++) | |
989 retval.push_back (p->first); | |
990 } | |
991 | |
992 if (! retval.empty ()) | |
993 retval.sort (); | |
994 | |
995 return retval; | |
996 } | |
997 | |
5832 | 998 std::string |
999 load_path::do_find_file (const std::string& file) const | |
1000 { | |
1001 std::string retval; | |
1002 | |
6850 | 1003 if (file.find_first_of (file_ops::dir_sep_chars) != NPOS) |
5832 | 1004 { |
6838 | 1005 if (octave_env::absolute_pathname (file) |
1006 || octave_env::rooted_relative_pathname (file)) | |
1007 { | |
1008 file_stat fs (file); | |
5832 | 1009 |
6838 | 1010 if (fs.exists ()) |
1011 return file; | |
1012 } | |
1013 else | |
1014 { | |
1015 for (const_dir_info_list_iterator p = dir_info_list.begin (); | |
1016 p != dir_info_list.end (); | |
1017 p++) | |
1018 { | |
7272 | 1019 std::string tfile = file_ops::concat (p->dir_name, file); |
5832 | 1020 |
6838 | 1021 file_stat fs (tfile); |
6159 | 1022 |
6838 | 1023 if (fs.exists ()) |
1024 return tfile; | |
5832 | 1025 } |
1026 } | |
1027 } | |
6838 | 1028 else |
1029 { | |
1030 for (const_dir_info_list_iterator p = dir_info_list.begin (); | |
1031 p != dir_info_list.end (); | |
1032 p++) | |
1033 { | |
1034 string_vector all_files = p->all_files; | |
6159 | 1035 |
6838 | 1036 octave_idx_type len = all_files.length (); |
1037 | |
1038 for (octave_idx_type i = 0; i < len; i++) | |
1039 { | |
1040 if (all_files[i] == file) | |
7272 | 1041 return file_ops::concat (p->dir_name, file); |
6838 | 1042 } |
1043 } | |
1044 } | |
5832 | 1045 |
1046 return retval; | |
1047 } | |
1048 | |
1049 std::string | |
1050 load_path::do_find_first_of (const string_vector& flist) const | |
1051 { | |
1052 std::string retval; | |
1053 | |
1054 std::string dir_name; | |
1055 std::string file_name; | |
1056 | |
1057 octave_idx_type flen = flist.length (); | |
1058 octave_idx_type rel_flen = 0; | |
1059 | |
1060 string_vector rel_flist (flen); | |
1061 | |
1062 for (octave_idx_type i = 0; i < flen; i++) | |
1063 { | |
1064 if (octave_env::absolute_pathname (flist[i])) | |
1065 { | |
1066 file_stat fs (flist[i]); | |
1067 | |
1068 if (fs.exists ()) | |
1069 return flist[i]; | |
1070 } | |
1071 else | |
1072 rel_flist[rel_flen++] = flist[i]; | |
1073 } | |
1074 | |
1075 rel_flist.resize (rel_flen); | |
1076 | |
1077 for (const_dir_info_list_iterator p = dir_info_list.begin (); | |
1078 p != dir_info_list.end (); | |
1079 p++) | |
1080 { | |
1081 string_vector all_files = p->all_files; | |
1082 | |
1083 octave_idx_type len = all_files.length (); | |
1084 | |
1085 for (octave_idx_type i = 0; i < len; i++) | |
1086 { | |
1087 for (octave_idx_type j = 0; j < rel_flen; j++) | |
1088 { | |
1089 if (all_files[i] == rel_flist[j]) | |
1090 { | |
1091 dir_name = p->dir_name; | |
1092 file_name = rel_flist[j]; | |
6159 | 1093 |
1094 goto done; | |
5832 | 1095 } |
1096 } | |
1097 } | |
1098 } | |
1099 | |
6159 | 1100 done: |
1101 | |
5832 | 1102 if (! dir_name.empty ()) |
7272 | 1103 retval = file_ops::concat (dir_name, file_name); |
5832 | 1104 |
1105 return retval; | |
1106 } | |
1107 | |
1108 string_vector | |
1109 load_path::do_find_all_first_of (const string_vector& flist) const | |
1110 { | |
1111 std::list<std::string> retlist; | |
1112 | |
1113 std::string dir_name; | |
1114 std::string file_name; | |
1115 | |
1116 octave_idx_type flen = flist.length (); | |
1117 octave_idx_type rel_flen = 0; | |
1118 | |
1119 string_vector rel_flist (flen); | |
1120 | |
1121 for (octave_idx_type i = 0; i < flen; i++) | |
1122 { | |
1123 if (octave_env::absolute_pathname (flist[i])) | |
1124 { | |
1125 file_stat fs (flist[i]); | |
1126 | |
1127 if (fs.exists ()) | |
1128 retlist.push_back (flist[i]); | |
1129 } | |
1130 else | |
1131 rel_flist[rel_flen++] = flist[i]; | |
1132 } | |
1133 | |
1134 rel_flist.resize (rel_flen); | |
1135 | |
1136 for (const_dir_info_list_iterator p = dir_info_list.begin (); | |
1137 p != dir_info_list.end (); | |
1138 p++) | |
1139 { | |
1140 string_vector all_files = p->all_files; | |
1141 | |
1142 octave_idx_type len = all_files.length (); | |
1143 | |
1144 for (octave_idx_type i = 0; i < len; i++) | |
1145 { | |
1146 for (octave_idx_type j = 0; j < rel_flen; j++) | |
1147 { | |
1148 if (all_files[i] == rel_flist[j]) | |
1149 retlist.push_back | |
7272 | 1150 (file_ops::concat (p->dir_name, rel_flist[j])); |
5832 | 1151 } |
1152 } | |
1153 } | |
1154 | |
1155 size_t retsize = retlist.size (); | |
1156 | |
1157 string_vector retval (retsize); | |
1158 | |
1159 for (size_t i = 0; i < retsize; i++) | |
1160 { | |
1161 retval[i] = retlist.front (); | |
1162 | |
1163 retlist.pop_front (); | |
1164 } | |
1165 | |
1166 return retval; | |
1167 } | |
1168 | |
1169 string_vector | |
1170 load_path::do_dirs (void) const | |
1171 { | |
1172 size_t len = dir_info_list.size (); | |
1173 | |
1174 string_vector retval (len); | |
1175 | |
1176 octave_idx_type k = 0; | |
1177 | |
1178 for (const_dir_info_list_iterator i = dir_info_list.begin (); | |
1179 i != dir_info_list.end (); | |
1180 i++) | |
1181 retval[k++] = i->dir_name; | |
1182 | |
1183 return retval; | |
1184 } | |
1185 | |
1186 std::list<std::string> | |
1187 load_path::do_dir_list (void) const | |
1188 { | |
1189 std::list<std::string> retval; | |
1190 | |
1191 for (const_dir_info_list_iterator i = dir_info_list.begin (); | |
1192 i != dir_info_list.end (); | |
1193 i++) | |
1194 retval.push_back (i->dir_name); | |
1195 | |
1196 return retval; | |
1197 } | |
1198 | |
1199 string_vector | |
1200 load_path::do_files (const std::string& dir) const | |
1201 { | |
1202 string_vector retval; | |
1203 | |
1204 const_dir_info_list_iterator i = find_dir_info (dir); | |
1205 | |
1206 if (i != dir_info_list.end ()) | |
1207 retval = i->fcn_files; | |
1208 | |
1209 return retval; | |
1210 } | |
1211 | |
1212 string_vector | |
1213 load_path::do_fcn_names (void) const | |
1214 { | |
1215 size_t len = fcn_map.size (); | |
1216 | |
1217 string_vector retval (len); | |
1218 | |
1219 octave_idx_type count = 0; | |
1220 | |
1221 for (const_fcn_map_iterator p = fcn_map.begin (); | |
1222 p != fcn_map.end (); | |
1223 p++) | |
1224 retval[count++] = p->first; | |
1225 | |
1226 return retval; | |
1227 } | |
1228 | |
1229 std::string | |
1230 load_path::do_path (void) const | |
1231 { | |
1232 std::string xpath; | |
1233 | |
1234 string_vector xdirs = load_path::dirs (); | |
1235 | |
1236 octave_idx_type len = xdirs.length (); | |
1237 | |
1238 if (len > 0) | |
1239 xpath = xdirs[0]; | |
1240 | |
1241 for (octave_idx_type i = 1; i < len; i++) | |
1242 xpath += dir_path::path_sep_str + xdirs[i]; | |
1243 | |
1244 return xpath; | |
1245 } | |
1246 | |
1247 void | |
7336 | 1248 print_types (std::ostream& os, int types) |
1249 { | |
1250 bool printed_type = false; | |
1251 | |
1252 if (types & load_path::OCT_FILE) | |
1253 { | |
1254 os << "oct"; | |
1255 printed_type = true; | |
1256 } | |
1257 | |
1258 if (types & load_path::MEX_FILE) | |
1259 { | |
1260 if (printed_type) | |
1261 os << "|"; | |
1262 os << "mex"; | |
1263 printed_type = true; | |
1264 } | |
1265 | |
1266 if (types & load_path::M_FILE) | |
1267 { | |
1268 if (printed_type) | |
1269 os << "|"; | |
1270 os << "m"; | |
1271 printed_type = true; | |
1272 } | |
1273 } | |
1274 | |
1275 void | |
1276 print_fcn_list (std::ostream& os, | |
1277 const load_path::dir_info::fcn_file_map_type& lst) | |
1278 { | |
1279 for (load_path::dir_info::const_fcn_file_map_iterator p = lst.begin (); | |
1280 p != lst.end (); | |
1281 p++) | |
1282 { | |
1283 os << " " << p->first << " ("; | |
1284 | |
1285 print_types (os, p->second); | |
1286 | |
1287 os << ")\n"; | |
1288 } | |
1289 } | |
1290 | |
1291 string_vector | |
1292 get_file_list (const load_path::dir_info::fcn_file_map_type& lst) | |
1293 { | |
1294 octave_idx_type n = lst.size (); | |
1295 | |
1296 string_vector retval (n); | |
1297 | |
1298 octave_idx_type count = 0; | |
1299 | |
1300 for (load_path::dir_info::const_fcn_file_map_iterator p = lst.begin (); | |
1301 p != lst.end (); | |
1302 p++) | |
1303 { | |
1304 std::string nm = p->first; | |
1305 | |
1306 int types = p->second; | |
1307 | |
1308 if (types & load_path::OCT_FILE) | |
1309 nm += ".oct"; | |
1310 else if (types & load_path::MEX_FILE) | |
1311 nm += ".mex"; | |
1312 else | |
1313 nm += ".m"; | |
1314 | |
1315 retval[count++] = nm; | |
1316 } | |
1317 | |
1318 return retval; | |
1319 } | |
1320 | |
1321 void | |
5832 | 1322 load_path::do_display (std::ostream& os) const |
1323 { | |
1324 for (const_dir_info_list_iterator i = dir_info_list.begin (); | |
1325 i != dir_info_list.end (); | |
1326 i++) | |
1327 { | |
1328 string_vector fcn_files = i->fcn_files; | |
1329 | |
1330 if (! fcn_files.empty ()) | |
1331 { | |
1332 os << "\n*** function files in " << i->dir_name << ":\n\n"; | |
1333 | |
1334 fcn_files.list_in_columns (os); | |
1335 } | |
1336 | |
7336 | 1337 const dir_info::method_file_map_type& method_file_map |
1338 = i->method_file_map; | |
5832 | 1339 |
7336 | 1340 if (! method_file_map.empty ()) |
5832 | 1341 { |
7336 | 1342 for (dir_info::const_method_file_map_iterator p = method_file_map.begin (); |
1343 p != method_file_map.end (); | |
5832 | 1344 p++) |
1345 { | |
7336 | 1346 os << "\n*** methods in " << i->dir_name |
1347 << "/@" << p->first << ":\n\n"; | |
5832 | 1348 |
7336 | 1349 string_vector method_files = get_file_list (p->second); |
5832 | 1350 |
7336 | 1351 method_files.list_in_columns (os); |
1352 } | |
1353 } | |
1354 } | |
5864 | 1355 |
7336 | 1356 for (const_private_fcn_map_iterator i = private_fcn_map.begin (); |
1357 i != private_fcn_map.end (); i++) | |
1358 { | |
1359 os << "\n*** private functions in " | |
1360 << file_ops::concat (i->first, "private") << ":\n\n"; | |
5832 | 1361 |
7336 | 1362 print_fcn_list (os, i->second); |
5832 | 1363 } |
1364 | |
1365 #if defined (DEBUG_LOAD_PATH) | |
1366 | |
1367 for (const_fcn_map_iterator i = fcn_map.begin (); | |
1368 i != fcn_map.end (); | |
1369 i++) | |
1370 { | |
1371 os << i->first << ":\n"; | |
1372 | |
7336 | 1373 const file_info_list_type& file_info_list = i->second; |
5832 | 1374 |
1375 for (const_file_info_list_iterator p = file_info_list.begin (); | |
1376 p != file_info_list.end (); | |
1377 p++) | |
1378 { | |
1379 os << " " << p->dir_name << " ("; | |
1380 | |
7336 | 1381 print_types (os, p->types); |
5832 | 1382 |
1383 os << ")\n"; | |
1384 } | |
1385 } | |
1386 | |
7336 | 1387 for (const_method_map_iterator i = method_map.begin (); |
1388 i != method_map.end (); | |
1389 i++) | |
1390 { | |
1391 os << "CLASS " << i->first << ":\n"; | |
1392 | |
1393 const fcn_map_type& fm = i->second; | |
1394 | |
1395 for (const_fcn_map_iterator q = fm.begin (); | |
1396 q != fm.end (); | |
1397 q++) | |
1398 { | |
1399 os << " " << q->first << ":\n"; | |
1400 | |
1401 const file_info_list_type& file_info_list = q->second; | |
1402 | |
1403 for (const_file_info_list_iterator p = file_info_list.begin (); | |
1404 p != file_info_list.end (); | |
1405 p++) | |
1406 { | |
1407 os << " " << p->dir_name << " ("; | |
1408 | |
1409 print_types (os, p->types); | |
1410 | |
1411 os << ")\n"; | |
1412 } | |
1413 } | |
1414 } | |
1415 | |
5832 | 1416 os << "\n"; |
1417 | |
1418 #endif | |
1419 } | |
1420 | |
1421 void | |
1422 load_path::add_to_fcn_map (const dir_info& di, bool at_end) const | |
1423 { | |
1424 std::string dir_name = di.dir_name; | |
1425 | |
1426 string_vector fcn_files = di.fcn_files; | |
1427 | |
1428 octave_idx_type len = fcn_files.length (); | |
1429 | |
1430 for (octave_idx_type i = 0; i < len; i++) | |
1431 { | |
1432 std::string fname = fcn_files[i]; | |
1433 | |
1434 std::string ext; | |
1435 std::string base = fname; | |
1436 | |
1437 size_t pos = fname.rfind ('.'); | |
1438 | |
1439 if (pos != NPOS) | |
1440 { | |
1441 base = fname.substr (0, pos); | |
1442 ext = fname.substr (pos); | |
1443 } | |
1444 | |
7336 | 1445 file_info_list_type& file_info_list = fcn_map[base]; |
5832 | 1446 |
1447 file_info_list_iterator p = file_info_list.begin (); | |
1448 | |
1449 while (p != file_info_list.end ()) | |
1450 { | |
1451 if (p->dir_name == dir_name) | |
1452 break; | |
1453 | |
1454 p++; | |
1455 } | |
1456 | |
1457 int t = 0; | |
1458 if (ext == ".m") | |
1459 t = load_path::M_FILE; | |
1460 else if (ext == ".oct") | |
1461 t = load_path::OCT_FILE; | |
5864 | 1462 else if (ext == ".mex") |
1463 t = load_path::MEX_FILE; | |
5832 | 1464 |
1465 if (p == file_info_list.end ()) | |
1466 { | |
1467 file_info fi (dir_name, t); | |
1468 | |
1469 if (at_end) | |
1470 file_info_list.push_back (fi); | |
1471 else | |
1472 file_info_list.push_front (fi); | |
1473 } | |
1474 else | |
1475 { | |
1476 file_info& fi = *p; | |
1477 | |
1478 fi.types |= t; | |
1479 } | |
1480 } | |
1481 } | |
1482 | |
7336 | 1483 void |
1484 load_path::add_to_private_fcn_map (const dir_info& di) const | |
1485 { | |
1486 dir_info::fcn_file_map_type private_file_map = di.private_file_map; | |
1487 | |
1488 if (! private_file_map.empty ()) | |
1489 private_fcn_map[di.dir_name] = private_file_map; | |
1490 } | |
1491 | |
1492 void | |
1493 load_path::add_to_method_map (const dir_info& di, bool at_end) const | |
1494 { | |
1495 std::string dir_name = di.dir_name; | |
1496 | |
1497 // <CLASS_NAME, <FCN_NAME, TYPES>> | |
1498 dir_info::method_file_map_type method_file_map = di.method_file_map; | |
1499 | |
1500 for (dir_info::const_method_file_map_iterator q = method_file_map.begin (); | |
1501 q != method_file_map.end (); | |
1502 q++) | |
1503 { | |
1504 std::string class_name = q->first; | |
1505 | |
1506 fcn_map_type& fm = method_map[class_name]; | |
1507 | |
1508 std::string full_dir_name | |
1509 = file_ops::concat (dir_name, "@" + class_name); | |
1510 | |
1511 // <FCN_NAME, TYPES> | |
1512 const dir_info::fcn_file_map_type& m = q->second; | |
1513 | |
1514 for (dir_info::const_fcn_file_map_iterator p = m.begin (); | |
1515 p != m.end (); | |
1516 p++) | |
1517 { | |
1518 std::string base = p->first; | |
1519 | |
1520 int types = p->second; | |
1521 | |
1522 file_info_list_type& file_info_list = fm[base]; | |
1523 | |
1524 file_info_list_iterator p2 = file_info_list.begin (); | |
1525 | |
1526 while (p2 != file_info_list.end ()) | |
1527 { | |
1528 if (p2->dir_name == full_dir_name) | |
1529 break; | |
1530 | |
1531 p2++; | |
1532 } | |
1533 | |
1534 if (p2 == file_info_list.end ()) | |
1535 { | |
1536 file_info fi (full_dir_name, types); | |
1537 | |
1538 if (at_end) | |
1539 file_info_list.push_back (fi); | |
1540 else | |
1541 file_info_list.push_front (fi); | |
1542 } | |
1543 else | |
1544 { | |
1545 // FIXME -- is this possible? | |
1546 | |
1547 file_info& fi = *p2; | |
1548 | |
1549 fi.types = types; | |
1550 } | |
1551 } | |
1552 } | |
1553 } | |
1554 | |
5832 | 1555 std::string |
1556 genpath (const std::string& dirname, const string_vector& skip) | |
1557 { | |
1558 std::string retval; | |
1559 | |
5871 | 1560 dir_entry dir (dirname); |
5832 | 1561 |
1562 if (dir) | |
1563 { | |
1564 retval = dirname; | |
1565 | |
1566 string_vector dirlist = dir.read (); | |
1567 | |
1568 octave_idx_type len = dirlist.length (); | |
1569 | |
1570 for (octave_idx_type i = 0; i < len; i++) | |
1571 { | |
1572 std::string elt = dirlist[i]; | |
1573 | |
1574 // FIXME -- the caller should be able to specify the list of | |
7336 | 1575 // directories to skip in addition to ".", "..", and |
1576 // directories beginning with "@". | |
5832 | 1577 |
7336 | 1578 bool skip_p = (elt == "." || elt == ".." || elt[0] == '@'); |
5832 | 1579 |
1580 if (! skip_p) | |
1581 { | |
1582 for (octave_idx_type j = 0; j < skip.length (); j++) | |
1583 { | |
1584 skip_p = (elt == skip[j]); | |
1585 if (skip_p) | |
1586 break; | |
1587 } | |
1588 | |
1589 if (! skip_p) | |
1590 { | |
7272 | 1591 std::string nm = file_ops::concat (dirname, elt); |
5832 | 1592 |
1593 file_stat fs (nm); | |
1594 | |
1595 if (fs && fs.is_dir ()) | |
1596 retval += dir_path::path_sep_str + genpath (nm); | |
1597 } | |
1598 } | |
1599 } | |
1600 } | |
1601 | |
1602 return retval; | |
1603 } | |
1604 | |
1605 static void | |
1606 execute_pkg_add_or_del (const std::string& dir, | |
1607 const std::string& script_file) | |
1608 { | |
1609 if (! octave_interpreter_ready) | |
1610 return; | |
1611 | |
1612 unwind_protect::begin_frame ("execute_pkg_add_or_del"); | |
1613 | |
1614 unwind_protect_bool (input_from_startup_file); | |
1615 | |
1616 input_from_startup_file = true; | |
1617 | |
7272 | 1618 std::string file = file_ops::concat (dir, script_file); |
5832 | 1619 |
5978 | 1620 file_stat fs (file); |
5832 | 1621 |
1622 if (fs.exists ()) | |
5975 | 1623 source_file (file, "base"); |
5832 | 1624 |
1625 unwind_protect::run_frame ("execute_pkg_add_or_del"); | |
1626 } | |
1627 | |
1628 void | |
1629 execute_pkg_add (const std::string& dir) | |
1630 { | |
1631 execute_pkg_add_or_del (dir, "PKG_ADD"); | |
1632 } | |
1633 | |
1634 void | |
1635 execute_pkg_del (const std::string& dir) | |
1636 { | |
1637 execute_pkg_add_or_del (dir, "PKG_DEL"); | |
1638 } | |
1639 | |
1640 DEFUN (genpath, args, , | |
1641 "-*- texinfo -*-\n\ | |
1642 @deftypefn {Built-in Function} {} genpath (@var{dir})\n\ | |
1643 Return a path constructed from @var{dir} and all its subdiretories.\n\ | |
1644 @end deftypefn") | |
1645 { | |
1646 octave_value retval; | |
1647 | |
1648 if (args.length () == 1) | |
1649 { | |
1650 std::string dirname = args(0).string_value (); | |
1651 | |
1652 if (! error_state) | |
1653 retval = genpath (dirname); | |
1654 else | |
1655 error ("genpath: expecting argument to be a character string"); | |
1656 } | |
1657 else | |
1658 print_usage (); | |
1659 | |
1660 return retval; | |
1661 } | |
1662 | |
1663 DEFUN (rehash, , , | |
1664 "-*- texinfo -*-\n\ | |
1665 @deftypefn {Built-in Function} {} rehash ()\n\ | |
6644 | 1666 Reinitialize Octave's load path directory cache.\n\ |
5832 | 1667 @end deftypefn") |
1668 { | |
1669 octave_value_list retval; | |
1670 | |
1671 load_path::update (); | |
1672 | |
1673 // FIXME -- maybe we should rename this variable since it is being | |
1674 // used for more than keeping track of the prompt time. | |
1675 | |
1676 // This will force updated functions to be found. | |
1677 Vlast_prompt_time.stamp (); | |
1678 | |
1679 return retval; | |
1680 } | |
1681 | |
7391 | 1682 DEFUN (restoredefaultpath, , , |
1683 "-*- texinfo -*-\n\ | |
1684 @deftypefn {Built-in Function} {} restoredefaultpath (@dots{})\n\ | |
1685 Restore Octave's path to it's initial state at startup.\n\ | |
1686 \n\ | |
1687 @seealso{path, addpath, rmpath, genpath, pathdef, savepath, pathsep}\n\ | |
1688 @end deftypefn") | |
1689 { | |
1690 load_path::initialize (true); | |
1691 | |
1692 return octave_value (load_path::system_path ()); | |
1693 } | |
1694 | |
1695 DEFUN (__pathorig__, , , | |
5832 | 1696 "-*- texinfo -*-\n\ |
7391 | 1697 @deftypefn {Built-in Function} {@var{val} =} __pathorig__ ()\n\ |
1698 Return Octave's original default list of directories in which to search\n\ | |
1699 for function files. This corresponds to the path that exists prior to\n\ | |
1700 running the system's @file{octaverc}, or the users' @file{~/.octaverc}\n\ | |
1701 @seealso{path, addpath, rmpath, genpath, savepath, pathsep, \n\ | |
1702 restoredefaultpath}\n\ | |
5832 | 1703 @end deftypefn") |
1704 { | |
6630 | 1705 return octave_value (load_path::system_path ()); |
5832 | 1706 } |
1707 | |
1708 DEFUN (path, args, nargout, | |
1709 "-*- texinfo -*-\n\ | |
6678 | 1710 @deftypefn {Built-in Function} {} path (@dots{})\n\ |
6644 | 1711 Modify or display Octave's load path.\n\ |
5832 | 1712 \n\ |
1713 If @var{nargin} and @var{nargout} are zero, display the elements of\n\ | |
6644 | 1714 Octave's load path in an easy to read format.\n\ |
5832 | 1715 \n\ |
1716 If @var{nargin} is zero and nargout is greater than zero, return the\n\ | |
6644 | 1717 current load path.\n\ |
5832 | 1718 \n\ |
1719 If @var{nargin} is greater than zero, concatenate the arguments,\n\ | |
1720 separating them with @code{pathsep()}. Set the internal search path\n\ | |
1721 to the result and return it.\n\ | |
1722 \n\ | |
1723 No checks are made for duplicate elements.\n\ | |
1724 @seealso{addpath, rmpath, genpath, pathdef, savepath, pathsep}\n\ | |
1725 @end deftypefn") | |
1726 { | |
1727 octave_value retval; | |
1728 | |
1729 int argc = args.length () + 1; | |
1730 | |
1731 string_vector argv = args.make_argv ("path"); | |
1732 | |
1733 if (! error_state) | |
1734 { | |
1735 if (argc > 1) | |
1736 { | |
1737 std::string path = argv[1]; | |
1738 | |
1739 for (int i = 2; i < argc; i++) | |
5867 | 1740 path += dir_path::path_sep_str + argv[i]; |
5832 | 1741 |
5867 | 1742 load_path::set (path, true); |
5832 | 1743 } |
1744 | |
1745 if (nargout > 0) | |
1746 retval = load_path::path (); | |
1747 else if (argc == 1 && nargout == 0) | |
1748 { | |
1749 octave_stdout << "\nOctave's search path contains the following directories:\n\n"; | |
1750 | |
1751 string_vector dirs = load_path::dirs (); | |
1752 | |
1753 dirs.list_in_columns (octave_stdout); | |
1754 | |
1755 octave_stdout << "\n"; | |
1756 } | |
1757 } | |
1758 | |
1759 return retval; | |
1760 } | |
1761 | |
1762 DEFCMD (addpath, args, nargout, | |
1763 "-*- texinfo -*-\n\ | |
6678 | 1764 @deftypefn {Built-in Function} {} addpath (@var{dir1}, @dots{})\n\ |
1765 @deftypefnx {Built-in Function} {} addpath (@var{dir1}, @dots{}, @var{option})\n\ | |
5832 | 1766 Add @var{dir1}, @dots{} to the current function search path. If\n\ |
1767 @var{option} is @samp{\"-begin\"} or 0 (the default), prepend the\n\ | |
1768 directory name to the current path. If @var{option} is @samp{\"-end\"}\n\ | |
1769 or 1, append the directory name to the current path.\n\ | |
1770 Directories added to the path must exist.\n\ | |
1771 @seealso{path, rmpath, genpath, pathdef, savepath, pathsep}\n\ | |
1772 @end deftypefn") | |
1773 { | |
1774 octave_value retval; | |
1775 | |
1776 // Originally written by Bill Denney and Etienne Grossman. Heavily | |
1777 // modified and translated to C++ by jwe. | |
1778 | |
1779 if (nargout > 0) | |
1780 retval = load_path::path (); | |
1781 | |
1782 int nargin = args.length (); | |
1783 | |
1784 if (nargin > 0) | |
1785 { | |
1786 bool append = false; | |
1787 | |
1788 octave_value option_arg = args(nargin-1); | |
1789 | |
1790 if (option_arg.is_string ()) | |
1791 { | |
1792 std::string option = option_arg.string_value (); | |
1793 | |
1794 if (option == "-end") | |
1795 { | |
1796 append = true; | |
1797 nargin--; | |
1798 } | |
1799 else if (option == "-begin") | |
1800 nargin--; | |
1801 } | |
1802 else if (option_arg.is_numeric_type ()) | |
1803 { | |
1804 int val = option_arg.int_value (); | |
1805 | |
1806 if (! error_state) | |
1807 { | |
1808 if (val == 0) | |
1809 append = false; | |
1810 else if (val == 1) | |
1811 append = true; | |
1812 else | |
1813 { | |
1814 error ("addpath: expecting final argument to be 1 or 0"); | |
1815 return retval; | |
1816 } | |
1817 } | |
1818 else | |
1819 { | |
1820 error ("addpath: expecting final argument to be 1 or 0"); | |
1821 return retval; | |
1822 } | |
1823 } | |
1824 | |
1825 for (int i = 0; i < nargin; i++) | |
1826 { | |
1827 std::string arg = args(i).string_value (); | |
1828 | |
1829 if (! error_state) | |
1830 { | |
1831 std::list<std::string> dir_elts = split_path (arg); | |
1832 | |
1833 for (std::list<std::string>::const_iterator p = dir_elts.begin (); | |
1834 p != dir_elts.end (); | |
1835 p++) | |
1836 { | |
1837 std::string dir = *p; | |
1838 | |
1839 //dir = regexprep (dir_elts{j}, "//+", "/"); | |
1840 //dir = regexprep (dir, "/$", ""); | |
1841 | |
5867 | 1842 if (append) |
1843 load_path::append (dir, true); | |
5832 | 1844 else |
5867 | 1845 load_path::prepend (dir, true); |
5832 | 1846 } |
1847 } | |
1848 else | |
1849 error ("addpath: expecting all args to be character strings"); | |
1850 } | |
1851 } | |
1852 else | |
1853 print_usage (); | |
1854 | |
1855 return retval; | |
1856 } | |
1857 | |
1858 DEFCMD (rmpath, args, nargout, | |
1859 "-*- texinfo -*-\n\ | |
6678 | 1860 @deftypefn {Built-in Function} {} rmpath (@var{dir1}, @dots{})\n\ |
5832 | 1861 Remove @var{dir1}, @dots{} from the current function search path.\n\ |
1862 \n\ | |
1863 @seealso{path, addpath, genpath, pathdef, savepath, pathsep}\n\ | |
1864 @end deftypefn") | |
1865 { | |
1866 // Originally by Etienne Grossmann. Heavily modified and translated | |
1867 // to C++ by jwe. | |
1868 | |
1869 octave_value retval; | |
1870 | |
1871 if (nargout > 0) | |
1872 retval = load_path::path (); | |
1873 | |
1874 int nargin = args.length (); | |
1875 | |
1876 if (nargin > 0) | |
1877 { | |
1878 for (int i = 0; i < nargin; i++) | |
1879 { | |
1880 std::string arg = args(i).string_value (); | |
1881 | |
1882 if (! error_state) | |
1883 { | |
1884 std::list<std::string> dir_elts = split_path (arg); | |
1885 | |
1886 for (std::list<std::string>::const_iterator p = dir_elts.begin (); | |
1887 p != dir_elts.end (); | |
1888 p++) | |
1889 { | |
1890 std::string dir = *p; | |
1891 | |
1892 //dir = regexprep (dir_elts{j}, "//+", "/"); | |
1893 //dir = regexprep (dir, "/$", ""); | |
1894 | |
1895 if (! load_path::remove (dir)) | |
1896 warning ("rmpath: %s: not found", dir.c_str ()); | |
1897 } | |
1898 } | |
1899 else | |
1900 error ("addpath: expecting all args to be character strings"); | |
1901 } | |
1902 } | |
1903 else | |
1904 print_usage (); | |
1905 | |
1906 return retval; | |
1907 } | |
1908 | |
1909 /* | |
1910 ;;; Local Variables: *** | |
1911 ;;; mode: C++ *** | |
1912 ;;; End: *** | |
1913 */ |