1
|
1 /* |
|
2 |
7017
|
3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, |
|
4 2002, 2003, 2004, 2005, 2006, 2007 John W. Eaton |
7336
|
5 |
1
|
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 |
7016
|
10 Free Software Foundation; either version 3 of the License, or (at your |
|
11 option) any later version. |
1
|
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 |
7016
|
19 along with Octave; see the file COPYING. If not, see |
|
20 <http://www.gnu.org/licenses/>. |
1
|
21 |
|
22 */ |
|
23 |
240
|
24 #ifdef HAVE_CONFIG_H |
1192
|
25 #include <config.h> |
1
|
26 #endif |
|
27 |
7336
|
28 #include "oct-env.h" |
|
29 #include "oct-time.h" |
|
30 #include "file-ops.h" |
|
31 #include "file-stat.h" |
1755
|
32 |
3308
|
33 #include "defun.h" |
7336
|
34 #include "dirfns.h" |
|
35 #include "input.h" |
|
36 #include "load-path.h" |
1755
|
37 #include "symtab.h" |
7336
|
38 #include "ov-fcn.h" |
|
39 #include "pager.h" |
|
40 #include "parse.h" |
|
41 #include "pt-arg-list.h" |
|
42 #include "toplev.h" |
|
43 #include "unwind-prot.h" |
1
|
44 #include "utils.h" |
7336
|
45 |
|
46 symbol_table *symbol_table::instance = 0; |
1
|
47 |
7336
|
48 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances; |
4913
|
49 |
7336
|
50 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table; |
4913
|
51 |
7336
|
52 const symbol_table::scope_id symbol_table::xglobal_scope = 0; |
|
53 const symbol_table::scope_id symbol_table::xtop_scope = 1; |
4238
|
54 |
7336
|
55 symbol_table::scope_id symbol_table::xcurrent_scope = 1; |
|
56 symbol_table::scope_id symbol_table::xcurrent_caller_scope = -1; |
3308
|
57 |
7336
|
58 symbol_table::scope_id symbol_table::xparent_scope = -1; |
|
59 |
|
60 std::deque<symbol_table::scope_id> symbol_table::scope_stack; |
4238
|
61 |
7336
|
62 symbol_table::scope_id symbol_table::next_available_scope = 2; |
|
63 std::set<symbol_table::scope_id> symbol_table::scope_ids_in_use; |
|
64 std::set<symbol_table::scope_id> symbol_table::scope_ids_free_list; |
195
|
65 |
7336
|
66 // Should Octave always check to see if function files have changed |
|
67 // since they were last compiled? |
|
68 static int Vignore_function_time_stamp = 1; |
3355
|
69 |
7336
|
70 octave_value |
|
71 symbol_table::symbol_record::find (tree_argument_list *args, |
|
72 const string_vector& arg_names, |
|
73 octave_value_list& evaluated_args, |
|
74 bool& args_evaluated) const |
|
75 { |
|
76 octave_value retval; |
3355
|
77 |
7336
|
78 if (is_global ()) |
|
79 return symbol_table::varref (name (), symbol_table::xglobal_scope); |
|
80 else |
|
81 { |
|
82 octave_value val = varval (); |
|
83 |
|
84 if (val.is_defined ()) |
|
85 return val; |
|
86 } |
|
87 |
|
88 return symbol_table::find_function (name (), args, arg_names, |
|
89 evaluated_args, args_evaluated); |
3355
|
90 } |
|
91 |
7336
|
92 // Check the load path to see if file that defined this is still |
|
93 // visible. If the file is no longer visible, then erase the |
|
94 // definition and move on. If the file is visible, then we also |
|
95 // need to check to see whether the file has changed since the the |
|
96 // function was loaded/parsed. However, this check should only |
|
97 // happen once per prompt (for files found from relative path |
|
98 // elements, we also check if the working directory has changed |
|
99 // since the last time the function was loaded/parsed). |
|
100 // |
|
101 // FIXME -- perhaps this should be done for all loaded functions when |
|
102 // the prompt is printed or the directory has changed, and then we |
|
103 // would not check for it when finding symbol definitions. |
3355
|
104 |
7336
|
105 static inline bool |
|
106 out_of_date_check_internal (octave_value& function) |
1
|
107 { |
3013
|
108 bool retval = false; |
2949
|
109 |
7336
|
110 octave_function *fcn = function.function_value (true); |
5861
|
111 |
7336
|
112 if (fcn) |
220
|
113 { |
7336
|
114 // FIXME -- we need to handle nested functions properly here. |
4914
|
115 |
7336
|
116 if (! fcn->is_nested_function ()) |
|
117 { |
|
118 std::string ff = fcn->fcn_file_name (); |
4914
|
119 |
7336
|
120 if (! ff.empty ()) |
|
121 { |
|
122 octave_time tc = fcn->time_checked (); |
4913
|
123 |
7336
|
124 bool relative = fcn->is_relative (); |
3013
|
125 |
7336
|
126 if (tc < Vlast_prompt_time |
|
127 || (relative && tc < Vlast_chdir_time)) |
4913
|
128 { |
7336
|
129 octave_time ottp = fcn->time_parsed (); |
|
130 time_t tp = ottp.unix_time (); |
4914
|
131 |
7336
|
132 std::string nm = fcn->name (); |
4914
|
133 |
7336
|
134 int nm_len = nm.length (); |
4913
|
135 |
7336
|
136 std::string file; |
|
137 std::string dir_name; |
4913
|
138 |
7336
|
139 if (octave_env::absolute_pathname (nm) |
|
140 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct" |
|
141 || nm.substr (nm_len-4) == ".mex")) |
|
142 || (nm_len > 2 && nm.substr (nm_len-4) == ".m"))) |
|
143 file = nm; |
|
144 else |
|
145 // FIXME -- this lookup is not right since it doesn't |
|
146 // account for dispatch type. |
|
147 file = octave_env::make_absolute (load_path::find_fcn (nm, dir_name), |
|
148 octave_env::getcwd ()); |
4913
|
149 |
7336
|
150 if (file.empty ()) |
|
151 { |
|
152 // Can't see this function from current |
|
153 // directory, so we should clear it. |
195
|
154 |
7336
|
155 function = octave_value (); |
|
156 } |
|
157 else if (same_file (file, ff)) |
|
158 { |
|
159 fcn->mark_fcn_file_up_to_date (octave_time ()); |
1
|
160 |
7336
|
161 if (! (Vignore_function_time_stamp == 2 |
|
162 || (Vignore_function_time_stamp |
|
163 && fcn->is_system_fcn_file ()))) |
|
164 { |
|
165 file_stat fs (ff); |
572
|
166 |
7336
|
167 if (fs) |
|
168 { |
|
169 if (fs.is_newer (tp)) |
|
170 { |
|
171 fcn = load_fcn_from_file (ff, dir_name); |
4009
|
172 |
7336
|
173 if (fcn) |
|
174 { |
|
175 retval = true; |
4009
|
176 |
7336
|
177 function = octave_value (fcn); |
|
178 } |
|
179 else |
|
180 function = octave_value (); |
|
181 } |
|
182 } |
|
183 else |
|
184 function = octave_value (); |
6829
|
185 } |
|
186 } |
|
187 } |
|
188 } |
4009
|
189 } |
|
190 } |
|
191 |
|
192 return retval; |
|
193 } |
|
194 |
|
195 bool |
7336
|
196 out_of_date_check (octave_value& function) |
4009
|
197 { |
7336
|
198 return out_of_date_check_internal (function); |
|
199 } |
4009
|
200 |
7336
|
201 octave_value |
|
202 symbol_table::fcn_info::fcn_info_rep::load_private_function |
|
203 (const std::string& dir_name) |
|
204 { |
|
205 octave_value retval; |
|
206 |
|
207 std::string file_name = load_path::find_private_fcn (dir_name, name); |
|
208 |
|
209 if (! file_name.empty ()) |
4009
|
210 { |
7336
|
211 octave_function *fcn = load_fcn_from_file (file_name); |
4009
|
212 |
7336
|
213 if (fcn) |
4009
|
214 { |
7336
|
215 retval = octave_value (fcn); |
4009
|
216 |
7336
|
217 private_functions[dir_name] = retval; |
4009
|
218 } |
|
219 } |
|
220 |
|
221 return retval; |
|
222 } |
|
223 |
7336
|
224 octave_value |
|
225 symbol_table::fcn_info::fcn_info_rep::load_class_constructor (void) |
4009
|
226 { |
7336
|
227 octave_value retval; |
|
228 |
|
229 std::string dir_name; |
4009
|
230 |
7336
|
231 std::string file_name = load_path::find_method (name, name, dir_name); |
|
232 |
|
233 if (! file_name.empty ()) |
4009
|
234 { |
7336
|
235 octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); |
4009
|
236 |
7336
|
237 if (fcn) |
4009
|
238 { |
7336
|
239 retval = octave_value (fcn); |
|
240 |
|
241 class_constructors[name] = retval; |
|
242 } |
|
243 } |
|
244 |
|
245 return retval; |
|
246 } |
|
247 |
|
248 octave_value |
|
249 symbol_table::fcn_info::fcn_info_rep::load_class_method |
|
250 (const std::string& dispatch_type) |
|
251 { |
|
252 octave_value retval; |
4009
|
253 |
7336
|
254 std::string dir_name; |
|
255 |
|
256 std::string file_name = load_path::find_method (dispatch_type, name, dir_name); |
4009
|
257 |
7336
|
258 if (! file_name.empty ()) |
|
259 { |
|
260 octave_function *fcn = load_fcn_from_file (file_name, dir_name, |
|
261 dispatch_type); |
4009
|
262 |
7336
|
263 if (fcn) |
|
264 { |
|
265 retval = octave_value (fcn); |
|
266 |
|
267 class_methods[dispatch_type] = retval; |
4009
|
268 } |
|
269 } |
|
270 |
|
271 return retval; |
|
272 } |
|
273 |
7336
|
274 void |
|
275 symbol_table::fcn_info::fcn_info_rep::print_dispatch (std::ostream& os) const |
1
|
276 { |
7336
|
277 if (dispatch_map.empty ()) |
|
278 os << "dispatch: " << name << " is not overloaded" << std::endl; |
|
279 else |
|
280 { |
|
281 os << "Overloaded function " << name << ":\n\n"; |
|
282 |
|
283 for (const_dispatch_map_iterator p = dispatch_map.begin (); |
|
284 p != dispatch_map.end (); p++) |
|
285 os << " " << name << " (" << p->first << ", ...) -> " |
|
286 << p->second << " (" << p->first << ", ...)\n"; |
3013
|
287 |
7336
|
288 os << std::endl; |
|
289 } |
|
290 } |
|
291 |
|
292 std::string |
|
293 symbol_table::fcn_info::fcn_info_rep::help_for_dispatch (void) const |
|
294 { |
|
295 std::string retval; |
|
296 |
|
297 if (! dispatch_map.empty ()) |
1
|
298 { |
7336
|
299 retval = "Overloaded function:\n\n"; |
|
300 |
|
301 for (const_dispatch_map_iterator p = dispatch_map.begin (); |
|
302 p != dispatch_map.end (); p++) |
|
303 retval += " " + p->second + " (" + p->first + ", ...)\n\n"; |
|
304 } |
|
305 |
|
306 return retval; |
|
307 } |
|
308 |
|
309 // Find the definition of NAME according to the following precedence |
|
310 // list: |
|
311 // |
|
312 // variable |
|
313 // subfunction |
|
314 // private function |
|
315 // class constructor |
|
316 // class method |
|
317 // legacy dispatch |
|
318 // command-line function |
|
319 // autoload function |
|
320 // function on the path |
|
321 // built-in function |
3013
|
322 |
7336
|
323 // Notes: |
|
324 // |
|
325 // FIXME -- we need to evaluate the argument list to determine the |
|
326 // dispatch type. The method used here works (pass in the args, pass |
|
327 // out the evaluated args and a flag saying whether the evaluation was |
|
328 // needed), but it seems a bit inelegant. We do need to save the |
|
329 // evaluated args in some way to avoid evaluating them multiple times. |
|
330 // Maybe evaluated args could be attached to the tree_argument_list |
|
331 // object? Then the argument list could be evaluated outside of this |
|
332 // function and we could elimnate the arg_names, evaluated_args, and |
|
333 // args_evaluated arguments. We would still want to avoid computing |
|
334 // the dispatch type unless it is needed, so the args should be passed |
|
335 // rather than the dispatch type. But the arguments will need to be |
|
336 // evaluated no matter what, so evaluating them beforehand should be |
|
337 // OK. If the evaluated arguments are attached to args, then we would |
|
338 // need to determine the appropriate place(s) to clear them (for |
|
339 // example, before returning from tree_index_expression::rvalue). |
|
340 |
|
341 octave_value |
|
342 symbol_table::fcn_info::fcn_info_rep::find |
|
343 (tree_argument_list *args, const string_vector& arg_names, |
|
344 octave_value_list& evaluated_args, bool& args_evaluated, |
|
345 scope_id scope) |
|
346 { |
|
347 static bool deja_vu = false; |
|
348 |
|
349 // Subfunction. I think it only makes sense to check for |
|
350 // subfunctions if we are currently executing a function defined |
|
351 // from a .m file. |
|
352 |
|
353 scope_val_iterator r = subfunctions.find (scope); |
|
354 |
|
355 if (r != subfunctions.end ()) |
|
356 { |
|
357 // FIXME -- out-of-date check here. |
|
358 |
|
359 return r->second; |
|
360 } |
|
361 else if (curr_parent_function) |
|
362 { |
|
363 scope_id pscope = curr_parent_function->scope (); |
|
364 |
|
365 r = subfunctions.find (pscope); |
|
366 |
|
367 if (r != subfunctions.end ()) |
1
|
368 { |
7336
|
369 // FIXME -- out-of-date check here. |
|
370 |
|
371 return r->second; |
1
|
372 } |
|
373 } |
3013
|
374 |
7336
|
375 // Private function. |
1
|
376 |
7336
|
377 octave_function *curr_fcn = octave_call_stack::current (); |
1
|
378 |
7336
|
379 if (curr_fcn) |
|
380 { |
|
381 std::string dir_name = curr_fcn->dir_name (); |
1
|
382 |
7336
|
383 if (! dir_name.empty ()) |
|
384 { |
|
385 str_val_iterator q = private_functions.find (dir_name); |
4913
|
386 |
7336
|
387 if (q == private_functions.end ()) |
|
388 { |
|
389 octave_value val = load_private_function (dir_name); |
4913
|
390 |
7336
|
391 if (val.is_defined ()) |
|
392 return val; |
|
393 } |
|
394 else |
4913
|
395 { |
7336
|
396 octave_value& fval = q->second; |
4913
|
397 |
7336
|
398 if (fval.is_defined ()) |
|
399 out_of_date_check_internal (fval); |
4913
|
400 |
7336
|
401 if (fval.is_defined ()) |
|
402 return fval; |
|
403 else |
|
404 { |
|
405 octave_value val = load_private_function (dir_name); |
4913
|
406 |
7336
|
407 if (val.is_defined ()) |
|
408 return val; |
4913
|
409 } |
|
410 } |
|
411 } |
|
412 } |
|
413 |
7336
|
414 // Class constructors. The class name and function name are the same. |
4913
|
415 |
7336
|
416 str_val_iterator q = class_constructors.find (name); |
4913
|
417 |
7336
|
418 if (q == class_constructors.end ()) |
|
419 { |
|
420 octave_value val = load_class_constructor (); |
3013
|
421 |
7336
|
422 if (val.is_defined ()) |
|
423 return val; |
|
424 } |
|
425 else |
1
|
426 { |
7336
|
427 octave_value& fval = q->second; |
3013
|
428 |
7336
|
429 if (fval.is_defined ()) |
|
430 out_of_date_check_internal (fval); |
867
|
431 |
7336
|
432 if (fval.is_defined ()) |
|
433 return fval; |
|
434 else |
|
435 { |
|
436 octave_value val = load_class_constructor (); |
867
|
437 |
7336
|
438 if (val.is_defined ()) |
|
439 return val; |
1
|
440 } |
|
441 } |
1755
|
442 |
7336
|
443 // Class methods. |
1
|
444 |
7336
|
445 if (args_evaluated || (args && args->length () > 0)) |
|
446 { |
|
447 if (! args_evaluated) |
|
448 evaluated_args = args->convert_to_const_vector (); |
3013
|
449 |
7336
|
450 if (! error_state) |
|
451 { |
|
452 int n = evaluated_args.length (); |
|
453 |
|
454 if (n > 0 && ! args_evaluated) |
|
455 evaluated_args.stash_name_tags (arg_names); |
|
456 |
|
457 args_evaluated = true; |
|
458 |
|
459 // FIXME -- need to handle precedence. |
3013
|
460 |
7336
|
461 std::string dispatch_type = evaluated_args(0).class_name (); |
3013
|
462 |
7336
|
463 for (int i = 1; i < n; i++) |
|
464 { |
|
465 octave_value arg = evaluated_args(i); |
3013
|
466 |
7336
|
467 if (arg.is_object ()) |
|
468 { |
|
469 dispatch_type = arg.class_name (); |
|
470 break; |
|
471 } |
|
472 } |
3013
|
473 |
7336
|
474 octave_value fcn = find_method (dispatch_type); |
|
475 |
|
476 if (fcn.is_defined ()) |
|
477 return fcn; |
|
478 } |
|
479 else |
|
480 return octave_value (); |
3013
|
481 } |
|
482 |
7336
|
483 // Legacy dispatch. We just check args_evaluated here because the |
|
484 // actual evaluation will have happened already when searching for |
|
485 // class methods. |
|
486 |
|
487 if (args_evaluated && ! dispatch_map.empty ()) |
|
488 { |
|
489 std::string dispatch_type = evaluated_args(0).type_name (); |
|
490 |
|
491 std::string fname; |
|
492 |
|
493 dispatch_map_iterator p = dispatch_map.find (dispatch_type); |
|
494 |
|
495 if (p == dispatch_map.end ()) |
|
496 p = dispatch_map.find ("any"); |
3013
|
497 |
7336
|
498 if (p != dispatch_map.end ()) |
|
499 { |
|
500 fname = p->second; |
|
501 |
|
502 octave_value fcn |
|
503 = symbol_table::find_function (fname, evaluated_args, scope); |
|
504 |
|
505 if (fcn.is_defined ()) |
|
506 return fcn; |
|
507 } |
|
508 } |
|
509 |
|
510 // Command-line function. |
|
511 |
|
512 if (cmdline_function.is_defined ()) |
|
513 return cmdline_function; |
|
514 |
|
515 // Autoload? |
3013
|
516 |
7336
|
517 octave_value fcn = find_autoload (); |
|
518 |
|
519 if (fcn.is_defined ()) |
|
520 return fcn; |
|
521 |
|
522 // Function on the path. |
|
523 |
|
524 fcn = find_user_function (); |
|
525 |
|
526 if (fcn.is_defined ()) |
|
527 return fcn; |
|
528 |
|
529 // Built-in function. |
|
530 |
|
531 if (built_in_function.is_defined ()) |
|
532 return built_in_function; |
3013
|
533 |
7336
|
534 // At this point, we failed to find anything. It is possible that |
|
535 // the user created a file on the fly since the last prompt or |
|
536 // chdir, so try updating the load path and searching again. |
|
537 |
|
538 octave_value retval; |
3145
|
539 |
7336
|
540 if (! deja_vu) |
|
541 { |
|
542 load_path::update (); |
|
543 |
|
544 deja_vu = true; |
|
545 |
|
546 retval = find (args, arg_names, evaluated_args, args_evaluated, scope); |
|
547 } |
|
548 |
|
549 deja_vu = false; |
|
550 |
|
551 return retval; |
3013
|
552 } |
1
|
553 |
7336
|
554 octave_value |
|
555 symbol_table::fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type) |
4913
|
556 { |
7336
|
557 octave_value retval; |
4913
|
558 |
7336
|
559 str_val_iterator q = class_methods.find (dispatch_type); |
4913
|
560 |
7336
|
561 if (q == class_methods.end ()) |
|
562 { |
|
563 octave_value val = load_class_method (dispatch_type); |
4913
|
564 |
7336
|
565 if (val.is_defined ()) |
|
566 return val; |
|
567 } |
|
568 else |
|
569 { |
|
570 octave_value& fval = q->second; |
4913
|
571 |
7336
|
572 if (fval.is_defined ()) |
|
573 out_of_date_check_internal (fval); |
|
574 |
|
575 if (fval.is_defined ()) |
|
576 return fval; |
4913
|
577 else |
|
578 { |
7336
|
579 octave_value val = load_class_method (dispatch_type); |
|
580 |
|
581 if (val.is_defined ()) |
|
582 return val; |
4913
|
583 } |
|
584 } |
|
585 |
7336
|
586 return retval; |
4913
|
587 } |
|
588 |
7336
|
589 octave_value |
|
590 symbol_table::fcn_info::fcn_info_rep::find_autoload (void) |
4913
|
591 { |
7336
|
592 octave_value retval; |
4913
|
593 |
7336
|
594 // Autoloaded function. |
4913
|
595 |
7336
|
596 if (autoload_function.is_defined ()) |
|
597 out_of_date_check_internal (autoload_function); |
4913
|
598 |
7336
|
599 if (! autoload_function.is_defined ()) |
|
600 { |
|
601 std::string file_name = lookup_autoload (name); |
4913
|
602 |
7336
|
603 if (! file_name.empty ()) |
|
604 { |
|
605 size_t pos = file_name.find_last_of (file_ops::dir_sep_chars); |
4913
|
606 |
7336
|
607 std::string dir_name = file_name.substr (0, pos); |
4913
|
608 |
7336
|
609 octave_function *fcn = load_fcn_from_file (file_name, dir_name, |
|
610 "", name, true); |
4913
|
611 |
7336
|
612 if (fcn) |
|
613 autoload_function = octave_value (fcn); |
|
614 } |
4913
|
615 } |
|
616 |
7336
|
617 return autoload_function; |
|
618 } |
4914
|
619 |
7336
|
620 octave_value |
|
621 symbol_table::fcn_info::fcn_info_rep::find_user_function (void) |
|
622 { |
|
623 // Function on the path. |
4913
|
624 |
7336
|
625 if (function_on_path.is_defined ()) |
|
626 out_of_date_check_internal (function_on_path); |
4913
|
627 |
7336
|
628 if (! function_on_path.is_defined ()) |
|
629 { |
|
630 std::string dir_name; |
4913
|
631 |
7336
|
632 std::string file_name = load_path::find_fcn (name, dir_name); |
4913
|
633 |
7336
|
634 if (! file_name.empty ()) |
|
635 { |
|
636 octave_function *fcn = load_fcn_from_file (file_name, dir_name); |
4913
|
637 |
7336
|
638 if (fcn) |
|
639 function_on_path = octave_value (fcn); |
4913
|
640 } |
|
641 } |
|
642 |
7336
|
643 return function_on_path; |
|
644 } |
|
645 |
|
646 octave_value |
|
647 symbol_table::fcn_info::find (tree_argument_list *args, |
|
648 const string_vector& arg_names, |
|
649 octave_value_list& evaluated_args, |
|
650 bool& args_evaluated, scope_id scope) |
|
651 { |
|
652 return rep->find (args, arg_names, evaluated_args, args_evaluated, scope); |
|
653 } |
|
654 |
|
655 octave_value |
|
656 symbol_table::find (const std::string& name, tree_argument_list *args, |
|
657 const string_vector& arg_names, |
|
658 octave_value_list& evaluated_args, bool& args_evaluated, |
|
659 symbol_table::scope_id scope, bool skip_variables) |
|
660 { |
|
661 symbol_table *inst = get_instance (scope); |
|
662 |
|
663 return inst |
|
664 ? inst->do_find (name, args, arg_names, evaluated_args, |
|
665 args_evaluated, scope, skip_variables) |
|
666 : octave_value (); |
|
667 } |
|
668 |
|
669 octave_value |
|
670 symbol_table::find_function (const std::string& name, tree_argument_list *args, |
|
671 const string_vector& arg_names, |
|
672 octave_value_list& evaluated_args, |
|
673 bool& args_evaluated, scope_id scope) |
|
674 { |
|
675 return find (name, args, arg_names, evaluated_args, args_evaluated, |
|
676 scope, true); |
4913
|
677 } |
|
678 |
7336
|
679 octave_value |
|
680 symbol_table::do_find (const std::string& name, tree_argument_list *args, |
|
681 const string_vector& arg_names, |
|
682 octave_value_list& evaluated_args, |
|
683 bool& args_evaluated, scope_id scope, |
|
684 bool skip_variables) |
3013
|
685 { |
7336
|
686 octave_value retval; |
4913
|
687 |
7336
|
688 // Variable. |
4913
|
689 |
7336
|
690 if (! skip_variables) |
3013
|
691 { |
7336
|
692 table_iterator p = table.find (name); |
3013
|
693 |
7336
|
694 if (p != table.end ()) |
|
695 { |
|
696 symbol_record& sr = p->second; |
3013
|
697 |
7336
|
698 // FIXME -- should we be using something other than varref here? |
5005
|
699 |
7336
|
700 if (sr.is_global ()) |
|
701 return symbol_table::varref (name, xglobal_scope); |
|
702 else |
|
703 { |
|
704 octave_value& val = sr.varref (); |
4913
|
705 |
7336
|
706 if (val.is_defined ()) |
|
707 return val; |
|
708 } |
|
709 } |
|
710 } |
4913
|
711 |
7336
|
712 fcn_table_iterator p = fcn_table.find (name); |
4913
|
713 |
7336
|
714 if (p != fcn_table.end ()) |
|
715 { |
|
716 evaluated_args = octave_value_list (); |
|
717 args_evaluated = false; |
3013
|
718 |
7336
|
719 return p->second.find (args, arg_names, evaluated_args, args_evaluated, |
|
720 scope); |
3013
|
721 } |
|
722 else |
|
723 { |
7336
|
724 fcn_info finfo (name); |
|
725 |
|
726 octave_value fcn = finfo.find (args, arg_names, evaluated_args, |
|
727 args_evaluated, scope); |
3013
|
728 |
7336
|
729 if (fcn.is_defined ()) |
|
730 fcn_table[name] = finfo; |
3013
|
731 |
7336
|
732 return fcn; |
3013
|
733 } |
|
734 |
7336
|
735 return retval; |
605
|
736 } |
|
737 |
7336
|
738 DEFUN (ignore_function_time_stamp, args, nargout, |
|
739 "-*- texinfo -*-\n\ |
|
740 @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\ |
|
741 @deftypefnx {Built-in Function} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\n\ |
|
742 Query or set the internal variable that controls whether Octave checks\n\ |
|
743 the time stamp on files each time it looks up functions defined in\n\ |
|
744 function files. If the internal variable is set to @code{\"system\"},\n\ |
|
745 Octave will not automatically recompile function files in subdirectories of\n\ |
|
746 @file{@var{octave-home}/lib/@var{version}} if they have changed since\n\ |
|
747 they were last compiled, but will recompile other function files in the\n\ |
|
748 search path if they change. If set to @code{\"all\"}, Octave will not\n\ |
|
749 recompile any function files unless their definitions are removed with\n\ |
|
750 @code{clear}. If set to \"none\", Octave will always check time stamps\n\ |
|
751 on files to determine whether functions defined in function files\n\ |
|
752 need to recompiled.\n\ |
|
753 @end deftypefn") |
220
|
754 { |
7336
|
755 octave_value retval; |
220
|
756 |
7336
|
757 if (nargout > 0) |
5861
|
758 { |
7336
|
759 switch (Vignore_function_time_stamp) |
5861
|
760 { |
7336
|
761 case 1: |
|
762 retval = "system"; |
|
763 break; |
5861
|
764 |
7336
|
765 case 2: |
|
766 retval = "all"; |
|
767 break; |
5861
|
768 |
7336
|
769 default: |
|
770 retval = "none"; |
|
771 break; |
5861
|
772 } |
|
773 } |
|
774 |
7336
|
775 int nargin = args.length (); |
5861
|
776 |
7336
|
777 if (nargin == 1) |
3013
|
778 { |
7336
|
779 std::string sval = args(0).string_value (); |
1
|
780 |
7336
|
781 if (! error_state) |
|
782 { |
|
783 if (sval == "all") |
|
784 Vignore_function_time_stamp = 2; |
|
785 else if (sval == "system") |
|
786 Vignore_function_time_stamp = 1; |
|
787 else if (sval == "none") |
|
788 Vignore_function_time_stamp = 0; |
|
789 else |
|
790 error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\""); |
|
791 } |
|
792 else |
|
793 error ("ignore_function_time_stamp: expecting argument to be character string"); |
|
794 } |
|
795 else if (nargin > 1) |
|
796 print_usage (); |
4238
|
797 |
7336
|
798 return retval; |
3308
|
799 } |
|
800 |
1
|
801 /* |
|
802 ;;; Local Variables: *** |
|
803 ;;; mode: C++ *** |
|
804 ;;; End: *** |
|
805 */ |