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