00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef HAVE_CONFIG_H
00026 #include <config.h>
00027 #endif
00028
00029 #include <iostream>
00030 #include <sstream>
00031 #include <vector>
00032
00033 #include "file-ops.h"
00034 #include "oct-locbuf.h"
00035
00036 #include "defun.h"
00037 #include "error.h"
00038 #include "gripes.h"
00039 #include "input.h"
00040 #include "oct-map.h"
00041 #include "ov-base.h"
00042 #include "ov-fcn-handle.h"
00043 #include "ov-usr-fcn.h"
00044 #include "pr-output.h"
00045 #include "pt-pr-code.h"
00046 #include "pt-misc.h"
00047 #include "pt-stmt.h"
00048 #include "pt-cmd.h"
00049 #include "pt-exp.h"
00050 #include "pt-assign.h"
00051 #include "pt-arg-list.h"
00052 #include "variables.h"
00053 #include "parse.h"
00054 #include "unwind-prot.h"
00055 #include "defaults.h"
00056 #include "file-stat.h"
00057 #include "load-path.h"
00058 #include "oct-env.h"
00059
00060 #include "byte-swap.h"
00061 #include "ls-ascii-helper.h"
00062 #include "ls-hdf5.h"
00063 #include "ls-oct-ascii.h"
00064 #include "ls-oct-binary.h"
00065 #include "ls-utils.h"
00066
00067 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle);
00068
00069 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_handle,
00070 "function handle",
00071 "function_handle");
00072
00073 const std::string octave_fcn_handle::anonymous ("@<anonymous>");
00074
00075 octave_fcn_handle::octave_fcn_handle (const octave_value& f,
00076 const std::string& n)
00077 : fcn (f), nm (n), has_overloads (false)
00078 {
00079 octave_user_function *uf = fcn.user_function_value (true);
00080
00081 if (uf && nm != anonymous)
00082 symbol_table::cache_name (uf->scope (), nm);
00083 }
00084
00085 octave_value_list
00086 octave_fcn_handle::subsref (const std::string& type,
00087 const std::list<octave_value_list>& idx,
00088 int nargout)
00089 {
00090 return octave_fcn_handle::subsref (type, idx, nargout, 0);
00091 }
00092
00093 octave_value_list
00094 octave_fcn_handle::subsref (const std::string& type,
00095 const std::list<octave_value_list>& idx,
00096 int nargout, const std::list<octave_lvalue>* lvalue_list)
00097 {
00098 octave_value_list retval;
00099
00100 switch (type[0])
00101 {
00102 case '(':
00103 {
00104 int tmp_nargout = (type.length () > 1 && nargout == 0) ? 1 : nargout;
00105
00106 retval = do_multi_index_op (tmp_nargout, idx.front (),
00107 idx.size () == 1 ? lvalue_list : 0);
00108 }
00109 break;
00110
00111 case '{':
00112 case '.':
00113 {
00114 std::string tnm = type_name ();
00115 error ("%s cannot be indexed with %c", tnm.c_str (), type[0]);
00116 }
00117 break;
00118
00119 default:
00120 panic_impossible ();
00121 }
00122
00123
00124
00125
00126
00127 if (idx.size () > 1)
00128 retval = retval(0).next_subsref (nargout, type, idx);
00129
00130 return retval;
00131 }
00132
00133 octave_value_list
00134 octave_fcn_handle::do_multi_index_op (int nargout,
00135 const octave_value_list& args)
00136 {
00137 return do_multi_index_op (nargout, args, 0);
00138 }
00139
00140 octave_value_list
00141 octave_fcn_handle::do_multi_index_op (int nargout,
00142 const octave_value_list& args,
00143 const std::list<octave_lvalue>* lvalue_list)
00144 {
00145 octave_value_list retval;
00146
00147 out_of_date_check (fcn, std::string (), false);
00148
00149 if (has_overloads)
00150 {
00151
00152 octave_value ov_fcn;
00153
00154
00155 builtin_type_t btyp;
00156 std::string dispatch_type = get_dispatch_type (args, btyp);
00157
00158
00159 if (btyp != btyp_unknown)
00160 {
00161 out_of_date_check (builtin_overloads[btyp], dispatch_type, false);
00162 ov_fcn = builtin_overloads[btyp];
00163 }
00164 else
00165 {
00166 str_ov_map::iterator it = overloads.find (dispatch_type);
00167
00168 if (it == overloads.end ())
00169 {
00170
00171
00172 std::list<std::string> plist
00173 = symbol_table::parent_classes (dispatch_type);
00174
00175 std::list<std::string>::const_iterator pit = plist.begin ();
00176
00177 while (pit != plist.end ())
00178 {
00179 std::string pname = *pit;
00180
00181 std::string fnm = fcn_name ();
00182
00183 octave_value ftmp = symbol_table::find_method (fnm, pname);
00184
00185 if (ftmp.is_defined ())
00186 {
00187 set_overload (pname, ftmp);
00188
00189 out_of_date_check (ftmp, pname, false);
00190 ov_fcn = ftmp;
00191
00192 break;
00193 }
00194
00195 pit++;
00196 }
00197 }
00198 else
00199 {
00200 out_of_date_check (it->second, dispatch_type, false);
00201 ov_fcn = it->second;
00202 }
00203 }
00204
00205 if (ov_fcn.is_defined ())
00206 retval = ov_fcn.do_multi_index_op (nargout, args, lvalue_list);
00207 else if (fcn.is_defined ())
00208 retval = fcn.do_multi_index_op (nargout, args, lvalue_list);
00209 else
00210 error ("%s: no method for class %s", nm.c_str (), dispatch_type.c_str ());
00211 }
00212 else
00213 {
00214
00215 if (fcn.is_defined ())
00216 retval = fcn.do_multi_index_op (nargout, args, lvalue_list);
00217 else
00218 error ("%s: no longer valid function handle", nm.c_str ());
00219 }
00220
00221 return retval;
00222 }
00223
00224 bool
00225 octave_fcn_handle::is_equal_to (const octave_fcn_handle& h) const
00226 {
00227 bool retval = fcn.is_copy_of (h.fcn) && (has_overloads == h.has_overloads);
00228 retval = retval && (overloads.size () == h.overloads.size ());
00229
00230 if (retval && has_overloads)
00231 {
00232 for (int i = 0; i < btyp_num_types && retval; i++)
00233 retval = builtin_overloads[i].is_copy_of (h.builtin_overloads[i]);
00234
00235 str_ov_map::const_iterator iter = overloads.begin (), hiter = h.overloads.begin ();
00236 for (; iter != overloads.end () && retval; iter++, hiter++)
00237 retval = (iter->first == hiter->first) && (iter->second.is_copy_of (hiter->second));
00238 }
00239
00240 return retval;
00241 }
00242
00243 bool
00244 octave_fcn_handle::set_fcn (const std::string &octaveroot,
00245 const std::string& fpath)
00246 {
00247 bool success = true;
00248
00249 if (octaveroot.length () != 0
00250 && fpath.length () >= octaveroot.length ()
00251 && fpath.substr (0, octaveroot.length ()) == octaveroot
00252 && OCTAVE_EXEC_PREFIX != octaveroot)
00253 {
00254
00255 std::string str = OCTAVE_EXEC_PREFIX +
00256 fpath.substr (octaveroot.length ());
00257 file_stat fs (str);
00258
00259 if (fs.exists ())
00260 {
00261 size_t xpos = str.find_last_of (file_ops::dir_sep_chars ());
00262
00263 std::string dir_name = str.substr (0, xpos);
00264
00265 octave_function *xfcn
00266 = load_fcn_from_file (str, dir_name, "", nm);
00267
00268 if (xfcn)
00269 {
00270 octave_value tmp (xfcn);
00271
00272 fcn = octave_value (new octave_fcn_handle (tmp, nm));
00273 }
00274 else
00275 {
00276 error ("function handle points to non-existent function");
00277 success = false;
00278 }
00279 }
00280 else
00281 {
00282
00283 string_vector names(3);
00284 names(0) = nm + ".oct";
00285 names(1) = nm + ".mex";
00286 names(2) = nm + ".m";
00287
00288 dir_path p (load_path::system_path ());
00289
00290 str = octave_env::make_absolute (p.find_first_of (names));
00291
00292 size_t xpos = str.find_last_of (file_ops::dir_sep_chars ());
00293
00294 std::string dir_name = str.substr (0, xpos);
00295
00296 octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm);
00297
00298 if (xfcn)
00299 {
00300 octave_value tmp (xfcn);
00301
00302 fcn = octave_value (new octave_fcn_handle (tmp, nm));
00303 }
00304 else
00305 {
00306 error ("function handle points to non-existent function");
00307 success = false;
00308 }
00309 }
00310 }
00311 else
00312 {
00313 if (fpath.length () > 0)
00314 {
00315 size_t xpos = fpath.find_last_of (file_ops::dir_sep_chars ());
00316
00317 std::string dir_name = fpath.substr (0, xpos);
00318
00319 octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm);
00320
00321 if (xfcn)
00322 {
00323 octave_value tmp (xfcn);
00324
00325 fcn = octave_value (new octave_fcn_handle (tmp, nm));
00326 }
00327 else
00328 {
00329 error ("function handle points to non-existent function");
00330 success = false;
00331 }
00332 }
00333 else
00334 {
00335 fcn = symbol_table::find_function (nm);
00336
00337 if (! fcn.is_function ())
00338 {
00339 error ("function handle points to non-existent function");
00340 success = false;
00341 }
00342 }
00343 }
00344
00345 return success;
00346 }
00347
00348 bool
00349 octave_fcn_handle::save_ascii (std::ostream& os)
00350 {
00351 if (nm == anonymous)
00352 {
00353 os << nm << "\n";
00354
00355 print_raw (os, true);
00356 os << "\n";
00357
00358 if (fcn.is_undefined ())
00359 return false;
00360
00361 octave_user_function *f = fcn.user_function_value ();
00362
00363 std::list<symbol_table::symbol_record> vars
00364 = symbol_table::all_variables (f->scope (), 0);
00365
00366 size_t varlen = vars.size ();
00367
00368 if (varlen > 0)
00369 {
00370 os << "# length: " << varlen << "\n";
00371
00372 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
00373 p != vars.end (); p++)
00374 {
00375 if (! save_ascii_data (os, p->varval (), p->name (), false, 0))
00376 return os;
00377 }
00378 }
00379 }
00380 else
00381 {
00382 octave_function *f = function_value ();
00383 std::string fnm = f ? f->fcn_file_name () : std::string ();
00384
00385 os << "# octaveroot: " << OCTAVE_EXEC_PREFIX << "\n";
00386 if (! fnm.empty ())
00387 os << "# path: " << fnm << "\n";
00388 os << nm << "\n";
00389 }
00390
00391 return true;
00392 }
00393
00394 bool
00395 octave_fcn_handle::load_ascii (std::istream& is)
00396 {
00397 bool success = true;
00398
00399 std::streampos pos = is.tellg ();
00400 std::string octaveroot = extract_keyword (is, "octaveroot", true);
00401 if (octaveroot.length() == 0)
00402 {
00403 is.seekg (pos);
00404 is.clear ();
00405 }
00406 pos = is.tellg ();
00407 std::string fpath = extract_keyword (is, "path", true);
00408 if (fpath.length() == 0)
00409 {
00410 is.seekg (pos);
00411 is.clear ();
00412 }
00413
00414 is >> nm;
00415
00416 if (nm == anonymous)
00417 {
00418 skip_preceeding_newline (is);
00419
00420 std::string buf;
00421
00422 if (is)
00423 {
00424
00425
00426
00427 buf = read_until_newline (is, true);
00428
00429 }
00430
00431 pos = is.tellg ();
00432
00433 unwind_protect_safe frame;
00434
00435
00436
00437
00438 symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
00439 frame.add_fcn (symbol_table::erase_scope, local_scope);
00440
00441 symbol_table::set_scope (local_scope);
00442
00443 octave_call_stack::push (local_scope, 0);
00444 frame.add_fcn (octave_call_stack::pop);
00445
00446 octave_idx_type len = 0;
00447
00448 if (extract_keyword (is, "length", len, true) && len >= 0)
00449 {
00450 if (len > 0)
00451 {
00452 for (octave_idx_type i = 0; i < len; i++)
00453 {
00454 octave_value t2;
00455 bool dummy;
00456
00457 std::string name
00458 = read_ascii_data (is, std::string (), dummy, t2, i);
00459
00460 if (!is)
00461 {
00462 error ("load: failed to load anonymous function handle");
00463 break;
00464 }
00465
00466 symbol_table::varref (name, local_scope, 0) = t2;
00467 }
00468 }
00469 }
00470 else
00471 {
00472 is.seekg (pos);
00473 is.clear ();
00474 }
00475
00476 if (is && success)
00477 {
00478 int parse_status;
00479 octave_value anon_fcn_handle =
00480 eval_string (buf, true, parse_status);
00481
00482 if (parse_status == 0)
00483 {
00484 octave_fcn_handle *fh =
00485 anon_fcn_handle.fcn_handle_value ();
00486
00487 if (fh)
00488 {
00489 fcn = fh->fcn;
00490
00491 octave_user_function *uf = fcn.user_function_value (true);
00492
00493 if (uf)
00494 symbol_table::cache_name (uf->scope (), nm);
00495 }
00496 else
00497 success = false;
00498 }
00499 else
00500 success = false;
00501 }
00502 else
00503 success = false;
00504 }
00505 else
00506 success = set_fcn (octaveroot, fpath);
00507
00508 return success;
00509 }
00510
00511 bool
00512 octave_fcn_handle::save_binary (std::ostream& os, bool& save_as_floats)
00513 {
00514 if (nm == anonymous)
00515 {
00516 std::ostringstream nmbuf;
00517
00518 if (fcn.is_undefined ())
00519 return false;
00520
00521 octave_user_function *f = fcn.user_function_value ();
00522
00523 std::list<symbol_table::symbol_record> vars
00524 = symbol_table::all_variables (f->scope (), 0);
00525
00526 size_t varlen = vars.size ();
00527
00528 if (varlen > 0)
00529 nmbuf << nm << " " << varlen;
00530 else
00531 nmbuf << nm;
00532
00533 std::string buf_str = nmbuf.str();
00534 int32_t tmp = buf_str.length ();
00535 os.write (reinterpret_cast<char *> (&tmp), 4);
00536 os.write (buf_str.c_str (), buf_str.length ());
00537
00538 std::ostringstream buf;
00539 print_raw (buf, true);
00540 std::string stmp = buf.str ();
00541 tmp = stmp.length ();
00542 os.write (reinterpret_cast<char *> (&tmp), 4);
00543 os.write (stmp.c_str (), stmp.length ());
00544
00545 if (varlen > 0)
00546 {
00547 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
00548 p != vars.end (); p++)
00549 {
00550 if (! save_binary_data (os, p->varval (), p->name (),
00551 "", 0, save_as_floats))
00552 return os;
00553 }
00554 }
00555 }
00556 else
00557 {
00558 std::ostringstream nmbuf;
00559
00560 octave_function *f = function_value ();
00561 std::string fnm = f ? f->fcn_file_name () : std::string ();
00562
00563 nmbuf << nm << "\n" << OCTAVE_EXEC_PREFIX << "\n" << fnm;
00564
00565 std::string buf_str = nmbuf.str ();
00566 int32_t tmp = buf_str.length ();
00567 os.write (reinterpret_cast<char *> (&tmp), 4);
00568 os.write (buf_str.c_str (), buf_str.length ());
00569 }
00570
00571 return true;
00572 }
00573
00574 bool
00575 octave_fcn_handle::load_binary (std::istream& is, bool swap,
00576 oct_mach_info::float_format fmt)
00577 {
00578 bool success = true;
00579
00580 int32_t tmp;
00581 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00582 return false;
00583 if (swap)
00584 swap_bytes<4> (&tmp);
00585
00586 OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1);
00587
00588
00589 is.read (ctmp1, tmp);
00590 ctmp1[tmp] = 0;
00591 nm = std::string (ctmp1);
00592
00593 if (! is)
00594 return false;
00595
00596 size_t anl = anonymous.length ();
00597
00598 if (nm.length() >= anl && nm.substr (0, anl) == anonymous)
00599 {
00600 octave_idx_type len = 0;
00601
00602 if (nm.length() > anl)
00603 {
00604 std::istringstream nm_is (nm.substr (anl));
00605 nm_is >> len;
00606 nm = nm.substr (0, anl);
00607 }
00608
00609 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
00610 return false;
00611 if (swap)
00612 swap_bytes<4> (&tmp);
00613
00614 OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
00615
00616
00617 is.read (ctmp2, tmp);
00618 ctmp2[tmp] = 0;
00619
00620 unwind_protect_safe frame;
00621
00622
00623
00624
00625 symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
00626 frame.add_fcn (symbol_table::erase_scope, local_scope);
00627
00628 symbol_table::set_scope (local_scope);
00629
00630 octave_call_stack::push (local_scope, 0);
00631 frame.add_fcn (octave_call_stack::pop);
00632
00633 if (len > 0)
00634 {
00635 for (octave_idx_type i = 0; i < len; i++)
00636 {
00637 octave_value t2;
00638 bool dummy;
00639 std::string doc;
00640
00641 std::string name =
00642 read_binary_data (is, swap, fmt, std::string (),
00643 dummy, t2, doc);
00644
00645 if (!is)
00646 {
00647 error ("load: failed to load anonymous function handle");
00648 break;
00649 }
00650
00651 symbol_table::varref (name, local_scope) = t2;
00652 }
00653 }
00654
00655 if (is && success)
00656 {
00657 int parse_status;
00658 octave_value anon_fcn_handle =
00659 eval_string (ctmp2, true, parse_status);
00660
00661 if (parse_status == 0)
00662 {
00663 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
00664
00665 if (fh)
00666 {
00667 fcn = fh->fcn;
00668
00669 octave_user_function *uf = fcn.user_function_value (true);
00670
00671 if (uf)
00672 symbol_table::cache_name (uf->scope (), nm);
00673 }
00674 else
00675 success = false;
00676 }
00677 else
00678 success = false;
00679 }
00680 }
00681 else
00682 {
00683 std::string octaveroot;
00684 std::string fpath;
00685
00686 if (nm.find_first_of ("\n") != std::string::npos)
00687 {
00688 size_t pos1 = nm.find_first_of ("\n");
00689 size_t pos2 = nm.find_first_of ("\n", pos1 + 1);
00690 octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1);
00691 fpath = nm.substr (pos2 + 1);
00692 nm = nm.substr (0, pos1);
00693 }
00694
00695 success = set_fcn (octaveroot, fpath);
00696 }
00697
00698 return success;
00699 }
00700
00701 #if defined (HAVE_HDF5)
00702 bool
00703 octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name,
00704 bool save_as_floats)
00705 {
00706 bool retval = true;
00707
00708 hid_t group_hid = -1;
00709 #if HAVE_HDF5_18
00710 group_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00711 #else
00712 group_hid = H5Gcreate (loc_id, name, 0);
00713 #endif
00714 if (group_hid < 0)
00715 return false;
00716
00717 hid_t space_hid = -1, data_hid = -1, type_hid = -1;;
00718
00719
00720 type_hid = H5Tcopy (H5T_C_S1);
00721 H5Tset_size (type_hid, nm.length () + 1);
00722 if (type_hid < 0)
00723 {
00724 H5Gclose (group_hid);
00725 return false;
00726 }
00727
00728 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2);
00729 hdims[0] = 0;
00730 hdims[1] = 0;
00731 space_hid = H5Screate_simple (0 , hdims, 0);
00732 if (space_hid < 0)
00733 {
00734 H5Tclose (type_hid);
00735 H5Gclose (group_hid);
00736 return false;
00737 }
00738 #if HAVE_HDF5_18
00739 data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid,
00740 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00741 #else
00742 data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, H5P_DEFAULT);
00743 #endif
00744 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
00745 H5P_DEFAULT, nm.c_str ()) < 0)
00746 {
00747 H5Sclose (space_hid);
00748 H5Tclose (type_hid);
00749 H5Gclose (group_hid);
00750 return false;
00751 }
00752 H5Dclose (data_hid);
00753
00754 if (nm == anonymous)
00755 {
00756 std::ostringstream buf;
00757 print_raw (buf, true);
00758 std::string stmp = buf.str ();
00759
00760
00761 H5Tset_size (type_hid, stmp.length () + 1);
00762 if (type_hid < 0)
00763 {
00764 H5Sclose (space_hid);
00765 H5Gclose (group_hid);
00766 return false;
00767 }
00768
00769 #if HAVE_HDF5_18
00770 data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid,
00771 H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00772 #else
00773 data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid,
00774 H5P_DEFAULT);
00775 #endif
00776 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL,
00777 H5P_DEFAULT, stmp.c_str ()) < 0)
00778 {
00779 H5Sclose (space_hid);
00780 H5Tclose (type_hid);
00781 H5Gclose (group_hid);
00782 return false;
00783 }
00784
00785 H5Dclose (data_hid);
00786
00787 octave_user_function *f = fcn.user_function_value ();
00788
00789 std::list<symbol_table::symbol_record> vars
00790 = symbol_table::all_variables (f->scope (), 0);
00791
00792 size_t varlen = vars.size ();
00793
00794 if (varlen > 0)
00795 {
00796 hid_t as_id = H5Screate (H5S_SCALAR);
00797
00798 if (as_id >= 0)
00799 {
00800 #if HAVE_HDF5_18
00801 hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
00802 H5T_NATIVE_IDX, as_id,
00803 H5P_DEFAULT, H5P_DEFAULT);
00804
00805 #else
00806 hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
00807 H5T_NATIVE_IDX, as_id, H5P_DEFAULT);
00808 #endif
00809
00810 if (a_id >= 0)
00811 {
00812 retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0);
00813
00814 H5Aclose (a_id);
00815 }
00816 else
00817 retval = false;
00818
00819 H5Sclose (as_id);
00820 }
00821 else
00822 retval = false;
00823 #if HAVE_HDF5_18
00824 data_hid = H5Gcreate (group_hid, "symbol table", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
00825 #else
00826 data_hid = H5Gcreate (group_hid, "symbol table", 0);
00827 #endif
00828 if (data_hid < 0)
00829 {
00830 H5Sclose (space_hid);
00831 H5Tclose (type_hid);
00832 H5Gclose (group_hid);
00833 return false;
00834 }
00835
00836 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
00837 p != vars.end (); p++)
00838 {
00839 if (! add_hdf5_data (data_hid, p->varval (), p->name (),
00840 "", false, save_as_floats))
00841 break;
00842 }
00843 H5Gclose (data_hid);
00844 }
00845 }
00846 else
00847 {
00848 std::string octaveroot = OCTAVE_EXEC_PREFIX;
00849
00850 octave_function *f = function_value ();
00851 std::string fpath = f ? f->fcn_file_name () : std::string ();
00852
00853 H5Sclose (space_hid);
00854 hdims[0] = 1;
00855 hdims[1] = octaveroot.length ();
00856 space_hid = H5Screate_simple (0 , hdims, 0);
00857 if (space_hid < 0)
00858 {
00859 H5Tclose (type_hid);
00860 H5Gclose (group_hid);
00861 return false;
00862 }
00863
00864 H5Tclose (type_hid);
00865 type_hid = H5Tcopy (H5T_C_S1);
00866 H5Tset_size (type_hid, octaveroot.length () + 1);
00867 #if HAVE_HDF5_18
00868 hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
00869 type_hid, space_hid, H5P_DEFAULT, H5P_DEFAULT);
00870 #else
00871 hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
00872 type_hid, space_hid, H5P_DEFAULT);
00873 #endif
00874
00875 if (a_id >= 0)
00876 {
00877 retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0);
00878
00879 H5Aclose (a_id);
00880 }
00881 else
00882 {
00883 H5Sclose (space_hid);
00884 H5Tclose (type_hid);
00885 H5Gclose (group_hid);
00886 return false;
00887 }
00888
00889 H5Sclose (space_hid);
00890 hdims[0] = 1;
00891 hdims[1] = fpath.length ();
00892 space_hid = H5Screate_simple (0 , hdims, 0);
00893 if (space_hid < 0)
00894 {
00895 H5Tclose (type_hid);
00896 H5Gclose (group_hid);
00897 return false;
00898 }
00899
00900 H5Tclose (type_hid);
00901 type_hid = H5Tcopy (H5T_C_S1);
00902 H5Tset_size (type_hid, fpath.length () + 1);
00903
00904 #if HAVE_HDF5_18
00905 a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid,
00906 H5P_DEFAULT, H5P_DEFAULT);
00907 #else
00908 a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, H5P_DEFAULT);
00909 #endif
00910
00911 if (a_id >= 0)
00912 {
00913 retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0);
00914
00915 H5Aclose (a_id);
00916 }
00917 else
00918 retval = false;
00919 }
00920
00921 H5Sclose (space_hid);
00922 H5Tclose (type_hid);
00923 H5Gclose (group_hid);
00924
00925 return retval;
00926 }
00927
00928 bool
00929 octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name)
00930 {
00931 bool success = true;
00932
00933 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
00934 hsize_t rank;
00935 int slen;
00936
00937 #if HAVE_HDF5_18
00938 group_hid = H5Gopen (loc_id, name, H5P_DEFAULT);
00939 #else
00940 group_hid = H5Gopen (loc_id, name);
00941 #endif
00942 if (group_hid < 0)
00943 return false;
00944
00945 #if HAVE_HDF5_18
00946 data_hid = H5Dopen (group_hid, "nm", H5P_DEFAULT);
00947 #else
00948 data_hid = H5Dopen (group_hid, "nm");
00949 #endif
00950
00951 if (data_hid < 0)
00952 {
00953 H5Gclose (group_hid);
00954 return false;
00955 }
00956
00957 type_hid = H5Dget_type (data_hid);
00958 type_class_hid = H5Tget_class (type_hid);
00959
00960 if (type_class_hid != H5T_STRING)
00961 {
00962 H5Tclose (type_hid);
00963 H5Dclose (data_hid);
00964 H5Gclose (group_hid);
00965 return false;
00966 }
00967
00968 space_hid = H5Dget_space (data_hid);
00969 rank = H5Sget_simple_extent_ndims (space_hid);
00970
00971 if (rank != 0)
00972 {
00973 H5Sclose (space_hid);
00974 H5Tclose (type_hid);
00975 H5Dclose (data_hid);
00976 H5Gclose (group_hid);
00977 return false;
00978 }
00979
00980 slen = H5Tget_size (type_hid);
00981 if (slen < 0)
00982 {
00983 H5Sclose (space_hid);
00984 H5Tclose (type_hid);
00985 H5Dclose (data_hid);
00986 H5Gclose (group_hid);
00987 return false;
00988 }
00989
00990 OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen);
00991
00992
00993 st_id = H5Tcopy (H5T_C_S1);
00994 H5Tset_size (st_id, slen);
00995
00996 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, nm_tmp) < 0)
00997 {
00998 H5Tclose (st_id);
00999 H5Sclose (space_hid);
01000 H5Tclose (type_hid);
01001 H5Dclose (data_hid);
01002 H5Gclose (group_hid);
01003 return false;
01004 }
01005 H5Tclose (st_id);
01006 H5Dclose (data_hid);
01007 nm = nm_tmp;
01008
01009 if (nm == anonymous)
01010 {
01011 #if HAVE_HDF5_18
01012 data_hid = H5Dopen (group_hid, "fcn", H5P_DEFAULT);
01013 #else
01014 data_hid = H5Dopen (group_hid, "fcn");
01015 #endif
01016
01017 if (data_hid < 0)
01018 {
01019 H5Sclose (space_hid);
01020 H5Tclose (type_hid);
01021 H5Gclose (group_hid);
01022 return false;
01023 }
01024
01025 H5Tclose (type_hid);
01026 type_hid = H5Dget_type (data_hid);
01027 type_class_hid = H5Tget_class (type_hid);
01028
01029 if (type_class_hid != H5T_STRING)
01030 {
01031 H5Sclose (space_hid);
01032 H5Tclose (type_hid);
01033 H5Dclose (data_hid);
01034 H5Gclose (group_hid);
01035 return false;
01036 }
01037
01038 H5Sclose (space_hid);
01039 space_hid = H5Dget_space (data_hid);
01040 rank = H5Sget_simple_extent_ndims (space_hid);
01041
01042 if (rank != 0)
01043 {
01044 H5Sclose (space_hid);
01045 H5Tclose (type_hid);
01046 H5Dclose (data_hid);
01047 H5Gclose (group_hid);
01048 return false;
01049 }
01050
01051 slen = H5Tget_size (type_hid);
01052 if (slen < 0)
01053 {
01054 H5Sclose (space_hid);
01055 H5Tclose (type_hid);
01056 H5Dclose (data_hid);
01057 H5Gclose (group_hid);
01058 return false;
01059 }
01060
01061 OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen);
01062
01063
01064 st_id = H5Tcopy (H5T_C_S1);
01065 H5Tset_size (st_id, slen);
01066
01067 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, fcn_tmp) < 0)
01068 {
01069 H5Tclose (st_id);
01070 H5Sclose (space_hid);
01071 H5Tclose (type_hid);
01072 H5Dclose (data_hid);
01073 H5Gclose (group_hid);
01074 return false;
01075 }
01076 H5Tclose (st_id);
01077 H5Dclose (data_hid);
01078
01079 octave_idx_type len = 0;
01080
01081
01082
01083
01084
01085 H5E_auto_t err_func;
01086 void *err_func_data;
01087
01088
01089
01090 #if HAVE_HDF5_18
01091 H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
01092 H5Eset_auto (H5E_DEFAULT, 0, 0);
01093 #else
01094 H5Eget_auto (&err_func, &err_func_data);
01095 H5Eset_auto (0, 0);
01096 #endif
01097
01098 hid_t attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE");
01099
01100 if (attr_id >= 0)
01101 {
01102 if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0)
01103 success = false;
01104
01105 H5Aclose (attr_id);
01106 }
01107
01108
01109 #if HAVE_HDF5_18
01110 H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
01111 #else
01112 H5Eset_auto (err_func, err_func_data);
01113 #endif
01114
01115 unwind_protect_safe frame;
01116
01117
01118
01119
01120 symbol_table::scope_id local_scope = symbol_table::alloc_scope ();
01121 frame.add_fcn (symbol_table::erase_scope, local_scope);
01122
01123 symbol_table::set_scope (local_scope);
01124
01125 octave_call_stack::push (local_scope, 0);
01126 frame.add_fcn (octave_call_stack::pop);
01127
01128 if (len > 0 && success)
01129 {
01130 hsize_t num_obj = 0;
01131 #if HAVE_HDF5_18
01132 data_hid = H5Gopen (group_hid, "symbol table", H5P_DEFAULT);
01133 #else
01134 data_hid = H5Gopen (group_hid, "symbol table");
01135 #endif
01136 H5Gget_num_objs (data_hid, &num_obj);
01137 H5Gclose (data_hid);
01138
01139 if (num_obj != static_cast<hsize_t>(len))
01140 {
01141 error ("load: failed to load anonymous function handle");
01142 success = false;
01143 }
01144
01145 if (! error_state)
01146 {
01147 hdf5_callback_data dsub;
01148 int current_item = 0;
01149 for (octave_idx_type i = 0; i < len; i++)
01150 {
01151 if (H5Giterate (group_hid, "symbol table", ¤t_item,
01152 hdf5_read_next_data, &dsub) <= 0)
01153 {
01154 error ("load: failed to load anonymous function handle");
01155 success = false;
01156 break;
01157 }
01158
01159 symbol_table::varref (dsub.name, local_scope) = dsub.tc;
01160 }
01161 }
01162 }
01163
01164 if (success)
01165 {
01166 int parse_status;
01167 octave_value anon_fcn_handle =
01168 eval_string (fcn_tmp, true, parse_status);
01169
01170 if (parse_status == 0)
01171 {
01172 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
01173
01174 if (fh)
01175 {
01176 fcn = fh->fcn;
01177
01178 octave_user_function *uf = fcn.user_function_value (true);
01179
01180 if (uf)
01181 symbol_table::cache_name (uf->scope (), nm);
01182 }
01183 else
01184 success = false;
01185 }
01186 else
01187 success = false;
01188 }
01189
01190 frame.run ();
01191 }
01192 else
01193 {
01194 std::string octaveroot;
01195 std::string fpath;
01196
01197
01198
01199
01200
01201 H5E_auto_t err_func;
01202 void *err_func_data;
01203
01204
01205
01206 #if HAVE_HDF5_18
01207 H5Eget_auto (H5E_DEFAULT, &err_func, &err_func_data);
01208 H5Eset_auto (H5E_DEFAULT, 0, 0);
01209 #else
01210 H5Eget_auto (&err_func, &err_func_data);
01211 H5Eset_auto (0, 0);
01212 #endif
01213
01214 hid_t attr_id = H5Aopen_name (group_hid, "OCTAVEROOT");
01215 if (attr_id >= 0)
01216 {
01217 H5Tclose (type_hid);
01218 type_hid = H5Aget_type (attr_id);
01219 type_class_hid = H5Tget_class (type_hid);
01220
01221 if (type_class_hid != H5T_STRING)
01222 success = false;
01223 else
01224 {
01225 slen = H5Tget_size (type_hid);
01226 st_id = H5Tcopy (H5T_C_S1);
01227 H5Tset_size (st_id, slen);
01228 OCTAVE_LOCAL_BUFFER (char, root_tmp, slen);
01229
01230 if (H5Aread (attr_id, st_id, root_tmp) < 0)
01231 success = false;
01232 else
01233 octaveroot = root_tmp;
01234
01235 H5Tclose (st_id);
01236 }
01237
01238 H5Aclose (attr_id);
01239 }
01240
01241 if (success)
01242 {
01243 attr_id = H5Aopen_name (group_hid, "FILE");
01244 if (attr_id >= 0)
01245 {
01246 H5Tclose (type_hid);
01247 type_hid = H5Aget_type (attr_id);
01248 type_class_hid = H5Tget_class (type_hid);
01249
01250 if (type_class_hid != H5T_STRING)
01251 success = false;
01252 else
01253 {
01254 slen = H5Tget_size (type_hid);
01255 st_id = H5Tcopy (H5T_C_S1);
01256 H5Tset_size (st_id, slen);
01257 OCTAVE_LOCAL_BUFFER (char, path_tmp, slen);
01258
01259 if (H5Aread (attr_id, st_id, path_tmp) < 0)
01260 success = false;
01261 else
01262 fpath = path_tmp;
01263
01264 H5Tclose (st_id);
01265 }
01266
01267 H5Aclose (attr_id);
01268 }
01269 }
01270
01271
01272 #if HAVE_HDF5_18
01273 H5Eset_auto (H5E_DEFAULT, err_func, err_func_data);
01274 #else
01275 H5Eset_auto (err_func, err_func_data);
01276 #endif
01277
01278 success = (success ? set_fcn (octaveroot, fpath) : success);
01279 }
01280
01281 H5Tclose (type_hid);
01282 H5Sclose (space_hid);
01283 H5Gclose (group_hid);
01284
01285 return success;
01286 }
01287
01288 #endif
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327 void
01328 octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const
01329 {
01330 print_raw (os, pr_as_read_syntax);
01331 newline (os);
01332 }
01333
01334 void
01335 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const
01336 {
01337 bool printed = false;
01338
01339 if (nm == anonymous)
01340 {
01341 tree_print_code tpc (os);
01342
01343
01344
01345
01346 octave_value ftmp = fcn;
01347
01348 octave_user_function *f = ftmp.user_function_value ();
01349
01350 if (f)
01351 {
01352 tree_parameter_list *p = f->parameter_list ();
01353
01354 os << "@(";
01355
01356 if (p)
01357 p->accept (tpc);
01358
01359 os << ") ";
01360
01361 tpc.print_fcn_handle_body (f->body ());
01362
01363 printed = true;
01364 }
01365 }
01366
01367 if (! printed)
01368 octave_print_internal (os, "@" + nm, pr_as_read_syntax,
01369 current_print_indent_level ());
01370 }
01371
01372 octave_value
01373 make_fcn_handle (const std::string& nm, bool local_funcs)
01374 {
01375 octave_value retval;
01376
01377
01378
01379
01380
01381
01382
01383
01384 std::string tnm = nm;
01385
01386 size_t len = nm.length ();
01387
01388 if (len == 3 && nm == ".**")
01389 tnm = "power";
01390 else if (len == 2)
01391 {
01392 if (nm[0] == '.')
01393 {
01394 switch (nm[1])
01395 {
01396 case '\'':
01397 tnm = "transpose";
01398 break;
01399
01400 case '+':
01401 tnm = "plus";
01402 break;
01403
01404 case '-':
01405 tnm = "minus";
01406 break;
01407
01408 case '*':
01409 tnm = "times";
01410 break;
01411
01412 case '/':
01413 tnm = "rdivide";
01414 break;
01415
01416 case '^':
01417 tnm = "power";
01418 break;
01419
01420 case '\\':
01421 tnm = "ldivide";
01422 break;
01423 }
01424 }
01425 else if (nm[1] == '=')
01426 {
01427 switch (nm[0])
01428 {
01429 case '<':
01430 tnm = "le";
01431 break;
01432
01433 case '=':
01434 tnm = "eq";
01435 break;
01436
01437 case '>':
01438 tnm = "ge";
01439 break;
01440
01441 case '~':
01442 case '!':
01443 tnm = "ne";
01444 break;
01445 }
01446 }
01447 else if (nm == "**")
01448 tnm = "mpower";
01449 }
01450 else if (len == 1)
01451 {
01452 switch (nm[0])
01453 {
01454 case '~':
01455 case '!':
01456 tnm = "not";
01457 break;
01458
01459 case '\'':
01460 tnm = "ctranspose";
01461 break;
01462
01463 case '+':
01464 tnm = "plus";
01465 break;
01466
01467 case '-':
01468 tnm = "minus";
01469 break;
01470
01471 case '*':
01472 tnm = "mtimes";
01473 break;
01474
01475 case '/':
01476 tnm = "mrdivide";
01477 break;
01478
01479 case '^':
01480 tnm = "mpower";
01481 break;
01482
01483 case '\\':
01484 tnm = "mldivide";
01485 break;
01486
01487 case '<':
01488 tnm = "lt";
01489 break;
01490
01491 case '>':
01492 tnm = "gt";
01493 break;
01494
01495 case '&':
01496 tnm = "and";
01497 break;
01498
01499 case '|':
01500 tnm = "or";
01501 break;
01502 }
01503 }
01504
01505 octave_value f = symbol_table::find_function (tnm, octave_value_list (),
01506 local_funcs);
01507
01508 octave_function *fptr = f.function_value (true);
01509
01510
01511
01512 if (local_funcs && fptr
01513 && (fptr->is_subfunction () || fptr->is_private_function ()
01514 || fptr->is_class_constructor ()))
01515 {
01516
01517 retval = octave_value (new octave_fcn_handle (f, tnm));
01518 }
01519 else
01520 {
01521
01522 std::list<std::string> classes = load_path::overloads (tnm);
01523 bool any_match = fptr != 0 || classes.size () > 0;
01524 if (! any_match)
01525 {
01526
01527 load_path::update ();
01528 classes = load_path::overloads (tnm);
01529 any_match = classes.size () > 0;
01530 }
01531
01532 if (any_match)
01533 {
01534 octave_fcn_handle *fh = new octave_fcn_handle (f, tnm);
01535 retval = fh;
01536
01537 for (std::list<std::string>::iterator iter = classes.begin ();
01538 iter != classes.end (); iter++)
01539 {
01540 std::string class_name = *iter;
01541 octave_value fmeth = symbol_table::find_method (tnm, class_name);
01542
01543 bool is_builtin = false;
01544 for (int i = 0; i < btyp_num_types; i++)
01545 {
01546
01547 if (class_name == btyp_class_name[i])
01548 {
01549 is_builtin = true;
01550 fh->set_overload (static_cast<builtin_type_t> (i), fmeth);
01551 }
01552 }
01553
01554 if (! is_builtin)
01555 fh->set_overload (class_name, fmeth);
01556 }
01557 }
01558 else
01559 error ("@%s: no function and no method found", tnm.c_str ());
01560 }
01561
01562 return retval;
01563 }
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599 DEFUN (functions, args, ,
01600 "-*- texinfo -*-\n\
01601 @deftypefn {Built-in Function} {} functions (@var{fcn_handle})\n\
01602 Return a struct containing information about the function handle\n\
01603 @var{fcn_handle}.\n\
01604 @end deftypefn")
01605 {
01606 octave_value retval;
01607
01608 if (args.length () == 1)
01609 {
01610 octave_fcn_handle *fh = args(0).fcn_handle_value ();
01611
01612 if (! error_state)
01613 {
01614 octave_function *fcn = fh ? fh->function_value () : 0;
01615
01616 if (fcn)
01617 {
01618 octave_scalar_map m;
01619
01620 std::string fh_nm = fh->fcn_name ();
01621
01622 if (fh_nm == octave_fcn_handle::anonymous)
01623 {
01624 std::ostringstream buf;
01625 fh->print_raw (buf);
01626 m.setfield ("function", buf.str ());
01627
01628 m.setfield ("type", "anonymous");
01629 }
01630 else
01631 {
01632 m.setfield ("function", fh_nm);
01633
01634 if (fcn->is_subfunction ())
01635 {
01636 m.setfield ("type", "subfunction");
01637 Cell parentage (dim_vector (1, 2));
01638 parentage.elem(0) = fh_nm;
01639 parentage.elem(1) = fcn->parent_fcn_name ();
01640 m.setfield ("parentage", octave_value (parentage));
01641 }
01642 else if (fcn->is_private_function ())
01643 m.setfield ("type", "private");
01644 else if (fh->is_overloaded ())
01645 m.setfield ("type", "overloaded");
01646 else
01647 m.setfield ("type", "simple");
01648 }
01649
01650 std::string nm = fcn->fcn_file_name ();
01651
01652 if (fh_nm == octave_fcn_handle::anonymous)
01653 {
01654 m.setfield ("file", nm);
01655
01656 octave_user_function *fu = fh->user_function_value ();
01657
01658 std::list<symbol_table::symbol_record> vars
01659 = symbol_table::all_variables (fu->scope (), 0);
01660
01661 size_t varlen = vars.size ();
01662
01663 if (varlen > 0)
01664 {
01665 octave_scalar_map ws;
01666 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin ();
01667 p != vars.end (); p++)
01668 {
01669 ws.assign (p->name (), p->varval (0));
01670 }
01671
01672 m.setfield ("workspace", ws);
01673 }
01674 }
01675 else if (fcn->is_user_function () || fcn->is_user_script ())
01676 {
01677 octave_function *fu = fh->function_value ();
01678 m.setfield ("file", fu->fcn_file_name ());
01679 }
01680 else
01681 m.setfield ("file", "");
01682
01683 retval = m;
01684 }
01685 else
01686 error ("functions: FCN_HANDLE is not a valid function handle object");
01687 }
01688 else
01689 error ("functions: FCN_HANDLE argument must be a function handle object");
01690 }
01691 else
01692 print_usage ();
01693
01694 return retval;
01695 }
01696
01697 DEFUN (func2str, args, ,
01698 "-*- texinfo -*-\n\
01699 @deftypefn {Built-in Function} {} func2str (@var{fcn_handle})\n\
01700 Return a string containing the name of the function referenced by\n\
01701 the function handle @var{fcn_handle}.\n\
01702 @end deftypefn")
01703 {
01704 octave_value retval;
01705
01706 if (args.length () == 1)
01707 {
01708 octave_fcn_handle *fh = args(0).fcn_handle_value ();
01709
01710 if (! error_state && fh)
01711 {
01712 std::string fh_nm = fh->fcn_name ();
01713
01714 if (fh_nm == octave_fcn_handle::anonymous)
01715 {
01716 std::ostringstream buf;
01717
01718 fh->print_raw (buf);
01719
01720 retval = buf.str ();
01721 }
01722 else
01723 retval = fh_nm;
01724 }
01725 else
01726 error ("func2str: FCN_HANDLE must be a valid function handle");
01727 }
01728 else
01729 print_usage ();
01730
01731 return retval;
01732 }
01733
01734 DEFUN (str2func, args, ,
01735 "-*- texinfo -*-\n\
01736 @deftypefn {Built-in Function} {} str2func (@var{fcn_name})\n\
01737 @deftypefnx {Built-in Function} {} str2func (@var{fcn_name}, \"global\")\n\
01738 Return a function handle constructed from the string @var{fcn_name}.\n\
01739 If the optional \"global\" argument is passed, locally visible functions\n\
01740 are ignored in the lookup.\n\
01741 @end deftypefn")
01742 {
01743 octave_value retval;
01744 int nargin = args.length ();
01745
01746 if (nargin == 1 || nargin == 2)
01747 {
01748 std::string nm = args(0).string_value ();
01749
01750 if (! error_state)
01751 retval = make_fcn_handle (nm, nargin != 2);
01752 else
01753 error ("str2func: FCN_NAME must be a string");
01754 }
01755 else
01756 print_usage ();
01757
01758 return retval;
01759 }
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779 DEFUN (is_function_handle, args, ,
01780 "-*- texinfo -*-\n\
01781 @deftypefn {Built-in Function} {} is_function_handle (@var{x})\n\
01782 Return true if @var{x} is a function handle.\n\
01783 @seealso{isa, typeinfo, class}\n\
01784 @end deftypefn")
01785 {
01786 octave_value retval;
01787
01788 int nargin = args.length ();
01789
01790 if (nargin == 1)
01791 retval = args(0).is_function_handle ();
01792 else
01793 print_usage ();
01794
01795 return retval;
01796 }
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811 octave_fcn_binder::octave_fcn_binder (const octave_value& f,
01812 const octave_value& root,
01813 const octave_value_list& templ,
01814 const std::vector<int>& mask,
01815 int exp_nargin)
01816 : octave_fcn_handle (f), root_handle (root), arg_template (templ),
01817 arg_mask (mask), expected_nargin (exp_nargin)
01818 {
01819 }
01820
01821 octave_fcn_handle *
01822 octave_fcn_binder::maybe_binder (const octave_value& f)
01823 {
01824 octave_fcn_handle *retval = 0;
01825
01826 octave_user_function *usr_fcn = f.user_function_value (false);
01827 tree_parameter_list *param_list = usr_fcn ? usr_fcn->parameter_list () : 0;
01828
01829
01830
01831 tree_statement_list *cmd_list = usr_fcn ? usr_fcn->body () : 0;
01832 tree_expression *body_expr = (cmd_list->length () == 1
01833 ? cmd_list->front ()->expression () : 0);
01834
01835
01836 if (body_expr && body_expr->is_index_expression ()
01837 && ! (param_list && param_list->takes_varargs ()))
01838 {
01839
01840 tree_index_expression *idx_expr = dynamic_cast<tree_index_expression *> (body_expr);
01841 tree_expression *head_expr = idx_expr->expression ();
01842 std::list<tree_argument_list *> arg_lists = idx_expr->arg_lists ();
01843 std::string type_tags = idx_expr->type_tags ();
01844
01845 if (type_tags.length () == 1 && type_tags[0] == '('
01846 && head_expr->is_identifier ())
01847 {
01848 assert (arg_lists.size () == 1);
01849
01850
01851 tree_identifier *head_id = dynamic_cast<tree_identifier *> (head_expr);
01852 tree_argument_list *arg_list = arg_lists.front ();
01853
01854
01855 std::map<std::string, int> arginmap;
01856 int npar = 0;
01857
01858 if (param_list)
01859 {
01860 for (tree_parameter_list::iterator it = param_list->begin ();
01861 it != param_list->end (); ++it, ++npar)
01862 {
01863 tree_decl_elt *elt = *it;
01864 tree_identifier *id = elt ? elt->ident () : 0;
01865 if (id && ! id->is_black_hole ())
01866 arginmap[id->name ()] = npar;
01867 }
01868 }
01869
01870 if (arg_list && arg_list->length () > 0)
01871 {
01872 bool bad = false;
01873 int nargs = arg_list->length ();
01874 octave_value_list arg_template (nargs);
01875 std::vector<int> arg_mask (nargs);
01876
01877
01878 int iarg = 0;
01879 for (tree_argument_list::iterator it = arg_list->begin ();
01880 it != arg_list->end (); ++it, ++iarg)
01881 {
01882 tree_expression *elt = *it;
01883 if (elt && elt->is_constant ())
01884 {
01885 arg_template(iarg) = elt->rvalue1 ();
01886 arg_mask[iarg] = -1;
01887 }
01888 else if (elt && elt->is_identifier ())
01889 {
01890 tree_identifier *elt_id = dynamic_cast<tree_identifier *> (elt);
01891 if (arginmap.find (elt_id->name ()) != arginmap.end ())
01892 {
01893 arg_mask[iarg] = arginmap[elt_id->name ()];
01894 }
01895 else if (elt_id->is_defined ())
01896 {
01897 arg_template(iarg) = elt_id->rvalue1 ();
01898 arg_mask[iarg] = -1;
01899 }
01900 else
01901 {
01902 bad = true;
01903 break;
01904 }
01905 }
01906 else
01907 {
01908 bad = true;
01909 break;
01910 }
01911 }
01912
01913 octave_value root_val;
01914
01915 if (! bad)
01916 {
01917
01918 if (head_id->is_defined ())
01919 root_val = head_id->rvalue1 ();
01920 else
01921 {
01922
01923 std::string head_name = head_id->name ();
01924
01925
01926 if (symbol_table::get_dispatch (head_name).size () > 0)
01927 bad = true;
01928 else
01929 {
01930
01931 unwind_protect frame;
01932 interpreter_try (frame);
01933
01934 root_val = make_fcn_handle (head_name);
01935 if (error_state)
01936 bad = true;
01937 }
01938 }
01939 }
01940
01941 if (! bad)
01942 {
01943
01944 std::list<string_vector> arg_names = idx_expr->arg_names ();
01945 assert (arg_names.size () == 1);
01946 arg_template.stash_name_tags (arg_names.front ());
01947
01948 retval = new octave_fcn_binder (f, root_val, arg_template,
01949 arg_mask, npar);
01950 }
01951 }
01952 }
01953 }
01954
01955 if (! retval)
01956 retval = new octave_fcn_handle (f, octave_fcn_handle::anonymous);
01957
01958 return retval;
01959 }
01960
01961 octave_value_list
01962 octave_fcn_binder::do_multi_index_op (int nargout,
01963 const octave_value_list& args)
01964 {
01965 return do_multi_index_op (nargout, args, 0);
01966 }
01967
01968 octave_value_list
01969 octave_fcn_binder::do_multi_index_op (int nargout,
01970 const octave_value_list& args,
01971 const std::list<octave_lvalue>* lvalue_list)
01972 {
01973 octave_value_list retval;
01974
01975 if (args.length () == expected_nargin)
01976 {
01977 for (int i = 0; i < arg_template.length (); i++)
01978 {
01979 int j = arg_mask[i];
01980 if (j >= 0)
01981 arg_template(i) = args(j);
01982 }
01983
01984
01985
01986 octave_value_list tmp (arg_template);
01987 retval = root_handle.do_multi_index_op (nargout, tmp, lvalue_list);
01988 }
01989 else
01990 retval = octave_fcn_handle::do_multi_index_op (nargout, args, lvalue_list);
01991
01992 return retval;
01993 }
01994
01995
01996
01997
01998
01999
02000
02001
02002