GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov-fcn-handle.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2003-2018 John W. Eaton
4 Copyright (C) 2009 VZLU Prague, a.s.
5 Copyright (C) 2010 Jaroslav Hajek
6 
7 This file is part of Octave.
8 
9 Octave is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #if defined (HAVE_CONFIG_H)
26 # include "config.h"
27 #endif
28 
29 #include <iostream>
30 #include <list>
31 #include <sstream>
32 #include <vector>
33 
34 #include "file-ops.h"
35 #include "oct-locbuf.h"
36 
37 #include "call-stack.h"
38 #include "defaults.h"
39 #include "defun.h"
40 #include "error.h"
41 #include "errwarn.h"
42 #include "file-stat.h"
43 #include "input.h"
44 #include "interpreter-private.h"
45 #include "interpreter.h"
46 #include "load-path.h"
47 #include "oct-env.h"
48 #include "oct-hdf5.h"
49 #include "oct-map.h"
50 #include "ov-base.h"
51 #include "ov-fcn-handle.h"
52 #include "ov-usr-fcn.h"
53 #include "parse.h"
54 #include "pr-output.h"
55 #include "pt-arg-list.h"
56 #include "pt-assign.h"
57 #include "pt-cmd.h"
58 #include "pt-eval.h"
59 #include "pt-exp.h"
60 #include "pt-idx.h"
61 #include "pt-misc.h"
62 #include "pt-pr-code.h"
63 #include "pt-stmt.h"
64 #include "symscope.h"
65 #include "unwind-prot.h"
66 #include "variables.h"
67 
68 #include "byte-swap.h"
69 #include "ls-ascii-helper.h"
70 #include "ls-hdf5.h"
71 #include "ls-oct-text.h"
72 #include "ls-oct-binary.h"
73 #include "ls-utils.h"
74 
75 
77  "function handle",
78  "function_handle");
79 
80 const std::string octave_fcn_handle::anonymous ("@<anonymous>");
81 
83  const std::string& n)
84  : fcn (f), nm (n), has_overloads (false)
85 {
87 
88  if (uf && nm != anonymous)
89  {
90  octave::symbol_scope uf_scope = uf->scope ();
91 
92  if (uf_scope)
93  uf_scope.cache_name (nm);
94  }
95 
96  if (uf && uf->is_nested_function () && ! uf->is_subfunction ())
97  error ("handles to nested functions are not yet supported");
98 }
99 
102  const std::list<octave_value_list>& idx,
103  int nargout)
104 {
106 
107  switch (type[0])
108  {
109  case '(':
110  {
111  int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout;
112 
113  retval = call (tmp_nargout, idx.front ());
114  }
115  break;
116 
117  case '{':
118  case '.':
119  {
120  std::string tnm = type_name ();
121  error ("%s cannot be indexed with %c", tnm.c_str (), type[0]);
122  }
123  break;
124 
125  default:
126  panic_impossible ();
127  }
128 
129  // FIXME: perhaps there should be an
130  // octave_value_list::next_subsref member function? See also
131  // octave_builtin::subsref.
132 
133  if (idx.size () > 1)
134  retval = retval(0).next_subsref (nargout, type, idx);
135 
136  return retval;
137 }
138 
141 {
143 
144  octave::out_of_date_check (fcn, "", false);
145 
146  if (has_overloads)
147  {
148  // Possibly overloaded function.
149  octave_value ov_fcn;
150 
151  // Compute dispatch type.
152  builtin_type_t btyp;
153  std::string dispatch_type = octave::get_dispatch_type (args, btyp);
154 
155  // Retrieve overload.
156  if (btyp != btyp_unknown)
157  {
158  octave::out_of_date_check (builtin_overloads[btyp], dispatch_type, false);
159  ov_fcn = builtin_overloads[btyp];
160  }
161  else
162  {
163  str_ov_map::iterator it = overloads.find (dispatch_type);
164 
165  if (it == overloads.end ())
166  {
167  // Try parent classes too.
168 
169  octave::symbol_table& symtab
170  = octave::__get_symbol_table__ ("octave_fcn_handle::call");
171 
172  std::list<std::string> plist
173  = symtab.parent_classes (dispatch_type);
174 
175  std::list<std::string>::const_iterator pit = plist.begin ();
176 
177  while (pit != plist.end ())
178  {
179  std::string pname = *pit;
180 
181  std::string fnm = fcn_name ();
182 
183  octave_value ftmp = symtab.find_method (fnm, pname);
184 
185  if (ftmp.is_defined ())
186  {
187  set_overload (pname, ftmp);
188 
189  octave::out_of_date_check (ftmp, pname, false);
190  ov_fcn = ftmp;
191 
192  break;
193  }
194 
195  pit++;
196  }
197  }
198  else
199  {
200  octave::out_of_date_check (it->second, dispatch_type, false);
201  ov_fcn = it->second;
202  }
203  }
204 
205  if (ov_fcn.is_defined ())
206  retval = octave::feval (ov_fcn, args, nargout);
207  else if (fcn.is_defined ())
208  retval = octave::feval (fcn, args, nargout);
209  else
210  error ("%s: no method for class %s",
211  nm.c_str (), dispatch_type.c_str ());
212  }
213  else
214  {
215  // Non-overloaded function (anonymous, subfunction, private function).
216  if (fcn.is_defined ())
217  retval = octave::feval (fcn, args, nargout);
218  else
219  error ("%s: no longer valid function handle", nm.c_str ());
220  }
221 
222  return retval;
223 }
224 
227 {
228  static dim_vector dv (1, 1);
229  return dv;
230 }
231 
232 bool
234 {
235  bool retval = fcn.is_copy_of (h.fcn) && (has_overloads == h.has_overloads);
236  retval = retval && (overloads.size () == h.overloads.size ());
237 
238  if (retval && has_overloads)
239  {
240  for (int i = 0; i < btyp_num_types && retval; i++)
241  retval = builtin_overloads[i].is_copy_of (h.builtin_overloads[i]);
242 
243  str_ov_map::const_iterator iter = overloads.begin ();
244  str_ov_map::const_iterator hiter = h.overloads.begin ();
245  for (; iter != overloads.end () && retval; iter++, hiter++)
246  retval = (iter->first == hiter->first)
247  && (iter->second.is_copy_of (hiter->second));
248  }
249 
250  return retval;
251 }
252 
253 bool
255  const std::string& fpath)
256 {
257  if (octaveroot.length () != 0
258  && fpath.length () >= octaveroot.length ()
259  && fpath.substr (0, octaveroot.length ()) == octaveroot
260  && octave::config::octave_exec_home () != octaveroot)
261  {
262  // First check if just replacing matlabroot is enough
265  + fpath.substr (octaveroot.length ()));
267 
268  if (fs.exists ())
269  {
270  size_t xpos = str.find_last_of (octave::sys::file_ops::dir_sep_chars ());
271 
272  std::string dir_name = str.substr (0, xpos);
273 
274  octave_value ov_fcn
275  = octave::load_fcn_from_file (str, dir_name, "", "", nm);
276 
277  if (ov_fcn.is_undefined ())
278  error ("function handle points to non-existent function");
279 
280  fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
281  }
282  else
283  {
284  // Next just search for it anywhere in the system path
285  std::list<std::string> names;
286  names.push_back (nm + ".oct");
287  names.push_back (nm + ".mex");
288  names.push_back (nm + ".m");
289 
290  octave::load_path& lp =
291  octave::__get_load_path__ ("octave_fcn_handle::set_fcn");
292 
294 
295  str = octave::sys::env::make_absolute (p.find_first_of (names));
296 
297  size_t xpos = str.find_last_of (octave::sys::file_ops::dir_sep_chars ());
298 
299  std::string dir_name = str.substr (0, xpos);
300 
301  octave_value ov_fcn
302  = octave::load_fcn_from_file (str, dir_name, "", "", nm);
303 
304  if (ov_fcn.is_undefined ())
305  error ("function handle points to non-existent function");
306 
307  fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
308  }
309  }
310  else
311  {
312  if (fpath.length () > 0)
313  {
314  size_t xpos = fpath.find_last_of (octave::sys::file_ops::dir_sep_chars ());
315 
316  std::string dir_name = fpath.substr (0, xpos);
317 
318  octave_value ov_fcn
319  = octave::load_fcn_from_file (fpath, dir_name, "", "", nm);
320 
321  if (ov_fcn.is_undefined ())
322  error ("function handle points to non-existent function");
323 
324  fcn = octave_value (new octave_fcn_handle (ov_fcn, nm));
325  }
326  else
327  {
328  octave::symbol_table& symtab
329  = octave::__get_symbol_table__ ("octave_fcn_handle::set_fcn");
330 
331  fcn = symtab.find_function (nm);
332 
333  if (! fcn.is_function ())
334  error ("function handle points to non-existent function");
335  }
336  }
337 
338  return true;
339 }
340 
341 bool
343 {
344  if (nm == anonymous)
345  {
346  os << nm << "\n";
347 
348  print_raw (os, true);
349  os << "\n";
350 
351  if (fcn.is_undefined ())
352  return false;
353 
354  std::list<octave::symbol_record> vars;
355 
358  octave::symbol_scope f_scope = f->scope ();
359  if (f_scope)
360  {
361  vars = f_scope.all_variables ();
362  context = f_scope.current_context ();
363  }
364 
365  size_t varlen = vars.size ();
366 
367  if (varlen > 0)
368  {
369  os << "# length: " << varlen << "\n";
370 
371  for (const auto& symrec : vars)
372  {
373  if (! save_text_data (os, symrec.varval (context),
374  symrec.name (), false, 0))
375  return ! os.fail ();
376  }
377  }
378  }
379  else
380  {
382  std::string fnm = (f ? f->fcn_file_name () : "");
383 
384  os << "# octaveroot: " << octave::config::octave_exec_home () << "\n";
385  if (! fnm.empty ())
386  os << "# path: " << fnm << "\n";
387  os << nm << "\n";
388  }
389 
390  return true;
391 }
392 
393 bool
395 {
396  bool success = true;
397 
398  int parse_status;
399 
400  octave_value anon_fcn_handle =
401  octave::eval_string (fcn_text, true, parse_status);
402 
403  if (parse_status == 0)
404  {
405  octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
406 
407  if (fh)
408  {
409  fcn = fh->fcn;
410 
412 
413  if (uf)
414  {
415  octave::symbol_scope uf_scope = uf->scope ();
416 
417  if (uf_scope)
418  uf_scope.cache_name (nm);
419  }
420  }
421  else
422  success = false;
423  }
424  else
425  success = false;
426 
427  return success;
428 }
429 
430 bool
432 {
433  bool success = true;
434 
435  std::streampos pos = is.tellg ();
436  std::string octaveroot = extract_keyword (is, "octaveroot", true);
437  if (octaveroot.empty ())
438  {
439  is.seekg (pos);
440  is.clear ();
441  }
442  pos = is.tellg ();
443  std::string fpath = extract_keyword (is, "path", true);
444  if (fpath.empty ())
445  {
446  is.seekg (pos);
447  is.clear ();
448  }
449 
450  is >> nm;
451 
452  if (nm == anonymous)
453  {
455 
456  std::string buf;
457 
458  if (is)
459  {
460 
461  // Get a line of text whitespace characters included, leaving
462  // newline in the stream.
463  buf = read_until_newline (is, true);
464 
465  }
466 
467  pos = is.tellg ();
468 
470 
471  // Set up temporary scope to use for evaluating the text that
472  // defines the anonymous function.
473 
474  octave::symbol_table& symtab
475  = octave::__get_symbol_table__ ("octave_fcn_handle::load_ascii");
476 
477  octave::symbol_scope local_scope (buf);
478 
479  symtab.set_scope (local_scope);
480 
482  = octave::__get_call_stack__ ("octave_fcn_handle::load_ascii");
483 
484  cs.push (local_scope, 0);
486 
487  octave_idx_type len = 0;
488 
489  if (extract_keyword (is, "length", len, true) && len >= 0)
490  {
491  if (len > 0)
492  {
493  for (octave_idx_type i = 0; i < len; i++)
494  {
495  octave_value t2;
496  bool dummy;
497 
499  = read_text_data (is, "", dummy, t2, i);
500 
501  if (! is)
502  error ("load: failed to load anonymous function handle");
503 
504  local_scope.assign (name, t2, 0);
505  }
506  }
507  }
508  else
509  {
510  is.seekg (pos);
511  is.clear ();
512  }
513 
514  if (is && success)
515  success = parse_anon_fcn_handle (buf);
516  else
517  success = false;
518  }
519  else
520  success = set_fcn (octaveroot, fpath);
521 
522  return success;
523 }
524 
525 bool
527 {
528  if (nm == anonymous)
529  {
530  std::ostringstream nmbuf;
531 
532  if (fcn.is_undefined ())
533  return false;
534 
535  std::list<octave::symbol_record> vars;
536 
538  octave::symbol_scope f_scope = f->scope ();
540  if (f_scope)
541  {
542  vars = f_scope.all_variables ();
543  context = f_scope.current_context ();
544  }
545 
546  size_t varlen = vars.size ();
547 
548  if (varlen > 0)
549  nmbuf << nm << ' ' << varlen;
550  else
551  nmbuf << nm;
552 
553  std::string buf_str = nmbuf.str ();
554  int32_t tmp = buf_str.length ();
555  os.write (reinterpret_cast<char *> (&tmp), 4);
556  os.write (buf_str.c_str (), buf_str.length ());
557 
558  std::ostringstream buf;
559  print_raw (buf, true);
560  std::string stmp = buf.str ();
561  tmp = stmp.length ();
562  os.write (reinterpret_cast<char *> (&tmp), 4);
563  os.write (stmp.c_str (), stmp.length ());
564 
565  if (varlen > 0)
566  {
567  for (const auto& symrec : vars)
568  {
569  if (! save_binary_data (os, symrec.varval (context),
570  symrec.name (), "", 0, save_as_floats))
571  return ! os.fail ();
572  }
573  }
574  }
575  else
576  {
577  std::ostringstream nmbuf;
578 
580  std::string fnm = (f ? f->fcn_file_name () : "");
581 
582  nmbuf << nm << "\n" << octave::config::octave_exec_home () << "\n" << fnm;
583 
584  std::string buf_str = nmbuf.str ();
585  int32_t tmp = buf_str.length ();
586  os.write (reinterpret_cast<char *> (&tmp), 4);
587  os.write (buf_str.c_str (), buf_str.length ());
588  }
589 
590  return true;
591 }
592 
593 bool
596 {
597  bool success = true;
598 
599  int32_t tmp;
600  if (! is.read (reinterpret_cast<char *> (&tmp), 4))
601  return false;
602  if (swap)
603  swap_bytes<4> (&tmp);
604 
605  OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);
606  // is.get (ctmp1, tmp+1, 0); caused is.eof () to be true though
607  // effectively not reading over file end
608  is.read (ctmp1, tmp);
609  ctmp1[tmp] = 0;
610  nm = std::string (ctmp1);
611 
612  if (! is)
613  return false;
614 
615  size_t anl = anonymous.length ();
616 
617  if (nm.length () >= anl && nm.substr (0, anl) == anonymous)
618  {
619  octave_idx_type len = 0;
620 
621  if (nm.length () > anl)
622  {
623  std::istringstream nm_is (nm.substr (anl));
624  nm_is >> len;
625  nm = nm.substr (0, anl);
626  }
627 
628  if (! is.read (reinterpret_cast<char *> (&tmp), 4))
629  return false;
630  if (swap)
631  swap_bytes<4> (&tmp);
632 
633  OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
634  // is.get (ctmp2, tmp+1, 0); caused is.eof () to be true though
635  // effectively not reading over file end
636  is.read (ctmp2, tmp);
637  ctmp2[tmp] = 0;
638 
640 
641  // Set up temporary scope to use for evaluating the text that
642  // defines the anonymous function.
643 
644  octave::symbol_table& symtab
645  = octave::__get_symbol_table__ ("octave_fcn_handle::load_binary");
646 
647  octave::symbol_scope local_scope (ctmp2);
648 
649  symtab.set_scope (local_scope);
650 
652  = octave::__get_call_stack__ ("octave_fcn_handle::load_binary");
653 
654  cs.push (local_scope, 0);
656 
657  if (len > 0)
658  {
659  for (octave_idx_type i = 0; i < len; i++)
660  {
661  octave_value t2;
662  bool dummy;
663  std::string doc;
664 
665  std::string name =
666  read_binary_data (is, swap, fmt, "",
667  dummy, t2, doc);
668 
669  if (! is)
670  error ("load: failed to load anonymous function handle");
671 
672  local_scope.force_assign (name, t2);
673  }
674  }
675 
676  if (is && success)
677  success = parse_anon_fcn_handle (ctmp2);
678  else
679  success = false;
680  }
681  else
682  {
683  std::string octaveroot;
684  std::string fpath;
685 
686  if (nm.find_first_of ('\n') != std::string::npos)
687  {
688  size_t pos1 = nm.find_first_of ('\n');
689  size_t pos2 = nm.find_first_of ('\n', pos1 + 1);
690  octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1);
691  fpath = nm.substr (pos2 + 1);
692  nm = nm.substr (0, pos1);
693  }
694 
695  success = set_fcn (octaveroot, fpath);
696  }
697 
698  return success;
699 }
700 
701 bool
703  bool save_as_floats)
704 {
705 #if defined (HAVE_HDF5)
706 
707  bool retval = true;
708 
709  hid_t group_hid = -1;
710 #if defined (HAVE_HDF5_18)
711  group_hid = H5Gcreate (loc_id, name, octave_H5P_DEFAULT, octave_H5P_DEFAULT,
713 #else
714  group_hid = H5Gcreate (loc_id, name, 0);
715 #endif
716  if (group_hid < 0)
717  return false;
718 
719  hid_t space_hid, data_hid, type_hid;
720  space_hid = data_hid = type_hid = -1;
721 
722  // attach the type of the variable
723  type_hid = H5Tcopy (H5T_C_S1);
724  H5Tset_size (type_hid, nm.length () + 1);
725  if (type_hid < 0)
726  {
727  H5Gclose (group_hid);
728  return false;
729  }
730 
731  OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);
732  hdims[0] = 0;
733  hdims[1] = 0;
734  space_hid = H5Screate_simple (0 , hdims, nullptr);
735  if (space_hid < 0)
736  {
737  H5Tclose (type_hid);
738  H5Gclose (group_hid);
739  return false;
740  }
741 #if defined (HAVE_HDF5_18)
742  data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid,
745 #else
746  data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid,
748 #endif
749  if (data_hid < 0
750  || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
751  octave_H5P_DEFAULT, nm.c_str ()) < 0)
752  {
753  H5Sclose (space_hid);
754  H5Tclose (type_hid);
755  H5Gclose (group_hid);
756  return false;
757  }
758  H5Dclose (data_hid);
759 
760  if (nm == anonymous)
761  {
762  std::ostringstream buf;
763  print_raw (buf, true);
764  std::string stmp = buf.str ();
765 
766  // attach the type of the variable
767  H5Tset_size (type_hid, stmp.length () + 1);
768  if (type_hid < 0)
769  {
770  H5Sclose (space_hid);
771  H5Gclose (group_hid);
772  return false;
773  }
774 
775 #if defined (HAVE_HDF5_18)
776  data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid,
779 #else
780  data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid,
782 #endif
783  if (data_hid < 0
784  || H5Dwrite (data_hid, type_hid, octave_H5S_ALL, octave_H5S_ALL,
785  octave_H5P_DEFAULT, stmp.c_str ()) < 0)
786  {
787  H5Sclose (space_hid);
788  H5Tclose (type_hid);
789  H5Gclose (group_hid);
790  return false;
791  }
792 
793  H5Dclose (data_hid);
794 
795  std::list<octave::symbol_record> vars;
796 
798  octave::symbol_scope f_scope = f->scope ();
800  if (f_scope)
801  {
802  vars = f_scope.all_variables ();
803  context = f_scope.current_context ();
804  }
805 
806  size_t varlen = vars.size ();
807 
808  if (varlen > 0)
809  {
810  hid_t as_id = H5Screate (H5S_SCALAR);
811 
812  if (as_id >= 0)
813  {
814 #if defined (HAVE_HDF5_18)
815  hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
816  H5T_NATIVE_IDX, as_id,
818 
819 #else
820  hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
822 #endif
823 
824  if (a_id >= 0)
825  {
826  retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0);
827 
828  H5Aclose (a_id);
829  }
830  else
831  retval = false;
832 
833  H5Sclose (as_id);
834  }
835  else
836  retval = false;
837 #if defined (HAVE_HDF5_18)
838  data_hid = H5Gcreate (group_hid, "symbol table",
840 #else
841  data_hid = H5Gcreate (group_hid, "symbol table", 0);
842 #endif
843  if (data_hid < 0)
844  {
845  H5Sclose (space_hid);
846  H5Tclose (type_hid);
847  H5Gclose (group_hid);
848  return false;
849  }
850 
851  for (const auto& symrec : vars)
852  {
853  if (! add_hdf5_data (data_hid, symrec.varval (context),
854  symrec.name (), "", false, save_as_floats))
855  break;
856  }
857  H5Gclose (data_hid);
858  }
859  }
860  else
861  {
863 
865  std::string fpath = (f ? f->fcn_file_name () : "");
866 
867  H5Sclose (space_hid);
868  hdims[0] = 1;
869  hdims[1] = octaveroot.length ();
870  space_hid = H5Screate_simple (0 , hdims, nullptr);
871  if (space_hid < 0)
872  {
873  H5Tclose (type_hid);
874  H5Gclose (group_hid);
875  return false;
876  }
877 
878  H5Tclose (type_hid);
879  type_hid = H5Tcopy (H5T_C_S1);
880  H5Tset_size (type_hid, octaveroot.length () + 1);
881 #if defined (HAVE_HDF5_18)
882  hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
883  type_hid, space_hid, octave_H5P_DEFAULT, octave_H5P_DEFAULT);
884 #else
885  hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
886  type_hid, space_hid, octave_H5P_DEFAULT);
887 #endif
888 
889  if (a_id >= 0)
890  {
891  retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0);
892 
893  H5Aclose (a_id);
894  }
895  else
896  {
897  H5Sclose (space_hid);
898  H5Tclose (type_hid);
899  H5Gclose (group_hid);
900  return false;
901  }
902 
903  H5Sclose (space_hid);
904  hdims[0] = 1;
905  hdims[1] = fpath.length ();
906  space_hid = H5Screate_simple (0 , hdims, nullptr);
907  if (space_hid < 0)
908  {
909  H5Tclose (type_hid);
910  H5Gclose (group_hid);
911  return false;
912  }
913 
914  H5Tclose (type_hid);
915  type_hid = H5Tcopy (H5T_C_S1);
916  H5Tset_size (type_hid, fpath.length () + 1);
917 
918 #if defined (HAVE_HDF5_18)
919  a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid,
921 #else
922  a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, octave_H5P_DEFAULT);
923 #endif
924 
925  if (a_id >= 0)
926  {
927  retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0);
928 
929  H5Aclose (a_id);
930  }
931  else
932  retval = false;
933  }
934 
935  H5Sclose (space_hid);
936  H5Tclose (type_hid);
937  H5Gclose (group_hid);
938 
939  return retval;
940 
941 #else
942  octave_unused_parameter (loc_id);
943  octave_unused_parameter (name);
944  octave_unused_parameter (save_as_floats);
945 
946  warn_save ("hdf5");
947 
948  return false;
949 #endif
950 }
951 
952 bool
954 {
955 #if defined (HAVE_HDF5)
956 
957  bool success = true;
958 
959  hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
960  hsize_t rank;
961  int slen;
962 
963 #if defined (HAVE_HDF5_18)
964  group_hid = H5Gopen (loc_id, name, octave_H5P_DEFAULT);
965 #else
966  group_hid = H5Gopen (loc_id, name);
967 #endif
968  if (group_hid < 0)
969  return false;
970 
971 #if defined (HAVE_HDF5_18)
972  data_hid = H5Dopen (group_hid, "nm", octave_H5P_DEFAULT);
973 #else
974  data_hid = H5Dopen (group_hid, "nm");
975 #endif
976 
977  if (data_hid < 0)
978  {
979  H5Gclose (group_hid);
980  return false;
981  }
982 
983  type_hid = H5Dget_type (data_hid);
984  type_class_hid = H5Tget_class (type_hid);
985 
986  if (type_class_hid != H5T_STRING)
987  {
988  H5Tclose (type_hid);
989  H5Dclose (data_hid);
990  H5Gclose (group_hid);
991  return false;
992  }
993 
994  space_hid = H5Dget_space (data_hid);
995  rank = H5Sget_simple_extent_ndims (space_hid);
996 
997  if (rank != 0)
998  {
999  H5Sclose (space_hid);
1000  H5Tclose (type_hid);
1001  H5Dclose (data_hid);
1002  H5Gclose (group_hid);
1003  return false;
1004  }
1005 
1006  slen = H5Tget_size (type_hid);
1007  if (slen < 0)
1008  {
1009  H5Sclose (space_hid);
1010  H5Tclose (type_hid);
1011  H5Dclose (data_hid);
1012  H5Gclose (group_hid);
1013  return false;
1014  }
1015 
1016  OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);
1017 
1018  // create datatype for (null-terminated) string to read into:
1019  st_id = H5Tcopy (H5T_C_S1);
1020  H5Tset_size (st_id, slen);
1021 
1022  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,
1023  octave_H5P_DEFAULT, nm_tmp)
1024  < 0)
1025  {
1026  H5Tclose (st_id);
1027  H5Sclose (space_hid);
1028  H5Tclose (type_hid);
1029  H5Dclose (data_hid);
1030  H5Gclose (group_hid);
1031  return false;
1032  }
1033  H5Tclose (st_id);
1034  H5Dclose (data_hid);
1035  nm = nm_tmp;
1036 
1037  if (nm == anonymous)
1038  {
1039 #if defined (HAVE_HDF5_18)
1040  data_hid = H5Dopen (group_hid, "fcn", octave_H5P_DEFAULT);
1041 #else
1042  data_hid = H5Dopen (group_hid, "fcn");
1043 #endif
1044 
1045  if (data_hid < 0)
1046  {
1047  H5Sclose (space_hid);
1048  H5Tclose (type_hid);
1049  H5Gclose (group_hid);
1050  return false;
1051  }
1052 
1053  H5Tclose (type_hid);
1054  type_hid = H5Dget_type (data_hid);
1055  type_class_hid = H5Tget_class (type_hid);
1056 
1057  if (type_class_hid != H5T_STRING)
1058  {
1059  H5Sclose (space_hid);
1060  H5Tclose (type_hid);
1061  H5Dclose (data_hid);
1062  H5Gclose (group_hid);
1063  return false;
1064  }
1065 
1066  H5Sclose (space_hid);
1067  space_hid = H5Dget_space (data_hid);
1068  rank = H5Sget_simple_extent_ndims (space_hid);
1069 
1070  if (rank != 0)
1071  {
1072  H5Sclose (space_hid);
1073  H5Tclose (type_hid);
1074  H5Dclose (data_hid);
1075  H5Gclose (group_hid);
1076  return false;
1077  }
1078 
1079  slen = H5Tget_size (type_hid);
1080  if (slen < 0)
1081  {
1082  H5Sclose (space_hid);
1083  H5Tclose (type_hid);
1084  H5Dclose (data_hid);
1085  H5Gclose (group_hid);
1086  return false;
1087  }
1088 
1089  OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen);
1090 
1091  // create datatype for (null-terminated) string to read into:
1092  st_id = H5Tcopy (H5T_C_S1);
1093  H5Tset_size (st_id, slen);
1094 
1095  if (H5Dread (data_hid, st_id, octave_H5S_ALL, octave_H5S_ALL,
1096  octave_H5P_DEFAULT, fcn_tmp)
1097  < 0)
1098  {
1099  H5Tclose (st_id);
1100  H5Sclose (space_hid);
1101  H5Tclose (type_hid);
1102  H5Dclose (data_hid);
1103  H5Gclose (group_hid);
1104  return false;
1105  }
1106  H5Tclose (st_id);
1107  H5Dclose (data_hid);
1108 
1109  octave_idx_type len = 0;
1110 
1111  // we have to pull some shenanigans here to make sure
1112  // HDF5 doesn't print out all sorts of error messages if we
1113  // call H5Aopen for a non-existing attribute
1114 
1115  H5E_auto_t err_func;
1116  void *err_func_data;
1117 
1118  // turn off error reporting temporarily, but save the error
1119  // reporting function:
1120 #if defined (HAVE_HDF5_18)
1121  H5Eget_auto (octave_H5E_DEFAULT, &err_func, &err_func_data);
1122  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
1123 #else
1124  H5Eget_auto (&err_func, &err_func_data);
1125  H5Eset_auto (nullptr, nullptr);
1126 #endif
1127 
1128  hid_t attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE");
1129 
1130  if (attr_id >= 0)
1131  {
1132  if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0)
1133  success = false;
1134 
1135  H5Aclose (attr_id);
1136  }
1137 
1138  // restore error reporting:
1139 #if defined (HAVE_HDF5_18)
1140  H5Eset_auto (octave_H5E_DEFAULT, err_func, err_func_data);
1141 #else
1142  H5Eset_auto (err_func, err_func_data);
1143 #endif
1144 
1146 
1147  // Set up temporary scope to use for evaluating the text that
1148  // defines the anonymous function.
1149 
1150  octave::symbol_table& symtab
1151  = octave::__get_symbol_table__ ("octave_fcn_handle::load_hdf5");
1152 
1153  octave::symbol_scope local_scope (fcn_tmp);
1154 
1155  symtab.set_scope (local_scope);
1156 
1158  = octave::__get_call_stack__ ("octave_fcn_handle::load_hdf5");
1159 
1160  cs.push (local_scope, 0);
1162 
1163  if (len > 0 && success)
1164  {
1165  hsize_t num_obj = 0;
1166 #if defined (HAVE_HDF5_18)
1167  data_hid = H5Gopen (group_hid, "symbol table", octave_H5P_DEFAULT);
1168 #else
1169  data_hid = H5Gopen (group_hid, "symbol table");
1170 #endif
1171  H5Gget_num_objs (data_hid, &num_obj);
1172  H5Gclose (data_hid);
1173 
1174  if (num_obj != static_cast<hsize_t>(len))
1175  error ("load: failed to load anonymous function handle");
1176 
1177  hdf5_callback_data dsub;
1178  int current_item = 0;
1179  for (octave_idx_type i = 0; i < len; i++)
1180  {
1181  if (hdf5_h5g_iterate (group_hid, "symbol table", &current_item,
1182  &dsub) <= 0)
1183  error ("load: failed to load anonymous function handle");
1184 
1185  local_scope.force_assign (dsub.name, dsub.tc);
1186  }
1187  }
1188 
1189  if (success)
1190  success = parse_anon_fcn_handle (fcn_tmp);
1191 
1192  frame.run ();
1193  }
1194  else
1195  {
1196  std::string octaveroot;
1197  std::string fpath;
1198 
1199  // we have to pull some shenanigans here to make sure
1200  // HDF5 doesn't print out all sorts of error messages if we
1201  // call H5Aopen for a non-existing attribute
1202 
1203  H5E_auto_t err_func;
1204  void *err_func_data;
1205 
1206  // turn off error reporting temporarily, but save the error
1207  // reporting function:
1208 #if defined (HAVE_HDF5_18)
1209  H5Eget_auto (octave_H5E_DEFAULT, &err_func, &err_func_data);
1210  H5Eset_auto (octave_H5E_DEFAULT, nullptr, nullptr);
1211 #else
1212  H5Eget_auto (&err_func, &err_func_data);
1213  H5Eset_auto (nullptr, nullptr);
1214 #endif
1215 
1216  hid_t attr_id = H5Aopen_name (group_hid, "OCTAVEROOT");
1217  if (attr_id >= 0)
1218  {
1219  H5Tclose (type_hid);
1220  type_hid = H5Aget_type (attr_id);
1221  type_class_hid = H5Tget_class (type_hid);
1222 
1223  if (type_class_hid != H5T_STRING)
1224  success = false;
1225  else
1226  {
1227  slen = H5Tget_size (type_hid);
1228  st_id = H5Tcopy (H5T_C_S1);
1229  H5Tset_size (st_id, slen);
1230  OCTAVE_LOCAL_BUFFER (char, root_tmp, slen);
1231 
1232  if (H5Aread (attr_id, st_id, root_tmp) < 0)
1233  success = false;
1234  else
1235  octaveroot = root_tmp;
1236 
1237  H5Tclose (st_id);
1238  }
1239 
1240  H5Aclose (attr_id);
1241  }
1242 
1243  if (success)
1244  {
1245  attr_id = H5Aopen_name (group_hid, "FILE");
1246  if (attr_id >= 0)
1247  {
1248  H5Tclose (type_hid);
1249  type_hid = H5Aget_type (attr_id);
1250  type_class_hid = H5Tget_class (type_hid);
1251 
1252  if (type_class_hid != H5T_STRING)
1253  success = false;
1254  else
1255  {
1256  slen = H5Tget_size (type_hid);
1257  st_id = H5Tcopy (H5T_C_S1);
1258  H5Tset_size (st_id, slen);
1259  OCTAVE_LOCAL_BUFFER (char, path_tmp, slen);
1260 
1261  if (H5Aread (attr_id, st_id, path_tmp) < 0)
1262  success = false;
1263  else
1264  fpath = path_tmp;
1265 
1266  H5Tclose (st_id);
1267  }
1268 
1269  H5Aclose (attr_id);
1270  }
1271  }
1272 
1273  // restore error reporting:
1274 #if defined (HAVE_HDF5_18)
1275  H5Eset_auto (octave_H5E_DEFAULT, err_func, err_func_data);
1276 #else
1277  H5Eset_auto (err_func, err_func_data);
1278 #endif
1279 
1280  success = (success ? set_fcn (octaveroot, fpath) : success);
1281  }
1282 
1283  H5Tclose (type_hid);
1284  H5Sclose (space_hid);
1285  H5Gclose (group_hid);
1286 
1287  return success;
1288 
1289 #else
1290  octave_unused_parameter (loc_id);
1291  octave_unused_parameter (name);
1292 
1293  warn_load ("hdf5");
1294 
1295  return false;
1296 #endif
1297 }
1298 
1299 /*
1300 %!test <*33857>
1301 %! a = 2;
1302 %! f = @(x) a + x;
1303 %! g = @(x) 2 * x;
1304 %! hm = @version;
1305 %! hdld = @svd;
1306 %! hbi = @log2;
1307 %! f2 = f;
1308 %! g2 = g;
1309 %! hm2 = hm;
1310 %! hdld2 = hdld;
1311 %! hbi2 = hbi;
1312 %! modes = {"-text", "-binary"};
1313 %! if (isfield (__octave_config_info__, "HAVE_HDF5")
1314 %! && __octave_config_info__ ("HAVE_HDF5"))
1315 %! modes(end+1) = "-hdf5";
1316 %! endif
1317 %! for i = 1:numel (modes)
1318 %! mode = modes{i};
1319 %! nm = tempname ();
1320 %! unwind_protect
1321 %! f2 (1);
1322 %! save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
1323 %! clear f2 g2 hm2 hdld2 hbi2
1324 %! load (nm);
1325 %! assert (f (2), f2 (2));
1326 %! assert (g (2), g2 (2));
1327 %! assert (g (3), g2 (3));
1328 %! unlink (nm);
1329 %! save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
1330 %! unwind_protect_cleanup
1331 %! unlink (nm);
1332 %! end_unwind_protect
1333 %! endfor
1334 */
1335 
1336 /*
1337 %!function fcn_handle_save_recurse (n, mode, nm, f2, g2, hm2, hdld2, hbi2)
1338 %! if (n == 0)
1339 %! save (mode, nm, "f2", "g2", "hm2", "hdld2", "hbi2");
1340 %! else
1341 %! fcn_handle_save_recurse (n - 1, mode, nm, f2, g2, hm2, hdld2, hbi2);
1342 %! endif
1343 %!endfunction
1344 %!function [f2, g2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (n, nm)
1345 %! if (n == 0)
1346 %! load (nm);
1347 %! else
1348 %! [f2, g2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (n - 1, nm);
1349 %! endif
1350 %!endfunction
1351 
1352 %!test <*35876>
1353 %! a = 2;
1354 %! f = @(x) a + x;
1355 %! g = @(x) 2 * x;
1356 %! hm = @version;
1357 %! hdld = @svd;
1358 %! hbi = @log2;
1359 %! f2 = f;
1360 %! g2 = g;
1361 %! hm2 = hm;
1362 %! hdld2 = hdld;
1363 %! hbi2 = hbi;
1364 %! modes = {"-text", "-binary"};
1365 %! if (isfield (__octave_config_info__, "HAVE_HDF5")
1366 %! && __octave_config_info__ ("HAVE_HDF5"))
1367 %! modes(end+1) = "-hdf5";
1368 %! endif
1369 %! for i = 1:numel (modes)
1370 %! mode = modes{i};
1371 %! nm = tempname ();
1372 %! unwind_protect
1373 %! fcn_handle_save_recurse (2, mode, nm, f2, g2, hm2, hdld2, hbi2);
1374 %! clear f2 g2 hm2 hdld2 hbi2
1375 %! [f2, f2, hm2, hdld2, hbi2] = fcn_handle_load_recurse (2, nm);
1376 %! load (nm);
1377 %! assert (f (2), f2 (2));
1378 %! assert (g (2), g2 (2));
1379 %! assert (g (3), g2 (3));
1380 %! unlink (nm);
1381 %! fcn_handle_save_recurse (2, mode, nm, f2, g2, hm2, hdld2, hbi2);
1382 %! unwind_protect_cleanup
1383 %! unlink (nm);
1384 %! end_unwind_protect
1385 %! endfor
1386 */
1387 
1388 void
1389 octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax)
1390 {
1391  print_raw (os, pr_as_read_syntax);
1392  newline (os);
1393 }
1394 
1395 void
1396 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const
1397 {
1398  bool printed = false;
1399 
1400  if (nm == anonymous)
1401  {
1403 
1404  // FCN is const because this member function is, so we can't
1405  // use it to call user_function_value, so we make a copy first.
1406 
1407  octave_value ftmp = fcn;
1408 
1410 
1411  if (f)
1412  {
1413  octave::tree_parameter_list *p = f->parameter_list ();
1414 
1415  os << "@(";
1416 
1417  if (p)
1418  p->accept (tpc);
1419 
1420  os << ") ";
1421 
1422  octave::tree_statement_list *b = f->body ();
1423 
1424  assert (b->length () == 1);
1425 
1426  octave::tree_statement *s = b->front ();
1427 
1428  if (s)
1429  {
1430  assert (s->is_expression ());
1431 
1432  octave::tree_expression *e = s->expression ();
1433 
1434  if (e)
1435  tpc.print_fcn_handle_body (e);
1436  }
1437 
1438  printed = true;
1439  }
1440  }
1441 
1442  if (! printed)
1443  octave_print_internal (os, '@' + nm, pr_as_read_syntax,
1445 }
1446 
1448 make_fcn_handle (const std::string& nm, bool local_funcs)
1449 {
1451 
1452  // Bow to the god of compatibility.
1453 
1454  // FIXME: it seems ugly to put this here, but there is no single
1455  // function in the parser that converts from the operator name to
1456  // the corresponding function name. At least try to do it without N
1457  // string compares.
1458 
1459  std::string tnm = nm;
1460 
1461  size_t len = nm.length ();
1462 
1463  if (len == 3 && nm == ".**")
1464  tnm = "power";
1465  else if (len == 2)
1466  {
1467  if (nm[0] == '.')
1468  {
1469  switch (nm[1])
1470  {
1471  case '\'':
1472  tnm = "transpose";
1473  break;
1474 
1475  case '+':
1476  tnm = "plus";
1477  break;
1478 
1479  case '-':
1480  tnm = "minus";
1481  break;
1482 
1483  case '*':
1484  tnm = "times";
1485  break;
1486 
1487  case '/':
1488  tnm = "rdivide";
1489  break;
1490 
1491  case '^':
1492  tnm = "power";
1493  break;
1494 
1495  case '\\':
1496  tnm = "ldivide";
1497  break;
1498  }
1499  }
1500  else if (nm[1] == '=')
1501  {
1502  switch (nm[0])
1503  {
1504  case '<':
1505  tnm = "le";
1506  break;
1507 
1508  case '=':
1509  tnm = "eq";
1510  break;
1511 
1512  case '>':
1513  tnm = "ge";
1514  break;
1515 
1516  case '~':
1517  case '!':
1518  tnm = "ne";
1519  break;
1520  }
1521  }
1522  else if (nm == "**")
1523  tnm = "mpower";
1524  }
1525  else if (len == 1)
1526  {
1527  switch (nm[0])
1528  {
1529  case '~':
1530  case '!':
1531  tnm = "not";
1532  break;
1533 
1534  case '\'':
1535  tnm = "ctranspose";
1536  break;
1537 
1538  case '+':
1539  tnm = "plus";
1540  break;
1541 
1542  case '-':
1543  tnm = "minus";
1544  break;
1545 
1546  case '*':
1547  tnm = "mtimes";
1548  break;
1549 
1550  case '/':
1551  tnm = "mrdivide";
1552  break;
1553 
1554  case '^':
1555  tnm = "mpower";
1556  break;
1557 
1558  case '\\':
1559  tnm = "mldivide";
1560  break;
1561 
1562  case '<':
1563  tnm = "lt";
1564  break;
1565 
1566  case '>':
1567  tnm = "gt";
1568  break;
1569 
1570  case '&':
1571  tnm = "and";
1572  break;
1573 
1574  case '|':
1575  tnm = "or";
1576  break;
1577  }
1578  }
1579 
1580  octave::symbol_table& symtab = octave::__get_symbol_table__ ("make_fcn_handle");
1581 
1582  octave_value f = symtab.find_function (tnm, octave_value_list (),
1583  local_funcs);
1584 
1585  octave_function *fptr = f.function_value (true);
1586 
1587  // Here we are just looking to see if FCN is a method or constructor
1588  // for any class.
1589  if (local_funcs && fptr
1590  && (fptr->is_subfunction () || fptr->is_private_function ()
1591  || fptr->is_class_constructor ()
1592  || fptr->is_classdef_constructor ()))
1593  {
1594  // Locally visible function.
1595  retval = octave_value (new octave_fcn_handle (f, tnm));
1596  }
1597  else
1598  {
1599  octave::load_path& lp = octave::__get_load_path__ ("make_fcn_handle");
1600 
1601  // Globally visible (or no match yet). Query overloads.
1602  std::list<std::string> classes = lp.overloads (tnm);
1603  bool any_match = fptr != nullptr || classes.size () > 0;
1604  if (! any_match)
1605  {
1606  // No match found, try updating load_path and query classes again.
1607  lp.update ();
1608  classes = lp.overloads (tnm);
1609  any_match = classes.size () > 0;
1610  }
1611 
1612  if (! any_match)
1613  error ("@%s: no function and no method found", tnm.c_str ());
1614 
1615  octave_fcn_handle *fh = new octave_fcn_handle (f, tnm);
1616  retval = fh;
1617 
1618  for (auto& cls : classes)
1619  {
1620  std::string class_name = cls;
1621  octave_value fmeth = symtab.find_method (tnm, class_name);
1622 
1623  bool is_builtin = false;
1624  for (int i = 0; i < btyp_num_types; i++)
1625  {
1626  // FIXME: Too slow? Maybe binary lookup?
1627  if (class_name == btyp_class_name[i])
1628  {
1629  is_builtin = true;
1630  fh->set_overload (static_cast<builtin_type_t> (i), fmeth);
1631  }
1632  }
1633 
1634  if (! is_builtin)
1635  fh->set_overload (class_name, fmeth);
1636  }
1637  }
1638 
1639  return retval;
1640 }
1641 
1642 /*
1643 %!test
1644 %! x = {".**", "power";
1645 %! ".'", "transpose";
1646 %! ".+", "plus";
1647 %! ".-", "minus";
1648 %! ".*", "times";
1649 %! "./", "rdivide";
1650 %! ".^", "power";
1651 %! ".\\", "ldivide";
1652 %! "<=", "le";
1653 %! "==", "eq";
1654 %! ">=", "ge";
1655 %! "~=", "ne";
1656 %! "!=", "ne";
1657 %! "**", "mpower";
1658 %! "~", "not";
1659 %! "!", "not";
1660 %! "\'", "ctranspose";
1661 %! "+", "plus";
1662 %! "-", "minus";
1663 %! "*", "mtimes";
1664 %! "/", "mrdivide";
1665 %! "^", "mpower";
1666 %! "\\", "mldivide";
1667 %! "<", "lt";
1668 %! ">", "gt";
1669 %! "&", "and";
1670 %! "|", "or"};
1671 %! for i = 1:rows (x)
1672 %! assert (functions (str2func (x{i,1})).function, x{i,2});
1673 %! endfor
1674 */
1675 
1676 DEFUN (functions, args, ,
1677  doc: /* -*- texinfo -*-
1678 @deftypefn {} {@var{s} =} functions (@var{fcn_handle})
1679 Return a structure containing information about the function handle
1680 @var{fcn_handle}.
1681 
1682 The structure @var{s} always contains these three fields:
1683 
1684 @table @asis
1685 @item function
1686 The function name. For an anonymous function (no name) this will be the
1687 actual function definition.
1688 
1689 @item type
1690 Type of the function.
1691 
1692 @table @asis
1693 @item anonymous
1694 The function is anonymous.
1695 
1696 @item private
1697 The function is private.
1698 
1699 @item overloaded
1700 The function overloads an existing function.
1701 
1702 @item simple
1703 The function is a built-in or m-file function.
1704 
1705 @item subfunction
1706 The function is a subfunction within an m-file.
1707 @end table
1708 
1709 @item file
1710 The m-file that will be called to perform the function. This field is empty
1711 for anonymous and built-in functions.
1712 @end table
1713 
1714 In addition, some function types may return more information in additional
1715 fields.
1716 
1717 @strong{Warning:} @code{functions} is provided for debugging purposes only.
1718 Its behavior may change in the future and programs should not depend on any
1719 particular output format.
1720 
1721 @seealso{func2str, str2func}
1722 @end deftypefn */)
1723 {
1724  if (args.length () != 1)
1725  print_usage ();
1726 
1727  octave_fcn_handle *fh = args(0).fcn_handle_value ("functions: FCN_HANDLE argument must be a function handle object");
1728 
1729  octave_function *fcn = (fh ? fh->function_value () : nullptr);
1730 
1731  if (! fcn)
1732  error ("functions: FCN_HANDLE is not a valid function handle object");
1733 
1735 
1736  std::string fh_nm = fh->fcn_name ();
1737 
1738  if (fh_nm == octave_fcn_handle::anonymous)
1739  {
1740  std::ostringstream buf;
1741  fh->print_raw (buf);
1742  m.setfield ("function", buf.str ());
1743 
1744  m.setfield ("type", "anonymous");
1745  }
1746  else
1747  {
1748  m.setfield ("function", fh_nm);
1749 
1750  if (fcn->is_subfunction ())
1751  {
1752  m.setfield ("type", "subfunction");
1753  Cell parentage (dim_vector (1, 2));
1754  parentage.elem (0) = fh_nm;
1755  parentage.elem (1) = fcn->parent_fcn_name ();
1756  m.setfield ("parentage", octave_value (parentage));
1757  }
1758  else if (fcn->is_private_function ())
1759  m.setfield ("type", "private");
1760  else if (fh->is_overloaded ())
1761  m.setfield ("type", "overloaded");
1762  else
1763  m.setfield ("type", "simple");
1764  }
1765 
1767 
1768  if (fh_nm == octave_fcn_handle::anonymous)
1769  {
1770  m.setfield ("file", nm);
1771 
1772  std::list<octave::symbol_record> vars;
1773 
1775  octave::symbol_scope fu_scope = fu->scope ();
1777  if (fu_scope)
1778  {
1779  vars = fu_scope.all_variables ();
1780  context = fu_scope.current_context ();
1781  }
1782 
1783  size_t varlen = vars.size ();
1784 
1785  if (varlen > 0)
1786  {
1787  octave_scalar_map ws;
1788  for (const auto& symrec : vars)
1789  ws.assign (symrec.name (), symrec.varval (context));
1790 
1791  m.setfield ("workspace", ws);
1792  }
1793  }
1794  else if (fcn->is_user_function () || fcn->is_user_script ())
1795  {
1796  octave_function *fu = fh->function_value ();
1797  m.setfield ("file", fu->fcn_file_name ());
1798  }
1799  else
1800  m.setfield ("file", "");
1801 
1802  return ovl (m);
1803 }
1804 
1805 DEFUN (func2str, args, ,
1806  doc: /* -*- texinfo -*-
1807 @deftypefn {} {} func2str (@var{fcn_handle})
1808 Return a string containing the name of the function referenced by the
1809 function handle @var{fcn_handle}.
1810 @seealso{str2func, functions}
1811 @end deftypefn */)
1812 {
1813  if (args.length () != 1)
1814  print_usage ();
1815 
1816  octave_fcn_handle *fh = args(0).fcn_handle_value ("func2str: FCN_HANDLE argument must be a function handle object");
1817 
1818  if (! fh)
1819  error ("func2str: FCN_HANDLE must be a valid function handle");
1820 
1822 
1823  std::string fh_nm = fh->fcn_name ();
1824 
1825  if (fh_nm == octave_fcn_handle::anonymous)
1826  {
1827  std::ostringstream buf;
1828 
1829  fh->print_raw (buf);
1830 
1831  retval = buf.str ();
1832  }
1833  else
1834  retval = fh_nm;
1835 
1836  return retval;
1837 }
1838 
1839 DEFUN (str2func, args, ,
1840  doc: /* -*- texinfo -*-
1841 @deftypefn {} {} str2func (@var{fcn_name})
1842 @deftypefnx {} {} str2func (@var{fcn_name}, "global")
1843 Return a function handle constructed from the string @var{fcn_name}.
1844 
1845 If the optional @qcode{"global"} argument is passed, locally visible
1846 functions are ignored in the lookup.
1847 @seealso{func2str, inline, functions}
1848 @end deftypefn */)
1849 {
1850  int nargin = args.length ();
1851 
1852  if (nargin < 1 || nargin > 2)
1853  print_usage ();
1854 
1855  std::string nm = args(0).xstring_value ("str2func: FCN_NAME must be a string");
1856 
1858 
1859  if (nm[0] == '@')
1860  {
1861  int parse_status;
1862  octave_value anon_fcn_handle
1863  = octave::eval_string (nm, true, parse_status);
1864 
1865  if (parse_status == 0)
1866  retval = anon_fcn_handle;
1867  }
1868  else
1869  retval = make_fcn_handle (nm, nargin != 2);
1870 
1871  return retval;
1872 }
1873 
1874 /*
1875 %!test
1876 %! f = str2func ("<");
1877 %! assert (class (f), "function_handle");
1878 %! assert (func2str (f), "lt");
1879 %! assert (f (1, 2), true);
1880 %! assert (f (2, 1), false);
1881 
1882 %!test
1883 %! f = str2func ("@(x) sin (x)");
1884 %! assert (func2str (f), "@(x) sin (x)");
1885 %! assert (f (0:3), sin (0:3));
1886 
1887 %!error <FCN_NAME must be a string> str2func ({"sin"})
1888 */
1889 
1890 /*
1891 %!function y = __testrecursionfunc (f, x, n)
1892 %! if (nargin < 3)
1893 %! n = 0;
1894 %! endif
1895 %! if (n > 2)
1896 %! y = f (x);
1897 %! else
1898 %! n++;
1899 %! y = __testrecursionfunc (@(x) f (2*x), x, n);
1900 %! endif
1901 %!endfunction
1902 %!
1903 %!assert (__testrecursionfunc (@(x) x, 1), 8)
1904 */
1905 
1906 DEFUN (is_function_handle, args, ,
1907  doc: /* -*- texinfo -*-
1908 @deftypefn {} {} is_function_handle (@var{x})
1909 Return true if @var{x} is a function handle.
1910 @seealso{isa, typeinfo, class, functions}
1911 @end deftypefn */)
1912 {
1913  if (args.length () != 1)
1914  print_usage ();
1915 
1916  return ovl (args(0).is_function_handle ());
1917 }
1918 
1919 /*
1920 %!shared fh
1921 %! fh = @(x) x;
1922 
1923 %!assert (is_function_handle (fh))
1924 %!assert (! is_function_handle ({fh}))
1925 %!assert (! is_function_handle (1))
1926 
1927 %!error is_function_handle ()
1928 %!error is_function_handle (1, 2)
1929 */
1930 
1932  const octave_value& root,
1933  const octave_value_list& templ,
1934  const std::vector<int>& mask,
1935  int exp_nargin)
1936  : octave_fcn_handle (f), root_handle (root), arg_template (templ),
1937  arg_mask (mask), expected_nargin (exp_nargin)
1938 { }
1939 
1943 {
1944  octave_fcn_handle *retval = nullptr;
1945 
1946  octave_user_function *usr_fcn = f.user_function_value (false);
1947  octave::tree_parameter_list *param_list = (usr_fcn ? usr_fcn->parameter_list ()
1948  : nullptr);
1949 
1950  octave::tree_statement_list *cmd_list = nullptr;
1951  octave::tree_expression *body_expr = nullptr;
1952 
1953  if (usr_fcn)
1954  {
1955  cmd_list = usr_fcn->body ();
1956  if (cmd_list)
1957  {
1958  // Verify that body is a single expression (always true in theory).
1959  body_expr = (cmd_list->length () == 1
1960  ? cmd_list->front ()->expression () : nullptr);
1961  }
1962  }
1963 
1964  if (body_expr && body_expr->is_index_expression ()
1965  && ! (param_list && param_list->takes_varargs ()))
1966  {
1967  // It's an index expression.
1969  (body_expr);
1970  octave::tree_expression *head_expr = idx_expr->expression ();
1971  std::list<octave::tree_argument_list *> arg_lists = idx_expr->arg_lists ();
1972  std::string type_tags = idx_expr->type_tags ();
1973 
1974  if (type_tags.length () == 1 && type_tags[0] == '('
1975  && head_expr->is_identifier ())
1976  {
1977  assert (arg_lists.size () == 1);
1978 
1979  // It's a single index expression: a(x,y,....)
1980  octave::tree_identifier *head_id =
1981  dynamic_cast<octave::tree_identifier *> (head_expr);
1982  octave::tree_argument_list *arg_list = arg_lists.front ();
1983 
1984  // Build a map of input params to their position.
1985  std::map<std::string, int> arginmap;
1986  int npar = 0;
1987 
1988  if (param_list)
1989  {
1990  for (auto& param_p : *param_list)
1991  {
1992  octave::tree_decl_elt *elt = param_p;
1993  octave::tree_identifier *id = (elt ? elt->ident () : nullptr);
1994  if (id && ! id->is_black_hole ())
1995  arginmap[id->name ()] = npar;
1996  }
1997  }
1998 
1999  if (arg_list && arg_list->length () > 0)
2000  {
2001  octave::symbol_scope scope = tw->get_current_scope ();
2002 
2004  = scope.current_context ();
2005 
2006  bool bad = false;
2007  int nargs = arg_list->length ();
2009  std::vector<int> arg_mask (nargs);
2010 
2011  // Verify that each argument is either a named param, a constant,
2012  // or a defined identifier.
2013  int iarg = 0;
2014  for (octave::tree_argument_list::iterator it = arg_list->begin ();
2015  it != arg_list->end (); ++it, ++iarg)
2016  {
2017  octave::tree_expression *elt = *it;
2018  if (elt && elt->is_constant ())
2019  {
2020  arg_template(iarg) = tw->evaluate (elt);
2021  arg_mask[iarg] = -1;
2022  }
2023  else if (elt && elt->is_identifier ())
2024  {
2025  octave::tree_identifier *elt_id =
2026  dynamic_cast<octave::tree_identifier *> (elt);
2027  if (arginmap.find (elt_id->name ()) != arginmap.end ())
2028  {
2029  arg_mask[iarg] = arginmap[elt_id->name ()];
2030  }
2031  else if (elt_id->is_defined (context))
2032  {
2033  arg_template(iarg) = tw->evaluate (elt_id);
2034  arg_mask[iarg] = -1;
2035  }
2036  else
2037  {
2038  bad = true;
2039  break;
2040  }
2041  }
2042  else
2043  {
2044  bad = true;
2045  break;
2046  }
2047  }
2048 
2049  octave_value root_val;
2050 
2051  if (! bad)
2052  {
2053  // If the head is a value, use it as root.
2054  if (head_id->is_defined (context))
2055  root_val = tw->evaluate (head_id);
2056  else
2057  {
2058  // It's a name.
2059  std::string head_name = head_id->name ();
2060 
2061  if (head_name == "eval" || head_name == "feval")
2062  bad = true;
2063  else
2064  {
2065  // Simulate try/catch.
2068 
2069  try
2070  {
2071  root_val = make_fcn_handle (head_name);
2072  }
2073  catch (const octave::execution_exception&)
2074  {
2076 
2077  bad = true;
2078  }
2079  }
2080  }
2081  }
2082 
2083  if (! bad)
2084  {
2085  // Stash proper name tags.
2086  std::list<string_vector> arg_names = idx_expr->arg_names ();
2087  assert (arg_names.size () == 1);
2088  arg_template.stash_name_tags (arg_names.front ());
2089 
2090  retval = new octave_fcn_binder (f, root_val, arg_template,
2091  arg_mask, npar);
2092  }
2093  }
2094  }
2095  }
2096 
2097  if (! retval)
2099 
2100  return retval;
2101 }
2102 
2103 /*
2104 %!test
2105 %! f = @(t) eval ('2*t');
2106 %! assert (f (21), 42);
2107 */
2108 
2111 {
2113 
2114  if (args.length () == expected_nargin)
2115  {
2116  for (int i = 0; i < arg_template.length (); i++)
2117  {
2118  int j = arg_mask[i];
2119  if (j >= 0)
2120  arg_template(i) = args(j); // May force a copy...
2121  }
2122 
2123  // Make a shallow copy of arg_template, to ensure consistency throughout
2124  // the following call even if we happen to get back here.
2127  }
2128  else
2130 
2131  return retval;
2132 }
2133 
2134 /*
2135 %!function r = __f (g, i)
2136 %! r = g(i);
2137 %!endfunction
2138 %!test
2139 %! x = [1,2;3,4];
2140 %! assert (__f (@(i) x(:,i), 1), [1;3]);
2141 */
uint32_t id
Definition: graphics.cc:12193
octave_idx_type write(const octave_value &data, octave_idx_type block_size, oct_data_conv::data_type output_type, octave_idx_type skip, mach_info::float_format flt_fmt)
Definition: oct-stream.cc:6704
OCTINTERP_API octave_value_list feval(const std::string &name, const octave_value_list &args=octave_value_list(), int nargout=0)
std::string read_until_newline(std::istream &is, bool keep_newline)
octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:412
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-fcn-handle.h:82
virtual bool is_user_function(void) const
Definition: ov-base.h:473
Definition: Cell.h:37
static const std::string anonymous
Definition: ov-fcn-handle.h:55
std::list< std::string > overloads(const std::string &meth) const
Definition: load-path.cc:399
void assign(const std::string &name, const octave_value &value, bool force_add)
Definition: symscope.h:707
std::string system_path(void) const
Definition: load-path.h:194
static void recover_from_exception(void)
std::string type_name(void) const
octave_fcn_handle * fcn_handle_value(bool=false)
OCTINTERP_API void print_usage(void)
Definition: defun.cc:54
std::string dir_sep_chars(void)
Definition: file-ops.cc:242
octave_value tc
Definition: ls-hdf5.h:110
int current_print_indent_level(void) const
Definition: ov-base.h:849
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE * f
const octave_hdf5_id octave_H5S_ALL
bool set_fcn(const std::string &octaveroot, const std::string &fpath)
void newline(std::ostream &os) const
Definition: ov-base.cc:1328
static std::map< std::string, std::string > vars
Definition: mkoctfile.in.cc:52
std::string name
Definition: ls-hdf5.h:104
std::vector< int > arg_mask
const octave_hdf5_id octave_H5E_DEFAULT
size_t length(void) const
Definition: base-list.h:50
OCTINTERP_API 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=false)
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:53
void error(const char *fmt,...)
Definition: error.cc:578
octave::tree_statement_list * body(void)
Definition: ov-usr-fcn.h:388
std::string octave_exec_home(void)
Definition: defaults.cc:271
void setfield(const std::string &key, const octave_value &val)
Definition: oct-map.cc:191
#define DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA(t, n, c)
Definition: ov-base.h:180
std::list< tree_expression * >::iterator iterator
Definition: base-list.h:40
bool is_defined(void) const
Definition: ov.h:523
static llvm::LLVMContext & context
Definition: jit-typeinfo.cc:79
void skip_preceeding_newline(std::istream &is)
T & elem(octave_idx_type n)
Definition: Array.h:488
void print_fcn_handle_body(tree_expression *)
Definition: pt-pr-code.cc:1155
std::list< string_vector > arg_names(void)
Definition: pt-idx.h:88
bool load_ascii(std::istream &is)
dim_vector dims(void) const
s
Definition: file-io.cc:2729
builtin_type_t
Definition: ov-base.h:71
bool save_binary(std::ostream &os, bool &save_as_floats)
bool takes_varargs(void) const
Definition: pt-misc.h:76
i e
Definition: data.cc:2591
virtual std::string fcn_file_name(void) const
Definition: ov-fcn.h:74
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
octave_value_list call(int nargout, const octave_value_list &args)
void push(octave_function *fcn)
Definition: call-stack.cc:357
octave_function * fcn
Definition: ov-class.cc:1754
std::list< std::string > parent_classes(const std::string &dispatch_type)
Definition: symtab.h:639
virtual bool is_user_script(void) const
Definition: ov-base.h:471
void warn_load(const char *type) const
Definition: ov-base.cc:1097
bool is_overloaded(void) const
Definition: ov-fcn-handle.h:99
octave_value make_fcn_handle(const std::string &nm, bool local_funcs)
bool parse_anon_fcn_handle(const std::string &fcn_text)
octave_fcn_binder(const octave_value &f, const octave_value &root, const octave_value_list &templ, const std::vector< int > &mask, int exp_nargin)
bool swap
Definition: load-save.cc:738
octave::call_stack & cs
Definition: ov-class.cc:1752
octave::tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:384
octave::symbol_scope scope(void)
Definition: ov-usr-fcn.h:100
static std::string make_absolute(const std::string &s, const std::string &dot_path=get_current_directory())
Definition: oct-env.cc:129
bool is_subfunction(void) const
Definition: ov-usr-fcn.h:324
std::list< symbol_record > all_variables(bool defined_only=true, unsigned int exclude=symbol_record::hidden) const
Definition: symscope.h:808
double h
Definition: graphics.cc:11808
str_ov_map overloads
symbol_table & __get_symbol_table__(const std::string &who)
void cache_name(const std::string &name)
Definition: symscope.h:924
void octave_print_internal(std::ostream &os, const float_display_format &fmt, bool d, bool pr_as_read_syntax)
Definition: pr-output.cc:1780
nd deftypefn *std::string name
Definition: sysdep.cc:647
iterator end(void)
Definition: base-list.h:86
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
void swap_bytes< 4 >(void *ptr)
Definition: byte-swap.h:60
std::string fcn_name(void) const
tree_expression * expression(void)
Definition: pt-idx.h:82
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:997
octave_value root_handle
bool add_hdf5_data(octave_hdf5_id loc_id, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
Definition: ls-hdf5.cc:1053
std::string extract_keyword(std::istream &is, const char *keyword, const bool next_only)
Definition: ls-oct-text.cc:82
OCTINTERP_API octave_value_list eval_string(const std::string &, bool silent, int &parse_status, int nargout)
virtual std::string parent_fcn_name(void) const
Definition: ov-fcn.h:81
bool save_ascii(std::ostream &os)
symbol_record::context_id current_context(void) const
Definition: symscope.h:669
std::string get_dispatch_type(const octave_value_list &args, builtin_type_t &builtin_type)
Definition: fcn-info.cc:268
virtual bool is_subfunction(void) const
Definition: ov-fcn.h:96
virtual bool is_index_expression(void) const
Definition: pt-exp.h:71
std::string btyp_class_name[btyp_num_types]
Definition: ov-base.cc:87
std::list< tree_argument_list * > arg_lists(void)
Definition: pt-idx.h:84
std::string type_tags(void)
Definition: pt-idx.h:86
std::string str
Definition: hash.cc:118
bool save_as_floats
Definition: load-save.cc:1617
std::string read_binary_data(std::istream &is, bool swap, octave::mach_info::float_format fmt, const std::string &filename, bool &global, octave_value &tc, std::string &doc)
bool save_hdf5(octave_hdf5_id loc_id, const char *name, bool save_as_floats)
double tmp
Definition: data.cc:6252
octave_value_list arg_template
is false
Definition: cellfun.cc:400
octave_hdf5_err hdf5_h5g_iterate(octave_hdf5_id loc_id, const char *name, int *idx, void *operator_data)
Definition: ls-hdf5.cc:707
octave_value retval
Definition: data.cc:6246
#define panic_impossible()
Definition: error.h:40
octave_value builtin_overloads[btyp_num_types]
int64_t octave_hdf5_id
octave_user_function * user_function_value(bool silent=false) const
void warn_save(const char *type) const
Definition: ov-base.cc:1106
idx type
Definition: ov.cc:3114
octave_value find_method(const std::string &name, const std::string &dispatch_type)
Definition: symtab.h:200
bool is_function(void) const
Definition: ov.h:758
std::string name(void) const
Definition: oct-stream.cc:7216
virtual bool is_constant(void) const
Definition: pt-exp.h:63
void update(void) const
Definition: load-path.cc:363
load_path & __get_load_path__(const std::string &who)
std::string pname
Definition: graphics.cc:11810
friend octave_value make_fcn_handle(const std::string &, bool)
virtual bool is_identifier(void) const
Definition: pt-exp.h:69
friend class octave_value
Definition: ov-base.h:228
If this string is printed
Definition: utils.cc:888
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
octave::unwind_protect frame
Definition: graphics.cc:12190
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_fcn_handle * fcn_handle_value(bool silent=false) const
bool is_undefined(void) const
Definition: ov.h:526
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
FloatComplex(* fptr)(const FloatComplex &, float, int, octave_idx_type &)
Definition: lo-specfun.cc:1129
p
Definition: lu.cc:138
void assign(const std::string &k, const octave_value &val)
Definition: oct-map.h:227
void force_assign(const std::string &name, const octave_value &value)
Definition: symscope.h:721
call_stack & __get_call_stack__(const std::string &who)
octave_value fcn
bool is_copy_of(const octave_value &val) const
Definition: ov.h:1329
bool out_of_date_check(octave_value &function, const std::string &dispatch_type, bool check_relative)
Definition: symtab.cc:116
std::string read_text_data(std::istream &is, const std::string &filename, bool &global, octave_value &tc, octave_idx_type count)
Definition: ls-oct-text.cc:238
octave_idx_type length(void) const
Definition: ovl.h:96
elt_type & front(void)
Definition: base-list.h:97
static octave_fcn_handle * maybe_binder(const octave_value &f, octave::tree_evaluator *tw)
#define H5T_NATIVE_IDX
Definition: oct-hdf5.h:39
b
Definition: cellfun.cc:400
symbol_scope get_current_scope(void)
Definition: pt-eval.cc:688
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:41
bool save_text_data(std::ostream &os, const octave_value &val_arg, const std::string &name, bool mark_global, int precision)
Definition: ls-oct-text.cc:307
bool exists(void) const
Definition: file-stat.h:144
octave::sys::file_stat fs(filename)
void add_method(T *obj, void(T::*method)(void))
args.length() nargin
Definition: file-io.cc:589
std::string name(void) const
Definition: pt-id.h:72
octave_value evaluate(tree_expression *expr, int nargout=1)
Definition: pt-eval.h:294
for i
Definition: data.cc:5264
const octave_hdf5_id octave_H5P_DEFAULT
void set_scope(const symbol_scope &sid)
Definition: symtab.h:92
void set_overload(builtin_type_t btyp, const octave_value &ov_fcn)
tree_identifier * ident(void)
Definition: pt-decl.h:98
bool is_nested_function(void) const
Definition: ov-usr-fcn.h:352
write the output to stdout if nargout is
Definition: load-save.cc:1612
bool is_private_function(void) const
Definition: ov-fcn.h:135
string_vector names
Definition: ovl.h:160
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
defaults to zero A value of zero computes the digamma a value the trigamma and so on The digamma function is for polygamma functions(ar{k} higher than 0)
void print(std::ostream &os, bool pr_as_read_syntax=false)
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
dim_vector dv
Definition: sub2ind.cc:263
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, size_t skip=1)
octave::stream os
Definition: file-io.cc:627
bool is_defined(symbol_record::context_id context)
Definition: pt-id.h:74
octave_function * function_value(bool=false)
bool save_binary_data(std::ostream &os, const octave_value &tc, const std::string &name, const std::string &doc, bool mark_global, bool save_as_floats)
iterator begin(void)
Definition: base-list.h:83
bool is_equal_to(const octave_fcn_handle &) const
OCTINTERP_API void interpreter_try(octave::unwind_protect &)
virtual octave_value_list call(int nargout, const octave_value_list &args)
tree_expression * expression(void)
Definition: pt-stmt.h:92
void stash_name_tags(const string_vector &nm)
Definition: ovl.h:144
octave_user_function * user_function_value(bool=false)