GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
fcn-info.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "file-ops.h"
31 #include "file-stat.h"
32 #include "oct-env.h"
33 
34 #include "defun.h"
35 #include "fcn-info.h"
36 #include "interpreter-private.h"
37 #include "interpreter.h"
38 #include "load-path.h"
39 #include "ov-fcn.h"
40 #include "ov-usr-fcn.h"
41 #include "parse.h"
42 #include "symscope.h"
43 #include "symtab.h"
44 #include "utils.h"
45 
46 // Should Octave always check to see if function files have changed
47 // since they were last compiled?
49 
50 namespace octave
51 {
53  fcn_info::fcn_info_rep::load_private_function (const std::string& dir_name)
54  {
56 
57  load_path& lp
58  = __get_load_path__ ("fcn_info::fcn_info_rep::load_private_function");
59 
60  std::string file_name = lp.find_private_fcn (dir_name, name);
61 
62  if (file_name.empty ())
63  return retval;
64 
65  octave_value ov_fcn = load_fcn_from_file (file_name, dir_name);
66 
67  if (ov_fcn.is_undefined ())
68  return retval;
69 
70  octave_function *tmpfcn = ov_fcn.function_value ();
71 
72  if (! tmpfcn)
73  return retval;
74 
75  std::string class_name;
76 
77  size_t pos = dir_name.find_last_of (sys::file_ops::dir_sep_chars ());
78 
79  if (pos != std::string::npos)
80  {
81  std::string tmp = dir_name.substr (pos+1);
82 
83  if (tmp[0] == '@')
84  class_name = tmp.substr (1);
85  }
86 
87  tmpfcn->mark_as_private_function (class_name);
88 
90 
91  return ov_fcn;
92  }
93 
96  {
98 
99  std::string dir_name;
100 
101  load_path& lp
102  = __get_load_path__ ("fcn_info::fcn_info_rep::load_class_constructor");
103 
104  std::string file_name = lp.find_method (name, name, dir_name, package_name);
105 
106  if (! file_name.empty ())
107  {
108  octave_value ov_fcn
109  = load_fcn_from_file (file_name, dir_name, name,
110  package_name);
111 
112  if (ov_fcn.is_defined ())
113  {
114  // Note: ov_fcn may be an octave_classdef_meta object instead
115  // of the actual constructor function.
116 
117  retval = ov_fcn;
118 
119  class_constructors[name] = retval;
120  class_methods[name] = retval;
121  }
122  }
123  else
124  {
125  // Classdef constructors can be defined anywhere in the path, not
126  // necessarily in @-folders. Look for a normal function and load it.
127  // If the loaded function is a classdef constructor, store it as such
128  // and restore function_on_path to its previous value.
129 
130  octave_value old_function_on_path = function_on_path;
131 
132  octave_value maybe_cdef_ctor = find_user_function ();
133 
134  if (maybe_cdef_ctor.is_defined ())
135  {
136  octave_function *fcn = maybe_cdef_ctor.function_value (true);
137 
138  if (fcn && fcn->is_classdef_constructor ())
139  {
140  retval = maybe_cdef_ctor;
141 
142  class_constructors[name] = retval;
143  class_methods[name] = retval;
144 
145  function_on_path = old_function_on_path;
146  }
147  }
148  }
149 
150  return retval;
151  }
152 
154  fcn_info::fcn_info_rep::load_class_method (const std::string& dispatch_type)
155  {
157 
158  if (full_name () == dispatch_type)
159  retval = load_class_constructor ();
160  else
161  {
162  cdef_manager& cdm
163  = __get_cdef_manager__ ("fcn_info::fcn_info_rep::load_class_method");
164 
165  retval = cdm.find_method_symbol (name, dispatch_type);
166 
167  if (! retval.is_defined ())
168  {
169  std::string dir_name;
170 
171  load_path& lp = __get_load_path__ ("fcn_info::fcn_info_rep::load_class_method");
172 
173  std::string file_name = lp.find_method (dispatch_type, name,
174  dir_name);
175 
176  if (! file_name.empty ())
177  {
178  octave_value ov_fcn
179  = load_fcn_from_file (file_name, dir_name,
180  dispatch_type);
181 
182  if (ov_fcn.is_defined ())
183  {
184  octave_function *tmpfcn = ov_fcn.function_value ();
185 
186  if (tmpfcn && tmpfcn->is_class_method (dispatch_type))
187  {
188  retval = ov_fcn;
189 
190  class_methods[dispatch_type] = retval;
191  }
192  }
193  }
194 
195  if (retval.is_undefined ())
196  {
197  // Search parent classes
198 
199  symbol_table& symtab
200  = __get_symbol_table__ ("fcn_info::fcn_info_rep::load_class_method");
201 
202  const std::list<std::string>& plist
203  = symtab.parent_classes (dispatch_type);
204 
205  auto it = plist.begin ();
206 
207  while (it != plist.end ())
208  {
209  retval = find_method (*it);
210 
211  if (retval.is_defined ())
212  {
213  class_methods[dispatch_type] = retval;
214  break;
215  }
216 
217  it++;
218  }
219  }
220 
221  if (retval.is_undefined ())
222  {
223  // Search for built-in functions that are declared to
224  // handle specific types.
225 
226  if (built_in_function.is_defined ())
227  {
228  octave_function *fcn = built_in_function.function_value ();
229 
230  if (fcn && fcn->handles_dispatch_class (dispatch_type))
231  {
232  retval = built_in_function;
233 
234  class_methods[dispatch_type] = retval;
235  }
236  }
237  }
238  }
239  }
240 
241  return retval;
242  }
243 
244  // :-) JWE, can you parse this? Returns a 2D array with second dimension equal
245  // to btyp_num_types (static constant). Only the leftmost dimension can be
246  // variable in C/C++. Typedefs are boring.
247 
249  {
250  static builtin_type_t sup_table[btyp_num_types][btyp_num_types];
251  for (int i = 0; i < btyp_num_types; i++)
252  for (int j = 0; j < btyp_num_types; j++)
253  {
254  builtin_type_t ityp = static_cast<builtin_type_t> (i);
255  builtin_type_t jtyp = static_cast<builtin_type_t> (j);
256  // FIXME: Is this really right?
257  bool use_j
258  = (jtyp == btyp_func_handle || ityp == btyp_bool
259  || (btyp_isarray (ityp)
260  && (! btyp_isarray (jtyp)
261  || (btyp_isinteger (jtyp) && ! btyp_isinteger (ityp))
262  || ((ityp == btyp_double || ityp == btyp_complex
263  || ityp == btyp_char)
264  && (jtyp == btyp_float
265  || jtyp == btyp_float_complex)))));
266 
267  sup_table[i][j] = (use_j ? jtyp : ityp);
268  }
269 
270  return sup_table;
271  }
272 
273  std::string
275  builtin_type_t& builtin_type)
276  {
277  static builtin_type_t (*sup_table)[btyp_num_types] = build_sup_table ();
278  std::string dispatch_type;
279 
280  int n = args.length ();
281 
282  if (n > 0)
283  {
284  int i = 0;
285  builtin_type = args(0).builtin_type ();
286  if (builtin_type != btyp_unknown)
287  {
288  for (i = 1; i < n; i++)
289  {
290  builtin_type_t bti = args(i).builtin_type ();
291  if (bti != btyp_unknown)
292  builtin_type = sup_table[builtin_type][bti];
293  else
294  {
295  builtin_type = btyp_unknown;
296  break;
297  }
298  }
299  }
300 
301  if (builtin_type == btyp_unknown)
302  {
303  // There's a non-builtin class in the argument list.
304  dispatch_type = args(i).class_name ();
305 
306  symbol_table& symtab = __get_symbol_table__ ("get_dispatch_type");
307 
308  for (int j = i+1; j < n; j++)
309  {
310  octave_value arg = args(j);
311 
312  if (arg.builtin_type () == btyp_unknown)
313  {
314  std::string cname = arg.class_name ();
315 
316  // Only switch to type of ARG if it is marked superior
317  // to the current DISPATCH_TYPE.
318  if (! symtab.is_superiorto (dispatch_type, cname)
319  && symtab.is_superiorto (cname, dispatch_type))
320  dispatch_type = cname;
321  }
322  }
323  }
324  else
325  dispatch_type = btyp_class_name[builtin_type];
326  }
327  else
328  builtin_type = btyp_unknown;
329 
330  return dispatch_type;
331  }
332 
333  std::string
335  {
336  builtin_type_t builtin_type;
337  return get_dispatch_type (args, builtin_type);
338  }
339 
340  // Find function definition according to the following precedence list:
341  //
342  // nested functions (and subfunctions)
343  // local functions in the current file
344  // private function
345  // class method
346  // class constructor
347  // command-line function
348  // autoload function
349  // functions on the load_path (current directory is always first)
350  // package (FIXME: does this belong here?)
351  // built-in function
352 
355  const octave_value_list& args)
356  {
357  symbol_scope search_scope
358  = (scope
359  ? scope : __get_current_scope__("fcn_info::fcn_info_rep::find"));
360 
361  octave_value retval = xfind (search_scope, args);
362 
363  if (retval.is_undefined ())
364  {
365  // It is possible that the user created a file on the fly since
366  // the last prompt or chdir, so try updating the load path and
367  // searching again.
368 
369  load_path& lp = __get_load_path__ ("fcn_info::fcn_info_rep::find");
370 
371  lp.update ();
372 
373  retval = xfind (search_scope, args);
374  }
375 
376  return retval;
377  }
378 
379 
380  static void
381  split_name_with_package (const std::string& name, std::string& fname,
382  std::string& pname)
383  {
384  size_t pos = name.rfind ('.');
385 
386  fname.clear ();
387  pname.clear ();
388 
389  if (pos != std::string::npos)
390  {
391  fname = name.substr (pos + 1);
392  pname = name.substr (0, pos);
393  }
394  else
395  fname = name;
396  }
397 
398  // Check the load path to see if file that defined this is still
399  // visible. If the file is no longer visible, then erase the
400  // definition and move on. If the file is visible, then we also
401  // need to check to see whether the file has changed since the
402  // function was loaded/parsed. However, this check should only
403  // happen once per prompt (for files found from relative path
404  // elements, we also check if the working directory has changed
405  // since the last time the function was loaded/parsed).
406  //
407  // FIXME: perhaps this should be done for all loaded functions when
408  // the prompt is printed or the directory has changed, and then we
409  // would not check for it when finding symbol definitions.
410 
411  static inline bool
412  load_out_of_date_fcn (const std::string& ff, const std::string& dir_name,
413  octave_value& function,
414  const std::string& dispatch_type = "",
415  const std::string& package_name = "")
416  {
417  bool retval = false;
418 
419  octave_value ov_fcn
420  = load_fcn_from_file (ff, dir_name, dispatch_type,
421  package_name);
422 
423  if (ov_fcn.is_defined ())
424  {
425  retval = true;
426 
427  function = ov_fcn;
428  }
429  else
430  function = octave_value ();
431 
432  return retval;
433  }
434 
435  static bool
437  const std::string& dispatch_type = "",
438  bool check_relative = true)
439  {
440  bool retval = false;
441 
442  octave_function *fcn = function.function_value (true);
443 
444  if (fcn)
445  {
446  // FIXME: we need to handle subfunctions properly here.
447 
448  if (! (fcn->is_subfunction () || fcn->is_anonymous_function ()))
449  {
450  std::string ff = fcn->fcn_file_name ();
451 
452  if (! ff.empty ())
453  {
454  sys::time tc = fcn->time_checked ();
455 
456  bool relative = check_relative && fcn->is_relative ();
457 
458  if (tc <= Vlast_prompt_time
459  || (relative && tc < Vlast_chdir_time))
460  {
461  bool clear_breakpoints = false;
462  std::string nm = fcn->name ();
463  std::string pack = fcn->package_name ();
464  std::string canonical_nm = fcn->canonical_name ();
465 
466  bool is_same_file = false;
467 
468  std::string file;
469  std::string dir_name;
470 
471  if (check_relative)
472  {
473  int nm_len = nm.length ();
474 
476  && ((nm_len > 4
477  && (nm.substr (nm_len-4) == ".oct"
478  || nm.substr (nm_len-4) == ".mex"))
479  || (nm_len > 2
480  && nm.substr (nm_len-2) == ".m")))
481  file = nm;
482  else
483  {
484  // We don't want to make this an absolute name,
485  // because load_fcn_file looks at the name to
486  // decide whether it came from a relative lookup.
487 
488  if (! dispatch_type.empty ())
489  {
490  load_path& lp
491  = __get_load_path__ ("out_of_date_check");
492 
493  file = lp.find_method (dispatch_type, nm,
494  dir_name, pack);
495 
496  if (file.empty ())
497  {
498  std::string s_name;
499  std::string s_pack;
500 
501  symbol_table& symtab
502  = __get_symbol_table__ ("out_of_date_check");
503 
504  const std::list<std::string>& plist
505  = symtab.parent_classes (dispatch_type);
506 
507  std::list<std::string>::const_iterator it
508  = plist.begin ();
509 
510  while (it != plist.end ())
511  {
512  split_name_with_package (*it, s_name,
513  s_pack);
514 
515  file = lp.find_method (*it, nm, dir_name,
516  s_pack);
517  if (! file.empty ())
518  {
519  pack = s_pack;
520  break;
521  }
522 
523  it++;
524  }
525  }
526  }
527 
528  // Maybe it's an autoload?
529  if (file.empty ())
530  {
531  tree_evaluator& tw
532  = __get_evaluator__ ("out_of_data_check");
533 
534  file = tw.lookup_autoload (nm);
535  }
536 
537  if (file.empty ())
538  {
539  load_path& lp
540  = __get_load_path__ ("out_of_date_check");
541  file = lp.find_fcn (nm, dir_name, pack);
542  }
543  }
544 
545  if (! file.empty ())
546  is_same_file = same_file (file, ff);
547  }
548  else
549  {
550  is_same_file = true;
551  file = ff;
552  }
553 
554  if (file.empty ())
555  {
556  // Can't see this function from current
557  // directory, so we should clear it.
558 
559  function = octave_value ();
560 
561  clear_breakpoints = true;
562  }
563  else if (is_same_file)
564  {
565  // Same file. If it is out of date, then reload it.
566 
567  sys::time ottp = fcn->time_parsed ();
568  time_t tp = ottp.unix_time ();
569 
571 
572  if (! (Vignore_function_time_stamp == 2
574  && fcn->is_system_fcn_file ())))
575  {
576  sys::file_stat fs (ff);
577 
578  if (fs)
579  {
580  if (fs.is_newer (tp))
581  {
582  retval = load_out_of_date_fcn (ff, dir_name,
583  function,
584  dispatch_type,
585  pack);
586 
587  clear_breakpoints = true;
588  }
589  }
590  else
591  {
592  function = octave_value ();
593 
594  clear_breakpoints = true;
595  }
596  }
597  }
598  else
599  {
600  // Not the same file, so load the new file in
601  // place of the old.
602 
603  retval = load_out_of_date_fcn (file, dir_name, function,
604  dispatch_type, pack);
605 
606  clear_breakpoints = true;
607  }
608 
609  // If the function has been replaced then clear any
610  // breakpoints associated with it
611  if (clear_breakpoints)
612  {
613  bp_table& bptab
614  = __get_bp_table__ ("out_of_date_check");
615 
616  bptab.remove_all_breakpoints_in_file (canonical_nm,
617  true);
618  }
619  }
620  }
621  }
622  }
623 
624  return retval;
625  }
626 
629  {
630  if (search_scope)
631  {
632  // Subfunction.
633 
634  octave_value fcn = search_scope.find_subfunction (name);
635 
636  if (fcn.is_defined ())
637  return fcn;
638 
639  // Local function.
640 
641  std::string fcn_file = search_scope.fcn_file_name ();
642 
643  // For anonymous functions we look at the parent scope so that if
644  // they were defined within class methods and use local functions
645  // (helper functions) we can still use those anonymous functions
646 
647  if (! fcn_file.empty ())
648  {
649  auto r = local_functions.find (fcn_file);
650 
651  if (r != local_functions.end ())
652  {
653  // We shouldn't need an out-of-date check here since
654  // local functions may ultimately be called only from
655  // a primary function or method defined in the same
656  // file.
657 
658  return r->second;
659  }
660  }
661 
662  // Private function.
663 
664  return find_private_function (search_scope.dir_name ());
665  }
666 
667  return octave_value ();
668  }
669 
671  fcn_info::fcn_info_rep::find_private_function (const std::string& dir_name)
672  {
673  if (! dir_name.empty ())
674  {
675  auto q = private_functions.find (dir_name);
676 
677  if (q == private_functions.end ())
678  {
679  octave_value val = load_private_function (dir_name);
680 
681  if (val.is_defined ())
682  return val;
683  }
684  else
685  {
686  octave_value& fval = q->second;
687 
688  if (fval.is_defined ())
689  out_of_date_check (fval, "", false);
690 
691  if (fval.is_defined ())
692  return fval;
693  else
694  {
695  octave_value val = load_private_function (dir_name);
696 
697  if (val.is_defined ())
698  return val;
699  }
700  }
701  }
702 
703  return octave_value ();
704  }
705 
708  {
709  if (! args.empty ())
710  {
711  std::string dispatch_type = get_dispatch_type (args);
712 
713  return find_method (dispatch_type);
714  }
715 
716  return octave_value ();
717  }
718 
721  const octave_value_list& args)
722  {
723  // Subfunction, local function, or private function.
724 
725  octave_value fcn;
726 
727  fcn = find_scoped_function (search_scope);
728 
729  if (fcn.is_defined ())
730  return fcn;
731 
732  // Class methods.
733 
734  fcn = find_method (args);
735 
736  if (fcn.is_defined ())
737  return fcn;
738 
739  // Class constructors. The class name and function name are the same.
740 
741  auto q = class_constructors.find (name);
742 
743  if (q == class_constructors.end ())
744  {
745  octave_value val = load_class_constructor ();
746 
747  if (val.is_defined ())
748  return val;
749  }
750  else
751  {
752  octave_value& fval = q->second;
753 
754  if (fval.is_defined ())
755  out_of_date_check (fval, name);
756 
757  if (fval.is_defined ())
758  return fval;
759  else
760  {
761  octave_value val = load_class_constructor ();
762 
763  if (val.is_defined ())
764  return val;
765  }
766  }
767 
768  // Command-line function.
769 
770  if (cmdline_function.is_defined ())
771  return cmdline_function;
772 
773  // Autoload?
774 
775  fcn = find_autoload ();
776 
777  if (fcn.is_defined ())
778  return fcn;
779 
780  // Function on the path.
781 
782  fcn = find_user_function ();
783 
784  if (fcn.is_defined ())
785  return fcn;
786 
787  // Package
788 
789  fcn = find_package ();
790 
791  if (fcn.is_defined ())
792  return fcn;
793 
794  // Built-in function (might be undefined).
795 
796  return built_in_function;
797  }
798 
799  // Find the definition of NAME according to the following precedence
800  // list:
801  //
802  // built-in function
803  // function on the path
804  // autoload function
805  // command-line function
806  // private function
807  // subfunction
808 
809  // This function is used to implement the "builtin" function, which
810  // searches for "built-in" functions. In Matlab, "builtin" only
811  // returns functions that are actually built-in to the interpreter.
812  // But since the list of built-in functions is different in Octave and
813  // Matlab, we also search up the precedence list until we find
814  // something that matches. Note that we are only searching by name,
815  // so class methods and constructors are skipped.
816 
819  {
820  symbol_scope search_scope
821  = (scope
822  ? scope : __get_current_scope__("fcn_info::fcn_info_rep::find"));
823 
824  octave_value retval = x_builtin_find (search_scope);
825 
826  if (! retval.is_defined ())
827  {
828  // It is possible that the user created a file on the fly since
829  // the last prompt or chdir, so try updating the load path and
830  // searching again.
831 
832  load_path& lp = __get_load_path__ ("fcn_info::fcn_info_rep::builtin_find");
833 
834  lp.update ();
835 
836  retval = x_builtin_find (search_scope);
837  }
838 
839  return retval;
840  }
841 
844  {
845  // Built-in function.
846  if (built_in_function.is_defined ())
847  return built_in_function;
848 
849  // Function on the path.
850 
852 
853  if (fcn.is_defined ())
854  return fcn;
855 
856  // Autoload?
857 
858  fcn = find_autoload ();
859 
860  if (fcn.is_defined ())
861  return fcn;
862 
863  // Command-line function.
864 
865  if (cmdline_function.is_defined ())
866  return cmdline_function;
867 
868  // Private function, local function, or subfunction.
869 
870  if (search_scope)
871  {
872  // Private function.
873 
874  std::string dir_name = search_scope.dir_name ();
875 
876  if (! dir_name.empty ())
877  {
878  auto q = private_functions.find (dir_name);
879 
880  if (q == private_functions.end ())
881  {
882  octave_value val = load_private_function (dir_name);
883 
884  if (val.is_defined ())
885  return val;
886  }
887  else
888  {
889  octave_value& fval = q->second;
890 
891  if (fval.is_defined ())
892  out_of_date_check (fval);
893 
894  if (fval.is_defined ())
895  return fval;
896  else
897  {
898  octave_value val = load_private_function (dir_name);
899 
900  if (val.is_defined ())
901  return val;
902  }
903  }
904  }
905 
906  // Local function.
907 
908  std::string fcn_file = search_scope.fcn_file_name ();
909 
910  if (! fcn_file.empty ())
911  {
912  auto r = local_functions.find (fcn_file);
913 
914  if (r != local_functions.end ())
915  {
916  // We shouldn't need an out-of-date check here since local
917  // functions may ultimately be called only from a primary
918  // function or method defined in the same file.
919 
920  return r->second;
921  }
922  }
923 
924  // Subfunction. I think it only makes sense to check for
925  // subfunctions if we are currently executing a function defined
926  // from a .m file.
927 
928  octave_value val = search_scope.find_subfunction (name);
929 
930  if (val.is_defined ())
931  return val;
932  }
933 
934  return octave_value ();
935  }
936 
938  fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type)
939  {
941 
942  auto q = class_methods.find (dispatch_type);
943 
944  if (q == class_methods.end ())
945  {
946  octave_value val = load_class_method (dispatch_type);
947 
948  if (val.is_defined ())
949  return val;
950  }
951  else
952  {
953  octave_value& fval = q->second;
954 
955  if (fval.is_defined ())
956  out_of_date_check (fval, dispatch_type);
957 
958  if (fval.is_defined ())
959  return fval;
960  else
961  {
962  octave_value val = load_class_method (dispatch_type);
963 
964  if (val.is_defined ())
965  return val;
966  }
967  }
968 
969  return retval;
970  }
971 
974  {
975  // Autoloaded function.
976 
977  if (autoload_function.is_defined ())
978  out_of_date_check (autoload_function);
979 
980  if (! autoload_function.is_defined ())
981  {
982  tree_evaluator& tw
983  = __get_evaluator__ ("fcn_info::fcn_info_rep::x_builtin_find");
984 
985  std::string file_name = tw.lookup_autoload (name);
986 
987  if (! file_name.empty ())
988  {
989  size_t pos = file_name.find_last_of (sys::file_ops::dir_sep_chars ());
990 
991  std::string dir_name = file_name.substr (0, pos);
992 
993  octave_value ov_fcn
994  = load_fcn_from_file (file_name, dir_name, "", "", name, true);
995 
996  if (ov_fcn.is_defined ())
997  autoload_function = octave_value (ov_fcn);
998  }
999  }
1000 
1001  return autoload_function;
1002  }
1003 
1004  octave_value
1006  {
1007  // Function on the path.
1008 
1009  if (function_on_path.is_defined ())
1010  out_of_date_check (function_on_path);
1011 
1012  if (function_on_path.is_undefined ())
1013  {
1014  std::string dir_name;
1015 
1016  load_path& lp
1017  = __get_load_path__ ("fcn_info::fcn_info_rep::find_user_function");
1018 
1019 
1020  std::string file_name = lp.find_fcn (name, dir_name, package_name);
1021 
1022  if (! file_name.empty ())
1023  {
1024  octave_value ov_fcn
1025  = load_fcn_from_file (file_name, dir_name, "", package_name);
1026 
1027  if (ov_fcn.is_defined ())
1028  function_on_path = ov_fcn;
1029  }
1030  }
1031 
1032  return function_on_path;
1033  }
1034 
1035  octave_value
1037  {
1038  // FIXME: implement correct way to check out of date package
1039  //if (package.is_defined ())
1040  // out_of_date_check (package);
1041 
1042  if (package.is_undefined ())
1043  {
1044  cdef_manager& cdm
1045  = __get_cdef_manager__ ("fcn_info::fcn_info_rep::find_package");
1046 
1047  package = cdm.find_package_symbol (full_name ());
1048  }
1049 
1050  return package;
1051  }
1052 
1053  void
1055  {
1056  if (built_in_function.is_defined ())
1057  {
1058  octave_function *fcn = built_in_function.function_value ();
1059 
1060  if (fcn)
1061  {
1062  if (fcn->handles_dispatch_class (klass))
1063  warning ("install_built_in_dispatch: '%s' already defined for class '%s'",
1064  name.c_str (), klass.c_str ());
1065  else
1066  fcn->push_dispatch_class (klass);
1067  }
1068  }
1069  else
1070  error ("install_built_in_dispatch: '%s' is not a built-in function",
1071  name.c_str ());
1072  }
1073 
1074  octave_value
1076  {
1077  std::map<std::string, octave_value> m
1078  = {{ "name", full_name () },
1079  { "package", package.dump () },
1080  { "local_functions", dump_function_map (local_functions) },
1081  { "private_functions", dump_function_map (private_functions) },
1082  { "class_methods", dump_function_map (class_methods) },
1083  { "class_constructors", dump_function_map (class_constructors) },
1084  { "cmdline_function", cmdline_function.dump () },
1085  { "autoload_function", autoload_function.dump () },
1086  { "function_on_path", function_on_path.dump () },
1087  { "built_in_function", built_in_function.dump () }};
1088 
1089  return octave_value (m);
1090  }
1091 
1092  octave_value
1093  dump_function_map (const std::map<std::string, octave_value>& fcn_map)
1094  {
1095  if (fcn_map.empty ())
1096  return octave_value (Matrix ());
1097 
1098  std::map<std::string, octave_value> info_map;
1099 
1100  for (const auto& nm_fcn : fcn_map)
1101  {
1102  std::string nm = nm_fcn.first;
1103  const octave_value& fcn = nm_fcn.second;
1104  info_map[nm] = fcn.dump ();
1105  }
1106 
1107  return octave_value (info_map);
1108  }
1109 }
1110 
1111 DEFUN (ignore_function_time_stamp, args, nargout,
1112  doc: /* -*- texinfo -*-
1113 @deftypefn {} {@var{val} =} ignore_function_time_stamp ()
1114 @deftypefnx {} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})
1115 Query or set the internal variable that controls whether Octave checks
1116 the time stamp on files each time it looks up functions defined in
1117 function files.
1118 
1119 If the internal variable is set to @qcode{"system"}, Octave will not
1120 automatically recompile function files in subdirectories of
1121 @file{@var{octave-home}/share/@var{version}/m} if they have changed since
1122 they were last compiled, but will recompile other function files in the
1123 search path if they change.
1124 
1125 If set to @qcode{"all"}, Octave will not recompile any function files
1126 unless their definitions are removed with @code{clear}.
1127 
1128 If set to @qcode{"none"}, Octave will always check time stamps on files
1129 to determine whether functions defined in function files need to
1130 recompiled.
1131 @end deftypefn */)
1132 {
1133  int nargin = args.length ();
1134 
1135  if (nargin > 1)
1136  print_usage ();
1137 
1139 
1140  if (nargout > 0 || nargin == 0)
1141  {
1143  {
1144  case 1:
1145  retval = "system";
1146  break;
1147 
1148  case 2:
1149  retval = "all";
1150  break;
1151 
1152  default:
1153  retval = "none";
1154  break;
1155  }
1156  }
1157 
1158  if (nargin == 1)
1159  {
1160  std::string sval = args(0).xstring_value ("ignore_function_time_stamp: first argument must be a string");
1161 
1162  if (sval == "all")
1164  else if (sval == "system")
1166  else if (sval == "none")
1168  else
1169  error (R"(ignore_function_time_stamp: argument must be one of "all", "system", or "none")");
1170  }
1171 
1172  return retval;
1173 }
1174 
1175 /*
1176 %!shared old_state
1177 %! old_state = ignore_function_time_stamp ();
1178 %!test
1179 %! state = ignore_function_time_stamp ("all");
1180 %! assert (state, old_state);
1181 %! assert (ignore_function_time_stamp (), "all");
1182 %! state = ignore_function_time_stamp ("system");
1183 %! assert (state, "all");
1184 %! assert (ignore_function_time_stamp (), "system");
1185 %! ignore_function_time_stamp (old_state);
1186 
1187 ## Test input validation
1188 %!error (ignore_function_time_stamp ("all", "all"))
1189 %!error (ignore_function_time_stamp ("UNKNOWN_VALUE"))
1190 %!error (ignore_function_time_stamp (42))
1191 */
Array< octave_idx_type > find(octave_idx_type n=-1, bool backward=false) const
Find indices of (at most n) nonzero elements.
Definition: Array.cc:2225
Definition: dMatrix.h:42
intmap remove_all_breakpoints_in_file(const std::string &fname, bool silent=false)
Definition: bp-table.cc:759
octave_value find_method_symbol(const std::string &method_name, const std::string &class_name)
octave_value load_private_function(const std::string &dir_name)
Definition: fcn-info.cc:53
octave_value x_builtin_find(const symbol_scope &search_scope)
Definition: fcn-info.cc:843
octave_value load_class_method(const std::string &dispatch_type)
Definition: fcn-info.cc:154
octave_value find_autoload(void)
Definition: fcn-info.cc:973
octave_value find_scoped_function(const symbol_scope &search_scope)
Definition: fcn-info.cc:628
octave_value dump(void) const
Definition: fcn-info.cc:1075
octave_value builtin_find(const symbol_scope &search_scope)
Definition: fcn-info.cc:818
void install_built_in_dispatch(const std::string &klass)
Definition: fcn-info.cc:1054
octave_value find_private_function(const std::string &dir_name)
Definition: fcn-info.cc:671
octave_value find_package(void)
Definition: fcn-info.cc:1036
octave_value find_user_function(void)
Definition: fcn-info.cc:1005
octave_value load_class_constructor(void)
Definition: fcn-info.cc:95
octave_value find(const symbol_scope &search_scope, const octave_value_list &args)
Definition: fcn-info.cc:354
std::map< std::string, octave_value > private_functions
Definition: fcn-info.h:215
octave_value xfind(const symbol_scope &search_scope, const octave_value_list &args)
Definition: fcn-info.cc:720
octave_value find_method(const std::string &dispatch_type)
Definition: fcn-info.cc:938
octave_value find_user_function(void)
Definition: fcn-info.h:295
octave_value find_private_function(const std::string &dir_name) const
Definition: fcn-info.h:269
octave_value find_autoload(void)
Definition: fcn-info.h:289
octave_value find_scoped_function(const symbol_scope &search_scope) const
Definition: fcn-info.h:264
octave_value find_method(const std::string &dispatch_type) const
Definition: fcn-info.h:274
std::string find_private_fcn(const std::string &dir, const std::string &fcn, const std::string &pack_name="")
Definition: load-path.h:124
std::string find_method(const std::string &class_name, const std::string &meth, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:79
std::string find_fcn(const std::string &fcn, std::string &dir_name, const std::string &pack_name="")
Definition: load-path.h:111
void update(void) const
Definition: load-path.cc:395
std::string fcn_file_name(void) const
Definition: symscope.h:647
octave_value find_subfunction(const std::string &name) const
Definition: symscope.h:519
std::string dir_name(void) const
Definition: symscope.h:652
bool is_superiorto(const std::string &a, const std::string &b)
Definition: symtab.cc:537
std::list< std::string > parent_classes(const std::string &dispatch_type)
Definition: symtab.cc:669
bool is_newer(const sys::time &time) const
Definition: file-stat.h:152
static bool absolute_pathname(const std::string &s)
Definition: oct-env.cc:112
time_t unix_time(void) const
Definition: oct-time.h:113
std::string lookup_autoload(const std::string &nm) const
Definition: pt-eval.cc:3684
virtual bool is_anonymous_function(void) const
Definition: ov-base.h:463
virtual octave_function * function_value(bool silent=false)
Definition: ov-base.cc:873
virtual bool handles_dispatch_class(const std::string &) const
Definition: ov-fcn.h:146
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:78
virtual octave::sys::time time_parsed(void) const
Definition: ov-fcn.h:99
bool is_relative(void) const
Definition: ov-fcn.h:212
std::string package_name(void) const
Definition: ov-fcn.h:155
bool is_class_method(const std::string &cname="") const
Definition: ov-fcn.h:118
virtual void push_dispatch_class(const std::string &)
Definition: ov-fcn.h:144
virtual bool is_subfunction(void) const
Definition: ov-fcn.h:111
virtual bool is_classdef_constructor(const std::string &="") const
Definition: ov-fcn.h:128
std::string canonical_name(void) const
Definition: ov-fcn.h:216
virtual octave::sys::time time_checked(void) const
Definition: ov-fcn.h:102
virtual void mark_fcn_file_up_to_date(const octave::sys::time &)
Definition: ov-fcn.h:95
virtual void mark_as_private_function(const std::string &cname="")
Definition: ov-fcn.h:158
std::string name(void) const
Definition: ov-fcn.h:214
virtual bool is_system_fcn_file(void) const
Definition: ov-fcn.h:76
bool empty(void) const
Definition: ovl.h:115
octave_idx_type length(void) const
Definition: ovl.h:113
builtin_type_t builtin_type(void) const
Definition: ov.h:643
octave_value dump(void) const
Definition: ov.h:1362
bool is_defined(void) const
Definition: ov.h:551
std::string class_name(void) const
Definition: ov.h:1256
octave_function * function_value(bool silent=false) const
bool is_undefined(void) const
Definition: ov.h:554
OCTINTERP_API void print_usage(void)
Definition: defun.cc:53
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
void warning(const char *fmt,...)
Definition: error.cc:1050
void error(const char *fmt,...)
Definition: error.cc:968
static int Vignore_function_time_stamp
Definition: fcn-info.cc:48
QString name
octave::sys::time Vlast_prompt_time
Definition: input.cc:83
T octave_idx_type m
Definition: mx-inlines.cc:773
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::string dir_sep_chars(void)
Definition: file-ops.cc:252
std::string canonicalize_file_name(const std::string &name)
Definition: file-ops.cc:693
static void split_name_with_package(const std::string &name, std::string &fname, std::string &pname)
Definition: fcn-info.cc:381
octave_value load_fcn_from_file(const std::string &file_name, const std::string &dir_name, const std::string &dispatch_type, const std::string &package_name, const std::string &fcn_name, bool autoload)
Definition: oct-parse.cc:9321
std::string get_dispatch_type(const octave_value_list &args, builtin_type_t &builtin_type)
Definition: fcn-info.cc:274
static bool out_of_date_check(octave_value &function, const std::string &dispatch_type="", bool check_relative=true)
Definition: fcn-info.cc:436
octave_value dump_function_map(const std::map< std::string, octave_value > &fcn_map)
Definition: fcn-info.cc:1093
bp_table & __get_bp_table__(const std::string &who)
tree_evaluator & __get_evaluator__(const std::string &who)
static builtin_type_t(* build_sup_table(void))[btyp_num_types]
Definition: fcn-info.cc:248
static bool load_out_of_date_fcn(const std::string &ff, const std::string &dir_name, octave_value &function, const std::string &dispatch_type="", const std::string &package_name="")
Definition: fcn-info.cc:412
sys::time Vlast_chdir_time
Definition: interpreter.cc:323
symbol_scope __get_current_scope__(const std::string &who)
symbol_table & __get_symbol_table__(const std::string &who)
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:138
cdef_manager & __get_cdef_manager__(const std::string &who)
load_path & __get_load_path__(const std::string &who)
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
std::string btyp_class_name[btyp_num_types]
Definition: ov-base.cc:89
bool btyp_isinteger(builtin_type_t btyp)
Definition: ov-base.h:100
bool btyp_isarray(builtin_type_t btyp)
Definition: ov-base.h:106
builtin_type_t
Definition: ov-base.h:72
@ btyp_float_complex
Definition: ov-base.h:76
@ btyp_func_handle
Definition: ov-base.h:89
@ btyp_double
Definition: ov-base.h:73
@ btyp_float
Definition: ov-base.h:74
@ btyp_bool
Definition: ov-base.h:85
@ btyp_unknown
Definition: ov-base.h:90
@ btyp_num_types
Definition: ov-base.h:91
@ btyp_char
Definition: ov-base.h:86
@ btyp_complex
Definition: ov-base.h:75
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811