00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include "file-ops.h"
00029 #include "file-stat.h"
00030 #include "oct-env.h"
00031 #include "oct-time.h"
00032 #include "singleton-cleanup.h"
00033
00034 #include "debug.h"
00035 #include "defun.h"
00036 #include "dirfns.h"
00037 #include "input.h"
00038 #include "load-path.h"
00039 #include "ov-fcn.h"
00040 #include "ov-usr-fcn.h"
00041 #include "pager.h"
00042 #include "parse.h"
00043 #include "pt-arg-list.h"
00044 #include "symtab.h"
00045 #include "unwind-prot.h"
00046 #include "utils.h"
00047
00048 symbol_table *symbol_table::instance = 0;
00049
00050 symbol_table::scope_id_cache *symbol_table::scope_id_cache::instance = 0;
00051
00052 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances;
00053
00054 std::map<std::string, octave_value> symbol_table::global_table;
00055
00056 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table;
00057
00058 std::map<std::string, std::set<std::string> > symbol_table::class_precedence_table;
00059
00060 std::map<std::string, std::list<std::string> > symbol_table::parent_map;
00061
00062 const symbol_table::scope_id symbol_table::xglobal_scope = 0;
00063 const symbol_table::scope_id symbol_table::xtop_scope = 1;
00064
00065 symbol_table::scope_id symbol_table::xcurrent_scope = 1;
00066
00067 symbol_table::context_id symbol_table::xcurrent_context = 0;
00068
00069
00070
00071 static int Vignore_function_time_stamp = 1;
00072
00073 void
00074 symbol_table::scope_id_cache::create_instance (void)
00075 {
00076 instance = new scope_id_cache ();
00077
00078 singleton_cleanup_list::add (cleanup_instance);
00079 }
00080
00081 void
00082 symbol_table::symbol_record::symbol_record_rep::dump
00083 (std::ostream& os, const std::string& prefix) const
00084 {
00085 octave_value val = varval (xcurrent_context);
00086
00087 os << prefix << name;
00088
00089 if (val.is_defined ())
00090 {
00091 os << " ["
00092 << (is_local () ? "l" : "")
00093 << (is_automatic () ? "a" : "")
00094 << (is_formal () ? "f" : "")
00095 << (is_hidden () ? "h" : "")
00096 << (is_inherited () ? "i" : "")
00097 << (is_global () ? "g" : "")
00098 << (is_persistent () ? "p" : "")
00099 << "] ";
00100 val.dump (os);
00101 }
00102
00103 os << "\n";
00104 }
00105
00106 octave_value
00107 symbol_table::symbol_record::find (const octave_value_list& args) const
00108 {
00109 octave_value retval;
00110
00111 if (is_global ())
00112 retval = symbol_table::global_varref (name ());
00113 else
00114 {
00115 retval = varval ();
00116
00117 if (retval.is_undefined ())
00118 {
00119
00120 if (rep->finfo)
00121 retval = rep->finfo->find (args);
00122 else
00123 {
00124 retval = symbol_table::find_function (name (), args);
00125
00126 if (retval.is_defined ())
00127 rep->finfo = get_fcn_info (name ());
00128 }
00129 }
00130 }
00131
00132 return retval;
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 static inline bool
00149 load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
00150 octave_value& function,
00151 const std::string& dispatch_type = std::string ())
00152 {
00153 bool retval = false;
00154
00155 octave_function *fcn = load_fcn_from_file (ff, dir_name, dispatch_type);
00156
00157 if (fcn)
00158 {
00159 retval = true;
00160
00161 function = octave_value (fcn);
00162 }
00163 else
00164 function = octave_value ();
00165
00166 return retval;
00167 }
00168
00169 bool
00170 out_of_date_check (octave_value& function,
00171 const std::string& dispatch_type,
00172 bool check_relative)
00173 {
00174 bool retval = false;
00175
00176 octave_function *fcn = function.function_value (true);
00177
00178 if (fcn)
00179 {
00180
00181
00182 if (! fcn->is_subfunction ())
00183 {
00184 std::string ff = fcn->fcn_file_name ();
00185
00186 if (! ff.empty ())
00187 {
00188 octave_time tc = fcn->time_checked ();
00189
00190 bool relative = check_relative && fcn->is_relative ();
00191
00192 if (tc < Vlast_prompt_time
00193 || (relative && tc < Vlast_chdir_time))
00194 {
00195 bool clear_breakpoints = false;
00196 std::string nm = fcn->name ();
00197
00198 bool is_same_file = false;
00199
00200 std::string file;
00201 std::string dir_name;
00202
00203 if (check_relative)
00204 {
00205 int nm_len = nm.length ();
00206
00207 if (octave_env::absolute_pathname (nm)
00208 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct"
00209 || nm.substr (nm_len-4) == ".mex"))
00210 || (nm_len > 2 && nm.substr (nm_len-2) == ".m")))
00211 file = nm;
00212 else
00213 {
00214
00215
00216
00217
00218 if (! dispatch_type.empty ())
00219 {
00220 file = load_path::find_method (dispatch_type, nm,
00221 dir_name);
00222
00223 if (file.empty ())
00224 {
00225 const std::list<std::string>& plist
00226 = symbol_table::parent_classes (dispatch_type);
00227 std::list<std::string>::const_iterator it
00228 = plist.begin ();
00229
00230 while (it != plist.end ())
00231 {
00232 file = load_path::find_method (*it, nm, dir_name);
00233 if (! file.empty ())
00234 break;
00235
00236 it++;
00237 }
00238 }
00239 }
00240
00241
00242 if (file.empty ())
00243 file = lookup_autoload (nm);
00244
00245 if (file.empty ())
00246 file = load_path::find_fcn (nm, dir_name);
00247 }
00248
00249 if (! file.empty ())
00250 is_same_file = same_file (file, ff);
00251 }
00252 else
00253 {
00254 is_same_file = true;
00255 file = ff;
00256 }
00257
00258 if (file.empty ())
00259 {
00260
00261
00262
00263 function = octave_value ();
00264
00265 clear_breakpoints = true;
00266 }
00267 else if (is_same_file)
00268 {
00269
00270
00271 octave_time ottp = fcn->time_parsed ();
00272 time_t tp = ottp.unix_time ();
00273
00274 fcn->mark_fcn_file_up_to_date (octave_time ());
00275
00276 if (! (Vignore_function_time_stamp == 2
00277 || (Vignore_function_time_stamp
00278 && fcn->is_system_fcn_file ())))
00279 {
00280 file_stat fs (ff);
00281
00282 if (fs)
00283 {
00284 if (fs.is_newer (tp))
00285 {
00286 retval = load_out_of_date_fcn (ff, dir_name,
00287 function,
00288 dispatch_type);
00289
00290 clear_breakpoints = true;
00291 }
00292 }
00293 else
00294 {
00295 function = octave_value ();
00296
00297 clear_breakpoints = true;
00298 }
00299 }
00300 }
00301 else
00302 {
00303
00304
00305
00306 retval = load_out_of_date_fcn (file, dir_name, function,
00307 dispatch_type);
00308
00309 clear_breakpoints = true;
00310 }
00311
00312
00313
00314 if (clear_breakpoints)
00315 bp_table::remove_all_breakpoints_in_file (nm, true);
00316 }
00317 }
00318 }
00319 }
00320
00321 return retval;
00322 }
00323
00324 octave_value
00325 symbol_table::fcn_info::fcn_info_rep::load_private_function
00326 (const std::string& dir_name)
00327 {
00328 octave_value retval;
00329
00330 std::string file_name = load_path::find_private_fcn (dir_name, name);
00331
00332 if (! file_name.empty ())
00333 {
00334 octave_function *fcn = load_fcn_from_file (file_name, dir_name);
00335
00336 if (fcn)
00337 {
00338 std::string class_name;
00339
00340 size_t pos = dir_name.find_last_of (file_ops::dir_sep_chars ());
00341
00342 if (pos != std::string::npos)
00343 {
00344 std::string tmp = dir_name.substr (pos+1);
00345
00346 if (tmp[0] == '@')
00347 class_name = tmp.substr (1);
00348 }
00349
00350 fcn->mark_as_private_function (class_name);
00351
00352 retval = octave_value (fcn);
00353
00354 private_functions[dir_name] = retval;
00355 }
00356 }
00357
00358 return retval;
00359 }
00360
00361 octave_value
00362 symbol_table::fcn_info::fcn_info_rep::load_class_constructor (void)
00363 {
00364 octave_value retval;
00365
00366 std::string dir_name;
00367
00368 std::string file_name = load_path::find_method (name, name, dir_name);
00369
00370 if (! file_name.empty ())
00371 {
00372 octave_function *fcn = load_fcn_from_file (file_name, dir_name, name);
00373
00374 if (fcn)
00375 {
00376 retval = octave_value (fcn);
00377
00378 class_constructors[name] = retval;
00379 }
00380 }
00381
00382 return retval;
00383 }
00384
00385 octave_value
00386 symbol_table::fcn_info::fcn_info_rep::load_class_method
00387 (const std::string& dispatch_type)
00388 {
00389 octave_value retval;
00390
00391 if (name == dispatch_type)
00392 retval = load_class_constructor ();
00393 else
00394 {
00395 std::string dir_name;
00396
00397 std::string file_name = load_path::find_method (dispatch_type, name,
00398 dir_name);
00399
00400 if (! file_name.empty ())
00401 {
00402 octave_function *fcn = load_fcn_from_file (file_name, dir_name,
00403 dispatch_type);
00404
00405 if (fcn)
00406 {
00407 retval = octave_value (fcn);
00408
00409 class_methods[dispatch_type] = retval;
00410 }
00411 }
00412
00413 if (retval.is_undefined ())
00414 {
00415
00416
00417 const std::list<std::string>& plist = parent_classes (dispatch_type);
00418
00419 std::list<std::string>::const_iterator it = plist.begin ();
00420
00421 while (it != plist.end ())
00422 {
00423 retval = find_method (*it);
00424
00425 if (retval.is_defined ())
00426 {
00427 class_methods[dispatch_type] = retval;
00428 break;
00429 }
00430
00431 it++;
00432 }
00433 }
00434 }
00435
00436 return retval;
00437 }
00438
00439 void
00440 symbol_table::fcn_info::fcn_info_rep:: mark_subfunction_in_scope_as_private
00441 (scope_id scope, const std::string& class_name)
00442 {
00443 scope_val_iterator p = subfunctions.find (scope);
00444
00445 if (p != subfunctions.end ())
00446 {
00447 octave_function *fcn = p->second.function_value ();
00448
00449 if (fcn)
00450 fcn->mark_as_private_function (class_name);
00451 }
00452 }
00453
00454 void
00455 symbol_table::fcn_info::fcn_info_rep::print_dispatch (std::ostream& os) const
00456 {
00457 if (dispatch_map.empty ())
00458 os << "dispatch: " << name << " is not overloaded" << std::endl;
00459 else
00460 {
00461 os << "Overloaded function " << name << ":\n\n";
00462
00463 for (dispatch_map_const_iterator p = dispatch_map.begin ();
00464 p != dispatch_map.end (); p++)
00465 os << " " << name << " (" << p->first << ", ...) -> "
00466 << p->second << " (" << p->first << ", ...)\n";
00467
00468 os << std::endl;
00469 }
00470 }
00471
00472 std::string
00473 symbol_table::fcn_info::fcn_info_rep::help_for_dispatch (void) const
00474 {
00475 std::string retval;
00476
00477 if (! dispatch_map.empty ())
00478 {
00479 retval = "Overloaded function:\n\n";
00480
00481 for (dispatch_map_const_iterator p = dispatch_map.begin ();
00482 p != dispatch_map.end (); p++)
00483 retval += " " + p->second + " (" + p->first + ", ...)\n\n";
00484 }
00485
00486 return retval;
00487 }
00488
00489
00490
00491
00492
00493 static builtin_type_t (*build_sup_table (void))[btyp_num_types]
00494 {
00495 static builtin_type_t sup_table[btyp_num_types][btyp_num_types];
00496 for (int i = 0; i < btyp_num_types; i++)
00497 for (int j = 0; j < btyp_num_types; j++)
00498 {
00499 builtin_type_t ityp = static_cast<builtin_type_t> (i);
00500 builtin_type_t jtyp = static_cast<builtin_type_t> (j);
00501
00502 bool use_j =
00503 (jtyp == btyp_func_handle || ityp == btyp_bool
00504 || (btyp_isarray (ityp)
00505 && (! btyp_isarray (jtyp)
00506 || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp))
00507 || ((ityp == btyp_double || ityp == btyp_complex || ityp == btyp_char)
00508 && (jtyp == btyp_float || jtyp == btyp_float_complex)))));
00509
00510 sup_table[i][j] = use_j ? jtyp : ityp;
00511 }
00512
00513 return sup_table;
00514 }
00515
00516 std::string
00517 get_dispatch_type (const octave_value_list& args,
00518 builtin_type_t& builtin_type)
00519 {
00520 static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table ();
00521 std::string dispatch_type;
00522
00523 int n = args.length ();
00524
00525 if (n > 0)
00526 {
00527 int i = 0;
00528 builtin_type = args(0).builtin_type ();
00529 if (builtin_type != btyp_unknown)
00530 {
00531 for (i = 1; i < n; i++)
00532 {
00533 builtin_type_t bti = args(i).builtin_type ();
00534 if (bti != btyp_unknown)
00535 builtin_type = sup_table[builtin_type][bti];
00536 else
00537 {
00538 builtin_type = btyp_unknown;
00539 break;
00540 }
00541 }
00542 }
00543
00544 if (builtin_type == btyp_unknown)
00545 {
00546
00547 dispatch_type = args(i).class_name ();
00548
00549 for (int j = i+1; j < n; j++)
00550 {
00551 octave_value arg = args(j);
00552
00553 if (arg.builtin_type () == btyp_unknown)
00554 {
00555 std::string cname = arg.class_name ();
00556
00557
00558
00559 if (! symbol_table::is_superiorto (dispatch_type, cname)
00560 && symbol_table::is_superiorto (cname, dispatch_type))
00561 dispatch_type = cname;
00562 }
00563 }
00564 }
00565 else
00566 dispatch_type = btyp_class_name[builtin_type];
00567 }
00568 else
00569 builtin_type = btyp_unknown;
00570
00571 return dispatch_type;
00572 }
00573
00574 std::string
00575 get_dispatch_type (const octave_value_list& args)
00576 {
00577 builtin_type_t builtin_type;
00578 return get_dispatch_type (args, builtin_type);
00579 }
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 octave_value
00599 symbol_table::fcn_info::fcn_info_rep::find (const octave_value_list& args,
00600 bool local_funcs)
00601 {
00602 octave_value retval = xfind (args, local_funcs);
00603
00604 if (! (error_state || retval.is_defined ()))
00605 {
00606
00607
00608
00609
00610 load_path::update ();
00611
00612 retval = xfind (args, local_funcs);
00613 }
00614
00615 return retval;
00616 }
00617
00618 octave_value
00619 symbol_table::fcn_info::fcn_info_rep::xfind (const octave_value_list& args,
00620 bool local_funcs)
00621 {
00622 if (local_funcs)
00623 {
00624
00625
00626
00627
00628 scope_val_iterator r = subfunctions.find (xcurrent_scope);
00629
00630 octave_user_function *curr_fcn = symbol_table::get_curr_fcn ();
00631
00632 if (r != subfunctions.end ())
00633 {
00634
00635
00636 return r->second;
00637 }
00638 else
00639 {
00640 if (curr_fcn)
00641 {
00642
00643
00644
00645
00646
00647
00648 scope_id pscope = curr_fcn->parent_fcn_scope ();
00649
00650 if (pscope > 0)
00651 {
00652 r = subfunctions.find (pscope);
00653
00654 if (r != subfunctions.end ())
00655 {
00656
00657
00658 return r->second;
00659 }
00660 }
00661 }
00662 }
00663
00664
00665
00666 if (curr_fcn)
00667 {
00668 std::string dir_name = curr_fcn->dir_name ();
00669
00670 if (! dir_name.empty ())
00671 {
00672 str_val_iterator q = private_functions.find (dir_name);
00673
00674 if (q == private_functions.end ())
00675 {
00676 octave_value val = load_private_function (dir_name);
00677
00678 if (val.is_defined ())
00679 return val;
00680 }
00681 else
00682 {
00683 octave_value& fval = q->second;
00684
00685 if (fval.is_defined ())
00686 out_of_date_check (fval, "", false);
00687
00688 if (fval.is_defined ())
00689 return fval;
00690 else
00691 {
00692 octave_value val = load_private_function (dir_name);
00693
00694 if (val.is_defined ())
00695 return val;
00696 }
00697 }
00698 }
00699 }
00700 }
00701
00702
00703
00704 if (! args.empty ())
00705 {
00706 std::string dispatch_type = get_dispatch_type (args);
00707
00708 octave_value fcn = find_method (dispatch_type);
00709
00710 if (fcn.is_defined ())
00711 return fcn;
00712 }
00713
00714
00715
00716 str_val_iterator q = class_constructors.find (name);
00717
00718 if (q == class_constructors.end ())
00719 {
00720 octave_value val = load_class_constructor ();
00721
00722 if (val.is_defined ())
00723 return val;
00724 }
00725 else
00726 {
00727 octave_value& fval = q->second;
00728
00729 if (fval.is_defined ())
00730 out_of_date_check (fval, name);
00731
00732 if (fval.is_defined ())
00733 return fval;
00734 else
00735 {
00736 octave_value val = load_class_constructor ();
00737
00738 if (val.is_defined ())
00739 return val;
00740 }
00741 }
00742
00743
00744
00745 if (! args.empty () && ! dispatch_map.empty ())
00746 {
00747 std::string dispatch_type = args(0).type_name ();
00748
00749 std::string fname;
00750
00751 dispatch_map_iterator p = dispatch_map.find (dispatch_type);
00752
00753 if (p == dispatch_map.end ())
00754 p = dispatch_map.find ("any");
00755
00756 if (p != dispatch_map.end ())
00757 {
00758 fname = p->second;
00759
00760 octave_value fcn
00761 = symbol_table::find_function (fname, args);
00762
00763 if (fcn.is_defined ())
00764 return fcn;
00765 }
00766 }
00767
00768
00769
00770 if (cmdline_function.is_defined ())
00771 return cmdline_function;
00772
00773
00774
00775 octave_value fcn = find_autoload ();
00776
00777 if (fcn.is_defined ())
00778 return fcn;
00779
00780
00781
00782 fcn = find_user_function ();
00783
00784 if (fcn.is_defined ())
00785 return fcn;
00786
00787
00788
00789 return built_in_function;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811 octave_value
00812 symbol_table::fcn_info::fcn_info_rep::builtin_find (void)
00813 {
00814 octave_value retval = x_builtin_find ();
00815
00816 if (! retval.is_defined ())
00817 {
00818
00819
00820
00821
00822 load_path::update ();
00823
00824 retval = x_builtin_find ();
00825 }
00826
00827 return retval;
00828 }
00829
00830 octave_value
00831 symbol_table::fcn_info::fcn_info_rep::x_builtin_find (void)
00832 {
00833
00834 if (built_in_function.is_defined ())
00835 return built_in_function;
00836
00837
00838
00839 octave_value fcn = find_user_function ();
00840
00841 if (fcn.is_defined ())
00842 return fcn;
00843
00844
00845
00846 fcn = find_autoload ();
00847
00848 if (fcn.is_defined ())
00849 return fcn;
00850
00851
00852
00853 if (cmdline_function.is_defined ())
00854 return cmdline_function;
00855
00856
00857
00858 octave_user_function *curr_fcn = symbol_table::get_curr_fcn ();
00859
00860 if (curr_fcn)
00861 {
00862 std::string dir_name = curr_fcn->dir_name ();
00863
00864 if (! dir_name.empty ())
00865 {
00866 str_val_iterator q = private_functions.find (dir_name);
00867
00868 if (q == private_functions.end ())
00869 {
00870 octave_value val = load_private_function (dir_name);
00871
00872 if (val.is_defined ())
00873 return val;
00874 }
00875 else
00876 {
00877 octave_value& fval = q->second;
00878
00879 if (fval.is_defined ())
00880 out_of_date_check (fval);
00881
00882 if (fval.is_defined ())
00883 return fval;
00884 else
00885 {
00886 octave_value val = load_private_function (dir_name);
00887
00888 if (val.is_defined ())
00889 return val;
00890 }
00891 }
00892 }
00893 }
00894
00895
00896
00897
00898
00899 scope_val_iterator r = subfunctions.find (xcurrent_scope);
00900
00901 if (r != subfunctions.end ())
00902 {
00903
00904
00905 return r->second;
00906 }
00907 else if (curr_fcn)
00908 {
00909 scope_id pscope = curr_fcn->parent_fcn_scope ();
00910
00911 if (pscope > 0)
00912 {
00913 r = subfunctions.find (pscope);
00914
00915 if (r != subfunctions.end ())
00916 {
00917
00918
00919 return r->second;
00920 }
00921 }
00922 }
00923
00924 return octave_value ();
00925 }
00926
00927 octave_value
00928 symbol_table::fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type)
00929 {
00930 octave_value retval;
00931
00932 str_val_iterator q = class_methods.find (dispatch_type);
00933
00934 if (q == class_methods.end ())
00935 {
00936 octave_value val = load_class_method (dispatch_type);
00937
00938 if (val.is_defined ())
00939 return val;
00940 }
00941 else
00942 {
00943 octave_value& fval = q->second;
00944
00945 if (fval.is_defined ())
00946 out_of_date_check (fval, dispatch_type);
00947
00948 if (fval.is_defined ())
00949 return fval;
00950 else
00951 {
00952 octave_value val = load_class_method (dispatch_type);
00953
00954 if (val.is_defined ())
00955 return val;
00956 }
00957 }
00958
00959 return retval;
00960 }
00961
00962 octave_value
00963 symbol_table::fcn_info::fcn_info_rep::find_autoload (void)
00964 {
00965 octave_value retval;
00966
00967
00968
00969 if (autoload_function.is_defined ())
00970 out_of_date_check (autoload_function);
00971
00972 if (! autoload_function.is_defined ())
00973 {
00974 std::string file_name = lookup_autoload (name);
00975
00976 if (! file_name.empty ())
00977 {
00978 size_t pos = file_name.find_last_of (file_ops::dir_sep_chars ());
00979
00980 std::string dir_name = file_name.substr (0, pos);
00981
00982 octave_function *fcn = load_fcn_from_file (file_name, dir_name,
00983 "", name, true);
00984
00985 if (fcn)
00986 autoload_function = octave_value (fcn);
00987 }
00988 }
00989
00990 return autoload_function;
00991 }
00992
00993 octave_value
00994 symbol_table::fcn_info::fcn_info_rep::find_user_function (void)
00995 {
00996
00997
00998 if (function_on_path.is_defined ())
00999 out_of_date_check (function_on_path);
01000
01001 if (! (error_state || function_on_path.is_defined ()))
01002 {
01003 std::string dir_name;
01004
01005 std::string file_name = load_path::find_fcn (name, dir_name);
01006
01007 if (! file_name.empty ())
01008 {
01009 octave_function *fcn = load_fcn_from_file (file_name, dir_name);
01010
01011 if (fcn)
01012 function_on_path = octave_value (fcn);
01013 }
01014 }
01015
01016 return function_on_path;
01017 }
01018
01019
01020
01021
01022
01023 bool
01024 symbol_table::set_class_relationship (const std::string& sup_class,
01025 const std::string& inf_class)
01026 {
01027 class_precedence_table_const_iterator p
01028 = class_precedence_table.find (inf_class);
01029
01030 if (p != class_precedence_table.end ())
01031 {
01032 const std::set<std::string>& inferior_classes = p->second;
01033
01034 std::set<std::string>::const_iterator q
01035 = inferior_classes.find (sup_class);
01036
01037 if (q != inferior_classes.end ())
01038 return false;
01039 }
01040
01041 class_precedence_table[sup_class].insert (inf_class);
01042
01043 return true;
01044 }
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059 bool
01060 symbol_table::is_superiorto (const std::string& a, const std::string& b)
01061 {
01062 bool retval = false;
01063
01064 class_precedence_table_const_iterator p = class_precedence_table.find (a);
01065
01066 if (p != class_precedence_table.end ())
01067 {
01068 const std::set<std::string>& inferior_classes = p->second;
01069 std::set<std::string>::const_iterator q = inferior_classes.find (b);
01070
01071 if (q != inferior_classes.end ())
01072 retval = true;
01073 }
01074
01075 return retval;
01076 }
01077
01078 static std::string
01079 fcn_file_name (const octave_value& fcn)
01080 {
01081 const octave_function *f = fcn.function_value ();
01082
01083 return f ? f->fcn_file_name () : std::string ();
01084 }
01085
01086 void
01087 symbol_table::fcn_info::fcn_info_rep::dump
01088 (std::ostream& os, const std::string& prefix) const
01089 {
01090 os << prefix << name
01091 << " ["
01092 << (cmdline_function.is_defined () ? "c" : "")
01093 << (built_in_function.is_defined () ? "b" : "")
01094 << "]\n";
01095
01096 std::string tprefix = prefix + " ";
01097
01098 if (autoload_function.is_defined ())
01099 os << tprefix << "autoload: "
01100 << fcn_file_name (autoload_function) << "\n";
01101
01102 if (function_on_path.is_defined ())
01103 os << tprefix << "function from path: "
01104 << fcn_file_name (function_on_path) << "\n";
01105
01106 if (! subfunctions.empty ())
01107 {
01108 for (scope_val_const_iterator p = subfunctions.begin ();
01109 p != subfunctions.end (); p++)
01110 os << tprefix << "subfunction: " << fcn_file_name (p->second)
01111 << " [" << p->first << "]\n";
01112 }
01113
01114 if (! private_functions.empty ())
01115 {
01116 for (str_val_const_iterator p = private_functions.begin ();
01117 p != private_functions.end (); p++)
01118 os << tprefix << "private: " << fcn_file_name (p->second)
01119 << " [" << p->first << "]\n";
01120 }
01121
01122 if (! class_constructors.empty ())
01123 {
01124 for (str_val_const_iterator p = class_constructors.begin ();
01125 p != class_constructors.end (); p++)
01126 os << tprefix << "constructor: " << fcn_file_name (p->second)
01127 << " [" << p->first << "]\n";
01128 }
01129
01130 if (! class_methods.empty ())
01131 {
01132 for (str_val_const_iterator p = class_methods.begin ();
01133 p != class_methods.end (); p++)
01134 os << tprefix << "method: " << fcn_file_name (p->second)
01135 << " [" << p->first << "]\n";
01136 }
01137
01138 if (! dispatch_map.empty ())
01139 {
01140 for (dispatch_map_const_iterator p = dispatch_map.begin ();
01141 p != dispatch_map.end (); p++)
01142 os << tprefix << "dispatch: " << fcn_file_name (p->second)
01143 << " [" << p->first << "]\n";
01144 }
01145 }
01146
01147 octave_value
01148 symbol_table::find (const std::string& name,
01149 const octave_value_list& args,
01150 bool skip_variables,
01151 bool local_funcs)
01152 {
01153 symbol_table *inst = get_instance (xcurrent_scope);
01154
01155 return inst
01156 ? inst->do_find (name, args, skip_variables, local_funcs)
01157 : octave_value ();
01158 }
01159
01160 octave_value
01161 symbol_table::builtin_find (const std::string& name)
01162 {
01163 symbol_table *inst = get_instance (xcurrent_scope);
01164
01165 return inst ? inst->do_builtin_find (name) : octave_value ();
01166 }
01167
01168 octave_value
01169 symbol_table::find_function (const std::string& name,
01170 const octave_value_list& args,
01171 bool local_funcs)
01172 {
01173 octave_value retval;
01174
01175 if (! name.empty () && name[0] == '@')
01176 {
01177
01178 std::string dispatch_type =
01179 name.substr (1, name.find_first_of (file_ops::dir_sep_str ()) - 1);
01180
01181 std::string method =
01182 name.substr (name.find_last_of (file_ops::dir_sep_str ()) + 1,
01183 std::string::npos);
01184
01185 retval = find_method (method, dispatch_type);
01186 }
01187 else
01188 {
01189 size_t pos = name.find_first_of (Vfilemarker);
01190
01191 if (pos == std::string::npos)
01192 retval = find (name, args, true, local_funcs);
01193 else
01194 {
01195 std::string fcn_scope = name.substr (0, pos);
01196 scope_id stored_scope = xcurrent_scope;
01197 xcurrent_scope = xtop_scope;
01198 octave_value parent = find_function (name.substr(0, pos),
01199 octave_value_list (), false);
01200
01201 if (parent.is_defined ())
01202 {
01203 octave_function *parent_fcn = parent.function_value ();
01204
01205 if (parent_fcn)
01206 {
01207 xcurrent_scope = parent_fcn->scope ();
01208
01209 if (xcurrent_scope > 1)
01210 retval = find_function (name.substr (pos + 1), args);
01211 }
01212 }
01213
01214 xcurrent_scope = stored_scope;
01215 }
01216 }
01217
01218 return retval;
01219 }
01220
01221 void
01222 symbol_table::dump (std::ostream& os, scope_id scope)
01223 {
01224 if (scope == xglobal_scope)
01225 dump_global (os);
01226 else
01227 {
01228 symbol_table *inst = get_instance (scope, false);
01229
01230 if (inst)
01231 {
01232 os << "*** dumping symbol table scope " << scope
01233 << " (" << inst->table_name << ")\n\n";
01234
01235 std::map<std::string, octave_value> sfuns
01236 = symbol_table::subfunctions_defined_in_scope (scope);
01237
01238 if (! sfuns.empty ())
01239 {
01240 os << " subfunctions defined in this scope:\n";
01241
01242 for (std::map<std::string, octave_value>::const_iterator p = sfuns.begin ();
01243 p != sfuns.end (); p++)
01244 os << " " << p->first << "\n";
01245
01246 os << "\n";
01247 }
01248
01249 inst->do_dump (os);
01250 }
01251 }
01252 }
01253
01254 void
01255 symbol_table::dump_global (std::ostream& os)
01256 {
01257 if (! global_table.empty ())
01258 {
01259 os << "*** dumping global symbol table\n\n";
01260
01261 for (global_table_const_iterator p = global_table.begin ();
01262 p != global_table.end (); p++)
01263 {
01264 std::string nm = p->first;
01265 octave_value val = p->second;
01266
01267 os << " " << nm << " ";
01268 val.dump (os);
01269 os << "\n";
01270 }
01271 }
01272 }
01273
01274 void
01275 symbol_table::dump_functions (std::ostream& os)
01276 {
01277 if (! fcn_table.empty ())
01278 {
01279 os << "*** dumping globally visible functions from symbol table\n"
01280 << " (c=commandline, b=built-in)\n\n";
01281
01282 for (fcn_table_const_iterator p = fcn_table.begin ();
01283 p != fcn_table.end (); p++)
01284 p->second.dump (os, " ");
01285
01286 os << "\n";
01287 }
01288 }
01289
01290 void
01291 symbol_table::stash_dir_name_for_subfunctions (scope_id scope,
01292 const std::string& dir_name)
01293 {
01294
01295
01296
01297
01298 for (fcn_table_const_iterator p = fcn_table.begin ();
01299 p != fcn_table.end (); p++)
01300 {
01301 std::pair<std::string, octave_value> tmp
01302 = p->second.subfunction_defined_in_scope (scope);
01303
01304 std::string nm = tmp.first;
01305
01306 if (! nm.empty ())
01307 {
01308 octave_value& fcn = tmp.second;
01309
01310 octave_user_function *f = fcn.user_function_value ();
01311
01312 if (f)
01313 f->stash_dir_name (dir_name);
01314 }
01315 }
01316 }
01317
01318 octave_value
01319 symbol_table::do_find (const std::string& name,
01320 const octave_value_list& args,
01321 bool skip_variables,
01322 bool local_funcs)
01323 {
01324 octave_value retval;
01325
01326
01327
01328 if (! skip_variables)
01329 {
01330 table_iterator p = table.find (name);
01331
01332 if (p != table.end ())
01333 {
01334 symbol_record sr = p->second;
01335
01336
01337
01338 if (sr.is_global ())
01339 return symbol_table::global_varref (name);
01340 else
01341 {
01342 octave_value& val = sr.varref ();
01343
01344 if (val.is_defined ())
01345 return val;
01346 }
01347 }
01348 }
01349
01350 fcn_table_iterator p = fcn_table.find (name);
01351
01352 if (p != fcn_table.end ())
01353 return p->second.find (args, local_funcs);
01354 else
01355 {
01356 fcn_info finfo (name);
01357
01358 octave_value fcn = finfo.find (args, local_funcs);
01359
01360 if (fcn.is_defined ())
01361 fcn_table[name] = finfo;
01362
01363 return fcn;
01364 }
01365
01366 return retval;
01367 }
01368
01369 octave_value
01370 symbol_table::do_builtin_find (const std::string& name)
01371 {
01372 octave_value retval;
01373
01374 fcn_table_iterator p = fcn_table.find (name);
01375
01376 if (p != fcn_table.end ())
01377 return p->second.builtin_find ();
01378 else
01379 {
01380 fcn_info finfo (name);
01381
01382 octave_value fcn = finfo.builtin_find ();
01383
01384 if (fcn.is_defined ())
01385 fcn_table[name] = finfo;
01386
01387 return fcn;
01388 }
01389
01390 return retval;
01391 }
01392
01393 void
01394 symbol_table::do_dump (std::ostream& os)
01395 {
01396 if (! persistent_table.empty ())
01397 {
01398 os << " persistent variables in this scope:\n\n";
01399
01400 for (persistent_table_const_iterator p = persistent_table.begin ();
01401 p != persistent_table.end (); p++)
01402 {
01403 std::string nm = p->first;
01404 octave_value val = p->second;
01405
01406 os << " " << nm << " ";
01407 val.dump (os);
01408 os << "\n";
01409 }
01410
01411 os << "\n";
01412 }
01413
01414 if (! table.empty ())
01415 {
01416 os << " other symbols in this scope (l=local; a=auto; f=formal\n"
01417 << " h=hidden; i=inherited; g=global; p=persistent)\n\n";
01418
01419 for (table_const_iterator p = table.begin (); p != table.end (); p++)
01420 p->second.dump (os, " ");
01421
01422 os << "\n";
01423 }
01424 }
01425
01426 void symbol_table::cleanup (void)
01427 {
01428
01429 all_instances[xtop_scope]->clear_variables ();
01430
01431
01432 fcn_table.clear ();
01433
01434
01435
01436 all_instances[xglobal_scope]->clear_variables ();
01437
01438
01439 global_table.clear ();
01440
01441
01442 for (all_instances_iterator iter = all_instances.begin ();
01443 iter != all_instances.end (); iter++)
01444 {
01445 scope_id scope = iter->first;
01446 if (scope != xglobal_scope && scope != xtop_scope)
01447 scope_id_cache::free (scope);
01448
01449
01450 symbol_table *inst = iter->second;
01451 iter->second = 0;
01452
01453
01454
01455 delete inst;
01456 }
01457 }
01458
01459 DEFUN (ignore_function_time_stamp, args, nargout,
01460 "-*- texinfo -*-\n\
01461 @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\
01462 @deftypefnx {Built-in Function} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\n\
01463 Query or set the internal variable that controls whether Octave checks\n\
01464 the time stamp on files each time it looks up functions defined in\n\
01465 function files. If the internal variable is set to @code{\"system\"},\n\
01466 Octave will not automatically recompile function files in subdirectories of\n\
01467 @file{@var{octave-home}/lib/@var{version}} if they have changed since\n\
01468 they were last compiled, but will recompile other function files in the\n\
01469 search path if they change. If set to @code{\"all\"}, Octave will not\n\
01470 recompile any function files unless their definitions are removed with\n\
01471 @code{clear}. If set to \"none\", Octave will always check time stamps\n\
01472 on files to determine whether functions defined in function files\n\
01473 need to recompiled.\n\
01474 @end deftypefn")
01475 {
01476 octave_value retval;
01477
01478 int nargin = args.length ();
01479
01480 if (nargout > 0 || nargin == 0)
01481 {
01482 switch (Vignore_function_time_stamp)
01483 {
01484 case 1:
01485 retval = "system";
01486 break;
01487
01488 case 2:
01489 retval = "all";
01490 break;
01491
01492 default:
01493 retval = "none";
01494 break;
01495 }
01496 }
01497
01498 if (nargin == 1)
01499 {
01500 std::string sval = args(0).string_value ();
01501
01502 if (! error_state)
01503 {
01504 if (sval == "all")
01505 Vignore_function_time_stamp = 2;
01506 else if (sval == "system")
01507 Vignore_function_time_stamp = 1;
01508 else if (sval == "none")
01509 Vignore_function_time_stamp = 0;
01510 else
01511 error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\"");
01512 }
01513 else
01514 error ("ignore_function_time_stamp: expecting argument to be character string");
01515 }
01516 else if (nargin > 1)
01517 print_usage ();
01518
01519 return retval;
01520 }
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541 DEFUN (__current_scope__, , ,
01542 "-*- texinfo -*-\n\
01543 @deftypefn {Built-in Function} {[@var{scope}, @var{context}]} __dump_symtab_info__ ()\n\
01544 Undocumented internal function.\n\
01545 @end deftypefn")
01546 {
01547 octave_value_list retval;
01548
01549 retval(1) = symbol_table::current_context ();
01550 retval(0) = symbol_table::current_scope ();
01551
01552 return retval;
01553 }
01554
01555 DEFUN (__dump_symtab_info__, args, ,
01556 "-*- texinfo -*-\n\
01557 @deftypefn {Built-in Function} {} __dump_symtab_info__ ()\n\
01558 @deftypefnx {Built-in Function} {} __dump_symtab_info__ (@var{scope})\n\
01559 @deftypefnx {Built-in Function} {} __dump_symtab_info__ (\"scopes\")\n\
01560 @deftypefnx {Built-in Function} {} __dump_symtab_info__ (\"functions\")\n\
01561 Undocumented internal function.\n\
01562 @end deftypefn")
01563 {
01564 octave_value retval;
01565
01566 int nargin = args.length ();
01567
01568 if (nargin == 0)
01569 {
01570 symbol_table::dump_functions (octave_stdout);
01571
01572 symbol_table::dump_global (octave_stdout);
01573
01574 std::list<symbol_table::scope_id> lst = symbol_table::scopes ();
01575
01576 for (std::list<symbol_table::scope_id>::const_iterator p = lst.begin ();
01577 p != lst.end (); p++)
01578 symbol_table::dump (octave_stdout, *p);
01579 }
01580 else if (nargin == 1)
01581 {
01582 octave_value arg = args(0);
01583
01584 if (arg.is_string ())
01585 {
01586 std::string s_arg = arg.string_value ();
01587
01588 if (s_arg == "scopes")
01589 {
01590 std::list<symbol_table::scope_id> lst = symbol_table::scopes ();
01591
01592 RowVector v (lst.size ());
01593
01594 octave_idx_type k = 0;
01595
01596 for (std::list<symbol_table::scope_id>::const_iterator p = lst.begin ();
01597 p != lst.end (); p++)
01598 v.xelem (k++) = *p;
01599
01600 retval = v;
01601 }
01602 else if (s_arg == "functions")
01603 {
01604 symbol_table::dump_functions (octave_stdout);
01605 }
01606 else
01607 error ("__dump_symtab_info__: expecting \"functions\" or \"scopes\"");
01608 }
01609 else
01610 {
01611 int s = arg.int_value ();
01612
01613 if (! error_state)
01614 symbol_table::dump (octave_stdout, s);
01615 else
01616 error ("__dump_symtab_info__: expecting string or scope id");
01617 }
01618 }
01619 else
01620 print_usage ();
01621
01622 return retval;
01623 }
01624
01625 #if 0
01626
01627
01628
01629 DEFUN (set_variable, args, , "set_variable (NAME, VALUE)")
01630 {
01631 octave_value retval;
01632
01633 if (args.length () == 2)
01634 {
01635 std::string name = args(0).string_value ();
01636
01637 if (! error_state)
01638 symbol_table::varref (name) = args(1);
01639 else
01640 error ("set_variable: expecting variable name as first argument");
01641 }
01642 else
01643 print_usage ();
01644
01645 return retval;
01646 }
01647
01648 DEFUN (variable_value, args, , "VALUE = variable_value (NAME)")
01649 {
01650 octave_value retval;
01651
01652 if (args.length () == 1)
01653 {
01654 std::string name = args(0).string_value ();
01655
01656 if (! error_state)
01657 {
01658 retval = symbol_table::varval (name);
01659
01660 if (retval.is_undefined ())
01661 error ("variable_value: '%s' is not a variable in the current scope",
01662 name.c_str ());
01663 }
01664 else
01665 error ("variable_value: expecting variable name as first argument");
01666 }
01667 else
01668 print_usage ();
01669
01670 return retval;
01671 }
01672 #endif