Mercurial > hg > octave-lyh
annotate src/ov-fcn-handle.cc @ 7689:a9d25da4ed9c
octave_fcn_handle::subsref: don't call next_subsref
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 03 Apr 2008 13:13:01 -0400 |
parents | 745a8299c2b5 |
children | 39930366b709 |
rev | line source |
---|---|
4343 | 1 /* |
2 | |
7017 | 3 Copyright (C) 2003, 2004, 2005, 2006, 2007 John W. Eaton |
4343 | 4 |
5 This file is part of Octave. | |
6 | |
7 Octave is free software; you can redistribute it and/or modify it | |
8 under the terms of the GNU General Public License as published by the | |
7016 | 9 Free Software Foundation; either version 3 of the License, or (at your |
10 option) any later version. | |
4343 | 11 |
12 Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
7016 | 18 along with Octave; see the file COPYING. If not, see |
19 <http://www.gnu.org/licenses/>. | |
4343 | 20 |
21 */ | |
22 | |
23 #ifdef HAVE_CONFIG_H | |
24 #include <config.h> | |
25 #endif | |
26 | |
27 #include <iostream> | |
5765 | 28 #include <sstream> |
5164 | 29 #include <vector> |
4343 | 30 |
7336 | 31 #include "file-ops.h" |
32 | |
4343 | 33 #include "defun.h" |
4654 | 34 #include "error.h" |
35 #include "gripes.h" | |
5663 | 36 #include "input.h" |
4343 | 37 #include "oct-map.h" |
38 #include "ov-base.h" | |
39 #include "ov-fcn-handle.h" | |
4980 | 40 #include "ov-usr-fcn.h" |
4343 | 41 #include "pr-output.h" |
4980 | 42 #include "pt-pr-code.h" |
43 #include "pt-misc.h" | |
44 #include "pt-stmt.h" | |
45 #include "pt-cmd.h" | |
46 #include "pt-exp.h" | |
47 #include "pt-assign.h" | |
4343 | 48 #include "variables.h" |
4988 | 49 #include "parse.h" |
6625 | 50 #include "unwind-prot.h" |
51 #include "defaults.h" | |
52 #include "file-stat.h" | |
53 #include "load-path.h" | |
54 #include "oct-env.h" | |
4988 | 55 |
56 #include "byte-swap.h" | |
57 #include "ls-oct-ascii.h" | |
6625 | 58 #include "ls-oct-binary.h" |
4988 | 59 #include "ls-hdf5.h" |
60 #include "ls-utils.h" | |
4343 | 61 |
62 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle); | |
63 | |
4612 | 64 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_handle, |
65 "function handle", | |
5946 | 66 "function_handle"); |
4343 | 67 |
4924 | 68 octave_value_list |
69 octave_fcn_handle::subsref (const std::string& type, | |
70 const std::list<octave_value_list>& idx, | |
71 int nargout) | |
72 { | |
73 octave_value_list retval; | |
74 | |
75 switch (type[0]) | |
76 { | |
77 case '(': | |
78 { | |
7336 | 79 out_of_date_check (fcn); |
5663 | 80 |
7336 | 81 if (fcn.is_defined ()) |
82 { | |
83 octave_function *f = function_value (); | |
5663 | 84 |
7336 | 85 if (f) |
86 retval = f->subsref (type, idx, nargout); | |
5663 | 87 else |
7336 | 88 error ("invalid function handle"); |
5663 | 89 } |
5312 | 90 else |
91 error ("invalid function handle"); | |
4924 | 92 } |
93 break; | |
94 | |
95 case '{': | |
96 case '.': | |
97 { | |
4930 | 98 std::string typ_nm = type_name (); |
99 error ("%s cannot be indexed with %c", typ_nm.c_str (), type[0]); | |
4924 | 100 } |
101 break; | |
102 | |
103 default: | |
104 panic_impossible (); | |
105 } | |
106 | |
7689
a9d25da4ed9c
octave_fcn_handle::subsref: don't call next_subsref
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
107 // There's no need to call next_subsref here -- |
a9d25da4ed9c
octave_fcn_handle::subsref: don't call next_subsref
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
108 // octave_function::subsref will handle that for us. |
4924 | 109 |
110 return retval; | |
111 } | |
112 | |
4988 | 113 bool |
6625 | 114 octave_fcn_handle::set_fcn (const std::string &octaveroot, |
115 const std::string& fpath) | |
4988 | 116 { |
6625 | 117 bool success = true; |
118 | |
119 if (octaveroot.length () != 0 && | |
120 fpath.length () >= octaveroot.length () && | |
121 fpath.substr (0, octaveroot.length ()) == octaveroot && | |
122 OCTAVE_EXEC_PREFIX != octaveroot) | |
123 { | |
124 // First check if just replacing matlabroot is enough | |
125 std::string str = OCTAVE_EXEC_PREFIX + | |
126 fpath.substr (octaveroot.length ()); | |
127 file_stat fs (str); | |
128 | |
129 if (fs.exists ()) | |
130 { | |
7336 | 131 size_t xpos = str.find_last_of (file_ops::dir_sep_chars); |
6625 | 132 |
7336 | 133 std::string dir_name = str.substr (0, xpos); |
6625 | 134 |
7336 | 135 octave_function *xfcn |
136 = load_fcn_from_file (str, dir_name, "", nm); | |
6625 | 137 |
7336 | 138 if (xfcn) |
139 { | |
140 octave_value tmp (xfcn); | |
6625 | 141 |
7336 | 142 fcn = octave_value (new octave_fcn_handle (tmp, nm)); |
6625 | 143 } |
144 else | |
145 { | |
146 error ("function handle points to non-existent function"); | |
147 success = false; | |
148 } | |
149 } | |
150 else | |
151 { | |
152 // Next just search for it anywhere in the system path | |
153 string_vector names(3); | |
154 names(0) = nm + ".oct"; | |
155 names(1) = nm + ".mex"; | |
156 names(2) = nm + ".m"; | |
157 | |
6626 | 158 dir_path p (load_path::system_path ()); |
6625 | 159 |
160 str = octave_env::make_absolute | |
161 (p.find_first_of (names), octave_env::getcwd ()); | |
162 | |
7336 | 163 size_t xpos = str.find_last_of (file_ops::dir_sep_chars); |
6625 | 164 |
7336 | 165 std::string dir_name = str.substr (0, xpos); |
166 | |
167 octave_function *xfcn = load_fcn_from_file (str, dir_name, "", nm); | |
4989 | 168 |
7336 | 169 if (xfcn) |
170 { | |
171 octave_value tmp (xfcn); | |
6625 | 172 |
7336 | 173 fcn = octave_value (new octave_fcn_handle (tmp, nm)); |
6625 | 174 } |
175 else | |
176 { | |
177 error ("function handle points to non-existent function"); | |
178 success = false; | |
179 } | |
180 } | |
181 } | |
182 else | |
183 { | |
184 if (fpath.length () > 0) | |
185 { | |
7336 | 186 size_t xpos = fpath.find_last_of (file_ops::dir_sep_chars); |
6625 | 187 |
7336 | 188 std::string dir_name = fpath.substr (0, xpos); |
189 | |
190 octave_function *xfcn = load_fcn_from_file (fpath, dir_name, "", nm); | |
6625 | 191 |
7336 | 192 if (xfcn) |
193 { | |
194 octave_value tmp (xfcn); | |
6625 | 195 |
7336 | 196 fcn = octave_value (new octave_fcn_handle (tmp, nm)); |
6625 | 197 } |
198 else | |
199 { | |
200 error ("function handle points to non-existent function"); | |
201 success = false; | |
202 } | |
203 } | |
204 else | |
205 { | |
7336 | 206 fcn = symbol_table::find_function (nm); |
207 | |
6625 | 208 if (! fcn.is_function ()) |
209 { | |
210 error ("function handle points to non-existent function"); | |
211 success = false; | |
212 } | |
213 } | |
214 } | |
215 | |
216 return success; | |
217 } | |
218 | |
219 bool | |
6974 | 220 octave_fcn_handle::save_ascii (std::ostream& os) |
6625 | 221 { |
4988 | 222 if (nm == "@<anonymous>") |
223 { | |
6625 | 224 os << nm << "\n"; |
225 | |
4989 | 226 print_raw (os, true); |
227 os << "\n"; | |
6625 | 228 |
7336 | 229 if (fcn.is_undefined ()) |
6625 | 230 return false; |
231 | |
232 octave_user_function *f = fcn.user_function_value (); | |
233 | |
7336 | 234 std::list<symbol_table::symbol_record> vars |
235 = symbol_table::all_variables (f->scope ()); | |
6625 | 236 |
7336 | 237 size_t varlen = vars.size (); |
6625 | 238 |
239 if (varlen > 0) | |
240 { | |
241 os << "# length: " << varlen << "\n"; | |
242 | |
7336 | 243 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin (); |
244 p != vars.end (); p++) | |
6625 | 245 { |
7336 | 246 if (! save_ascii_data (os, p->varval (), p->name (), false, 0)) |
6625 | 247 return os; |
248 } | |
249 } | |
250 } | |
251 else | |
252 { | |
253 os << "# octaveroot: " << OCTAVE_EXEC_PREFIX << "\n"; | |
254 os << "# path: " << user_function_value ()-> fcn_file_name () << "\n"; | |
255 os << nm << "\n"; | |
4988 | 256 } |
257 | |
258 return true; | |
259 } | |
260 | |
261 bool | |
262 octave_fcn_handle::load_ascii (std::istream& is) | |
263 { | |
6625 | 264 bool success = true; |
265 | |
266 std::streampos pos = is.tellg (); | |
267 std::string octaveroot = extract_keyword (is, "octaveroot", true); | |
268 if (octaveroot.length() == 0) | |
269 { | |
270 is.seekg (pos); | |
271 is.clear (); | |
272 } | |
273 pos = is.tellg (); | |
274 std::string fpath = extract_keyword (is, "path", true); | |
275 if (fpath.length() == 0) | |
276 { | |
277 is.seekg (pos); | |
278 is.clear (); | |
279 } | |
280 | |
4988 | 281 is >> nm; |
4989 | 282 |
4988 | 283 if (nm == "@<anonymous>") |
284 { | |
6625 | 285 octave_idx_type len = 0; |
4988 | 286 char c; |
5765 | 287 std::ostringstream buf; |
4988 | 288 |
4989 | 289 // Skip preceeding newline(s). |
290 while (is.get (c) && c == '\n') | |
291 /* do nothing */; | |
4988 | 292 |
293 if (is) | |
294 { | |
295 buf << c; | |
296 | |
297 // Get a line of text whitespace characters included, leaving | |
4989 | 298 // newline in the stream. |
299 | |
4988 | 300 while (is.peek () != '\n') |
301 { | |
302 is.get (c); | |
303 if (! is) | |
304 break; | |
305 buf << c; | |
306 } | |
307 } | |
308 | |
6625 | 309 pos = is.tellg (); |
7336 | 310 |
311 symbol_table::scope_id local_scope = symbol_table::alloc_scope (); | |
4988 | 312 |
6625 | 313 if (extract_keyword (is, "length", len, true) && len >= 0) |
4989 | 314 { |
6625 | 315 if (len > 0) |
316 { | |
317 for (octave_idx_type i = 0; i < len; i++) | |
318 { | |
319 octave_value t2; | |
320 bool dummy; | |
321 | |
322 std::string name | |
323 = read_ascii_data (is, std::string (), dummy, t2, i); | |
324 | |
325 if (!is) | |
326 { | |
327 error ("load: failed to load anonymous function handle"); | |
328 break; | |
329 } | |
330 | |
7336 | 331 symbol_table::varref (name, local_scope) = t2; |
6625 | 332 } |
333 } | |
4989 | 334 } |
335 else | |
6625 | 336 { |
337 is.seekg (pos); | |
338 is.clear (); | |
339 } | |
340 | |
341 if (is && success) | |
342 { | |
343 unwind_protect::begin_frame ("anon_ascii_load"); | |
344 | |
7336 | 345 symbol_table::push_scope (local_scope); |
346 | |
347 unwind_protect::add (symbol_table::pop_scope); | |
6625 | 348 |
349 int parse_status; | |
350 octave_value anon_fcn_handle = | |
351 eval_string (buf.str (), true, parse_status); | |
352 | |
353 if (parse_status == 0) | |
354 { | |
355 octave_fcn_handle *fh = | |
356 anon_fcn_handle.fcn_handle_value (); | |
357 if (fh) | |
358 fcn = fh->fcn; | |
359 else | |
360 success = false; | |
361 } | |
362 else | |
363 success = false; | |
364 | |
365 unwind_protect::run_frame ("anon_ascii_load"); | |
366 } | |
367 else | |
368 success = false; | |
369 | |
7336 | 370 symbol_table::erase_scope (local_scope); |
4988 | 371 } |
372 else | |
6625 | 373 success = set_fcn (octaveroot, fpath); |
4988 | 374 |
6625 | 375 return success; |
4988 | 376 } |
377 | |
6625 | 378 /* |
379 | |
380 %!test | |
381 %! a = 2; | |
382 %! f = @(x) a + x; | |
383 %! g = @(x) 2 * x; | |
384 %! h = @log2; | |
385 %! f2 = f; | |
386 %! g2 = g; | |
387 %! h2 = h; | |
388 %! nm = tmpnam(); | |
389 %! unwind_protect | |
390 %! save ("-text", nm, "f2", "g2", "h2"); | |
391 %! clear f2 g2 h2 | |
392 %! load (nm); | |
393 %! assert (f(2),f2(2)); | |
394 %! assert (g(2),g2(2)); | |
395 %! assert (g(3),g2(3)); | |
396 %! unlink (nm); | |
397 %! save ("-text", nm, "f2", "g2", "h2"); | |
398 %! unwind_protect_cleanup | |
399 %! unlink (nm); | |
400 %! end_unwind_protect | |
401 | |
402 */ | |
403 | |
4988 | 404 bool |
6625 | 405 octave_fcn_handle::save_binary (std::ostream& os, bool& save_as_floats) |
4988 | 406 { |
407 if (nm == "@<anonymous>") | |
408 { | |
6625 | 409 std::ostringstream nmbuf; |
410 | |
7336 | 411 if (fcn.is_undefined ()) |
6625 | 412 return false; |
413 | |
414 octave_user_function *f = fcn.user_function_value (); | |
415 | |
7336 | 416 std::list<symbol_table::symbol_record> vars |
417 = symbol_table::all_variables (f->scope ()); | |
6625 | 418 |
7336 | 419 size_t varlen = vars.size (); |
6625 | 420 |
421 if (varlen > 0) | |
422 nmbuf << nm << " " << varlen; | |
423 else | |
424 nmbuf << nm; | |
425 | |
426 std::string buf_str = nmbuf.str(); | |
427 int32_t tmp = buf_str.length (); | |
428 os.write (reinterpret_cast<char *> (&tmp), 4); | |
429 os.write (buf_str.c_str (), buf_str.length ()); | |
430 | |
5765 | 431 std::ostringstream buf; |
4988 | 432 print_raw (buf, true); |
5765 | 433 std::string stmp = buf.str (); |
4988 | 434 tmp = stmp.length (); |
5760 | 435 os.write (reinterpret_cast<char *> (&tmp), 4); |
4988 | 436 os.write (stmp.c_str (), stmp.length ()); |
6625 | 437 |
438 if (varlen > 0) | |
439 { | |
7336 | 440 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin (); |
441 p != vars.end (); p++) | |
6625 | 442 { |
7336 | 443 if (! save_binary_data (os, p->varval (), p->name (), |
6625 | 444 "", 0, save_as_floats)) |
445 return os; | |
446 } | |
447 } | |
448 } | |
449 else | |
450 { | |
451 std::ostringstream nmbuf; | |
452 | |
453 nmbuf << nm << "\n" << OCTAVE_EXEC_PREFIX << "\n" | |
454 << user_function_value ()-> fcn_file_name () ; | |
455 | |
456 std::string buf_str = nmbuf.str (); | |
457 int32_t tmp = buf_str.length (); | |
458 os.write (reinterpret_cast<char *> (&tmp), 4); | |
459 os.write (buf_str.c_str (), buf_str.length ()); | |
4988 | 460 } |
7336 | 461 |
4988 | 462 return true; |
463 } | |
464 | |
465 bool | |
466 octave_fcn_handle::load_binary (std::istream& is, bool swap, | |
6625 | 467 oct_mach_info::float_format fmt) |
4988 | 468 { |
6625 | 469 bool success = true; |
7336 | 470 |
5828 | 471 int32_t tmp; |
5760 | 472 if (! is.read (reinterpret_cast<char *> (&tmp), 4)) |
4988 | 473 return false; |
474 if (swap) | |
475 swap_bytes<4> (&tmp); | |
476 | |
477 OCTAVE_LOCAL_BUFFER (char, ctmp1, tmp+1); | |
478 is.read (ctmp1, tmp); | |
479 nm = std::string (ctmp1); | |
480 | |
481 if (! is) | |
482 return false; | |
483 | |
6625 | 484 if (nm.length() >= 12 && nm.substr (0, 12) == "@<anonymous>") |
4988 | 485 { |
6625 | 486 octave_idx_type len = 0; |
487 | |
488 if (nm.length() > 12) | |
489 { | |
490 std::istringstream nm_is (nm.substr(12)); | |
491 nm_is >> len; | |
492 nm = nm.substr(0,12); | |
493 } | |
494 | |
5760 | 495 if (! is.read (reinterpret_cast<char *> (&tmp), 4)) |
4988 | 496 return false; |
497 if (swap) | |
498 swap_bytes<4> (&tmp); | |
499 | |
500 OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1); | |
501 is.read (ctmp2, tmp); | |
502 | |
7336 | 503 symbol_table::scope_id local_scope = symbol_table::alloc_scope (); |
504 | |
6625 | 505 if (len > 0) |
4989 | 506 { |
6625 | 507 for (octave_idx_type i = 0; i < len; i++) |
508 { | |
509 octave_value t2; | |
510 bool dummy; | |
511 std::string doc; | |
512 | |
513 std::string name = | |
514 read_binary_data (is, swap, fmt, std::string (), | |
515 dummy, t2, doc); | |
516 | |
517 if (!is) | |
518 { | |
519 error ("load: failed to load anonymous function handle"); | |
520 break; | |
521 } | |
522 | |
7336 | 523 symbol_table::varref (name, local_scope) = t2; |
6625 | 524 } |
525 } | |
526 | |
527 if (is && success) | |
528 { | |
529 unwind_protect::begin_frame ("anon_binary_load"); | |
530 | |
7336 | 531 symbol_table::push_scope (local_scope); |
532 | |
533 unwind_protect::add (symbol_table::pop_scope); | |
6625 | 534 |
535 int parse_status; | |
536 octave_value anon_fcn_handle = | |
537 eval_string (ctmp2, true, parse_status); | |
538 | |
539 if (parse_status == 0) | |
540 { | |
541 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); | |
542 if (fh) | |
543 fcn = fh->fcn; | |
544 else | |
545 success = false; | |
546 } | |
4989 | 547 else |
6625 | 548 success = false; |
549 | |
550 unwind_protect::run_frame ("anon_binary_load"); | |
4989 | 551 } |
6625 | 552 |
7336 | 553 symbol_table::erase_scope (local_scope); |
4988 | 554 } |
555 else | |
556 { | |
6625 | 557 std::string octaveroot; |
558 std::string fpath; | |
559 | |
560 if (nm.find_first_of ("\n") != NPOS) | |
6225 | 561 { |
6625 | 562 size_t pos1 = nm.find_first_of ("\n"); |
563 size_t pos2 = nm.find_first_of ("\n", pos1 + 1); | |
564 octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1); | |
565 fpath = nm.substr (pos2 + 1); | |
566 nm = nm.substr (0, pos1); | |
6225 | 567 } |
6625 | 568 |
569 success = set_fcn (octaveroot, fpath); | |
570 } | |
571 | |
572 return success; | |
4988 | 573 } |
574 | |
6625 | 575 /* |
576 | |
577 %!test | |
578 %! a = 2; | |
579 %! f = @(x) a + x; | |
580 %! g = @(x) 2 * x; | |
581 %! h = @log2; | |
582 %! f2 = f; | |
583 %! g2 = g; | |
584 %! h2 = h; | |
585 %! nm = tmpnam(); | |
586 %! unwind_protect | |
587 %! save ("-binary", nm, "f2", "g2", "h2"); | |
588 %! clear f2 g2 h2 | |
589 %! load (nm); | |
590 %! assert (f(2),f2(2)); | |
591 %! assert (g(2),g2(2)); | |
592 %! assert (g(3),g2(3)); | |
593 %! unlink (nm); | |
594 %! save ("-binary", nm, "f2", "g2", "h2"); | |
595 %! unwind_protect_cleanup | |
596 %! unlink (nm); | |
597 %! end_unwind_protect | |
598 | |
599 */ | |
600 | |
4988 | 601 #if defined (HAVE_HDF5) |
602 bool | |
603 octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name, | |
6625 | 604 bool save_as_floats) |
4988 | 605 { |
7336 | 606 bool retval = true; |
607 | |
4988 | 608 hid_t group_hid = -1; |
609 group_hid = H5Gcreate (loc_id, name, 0); | |
7336 | 610 if (group_hid < 0) |
611 return false; | |
4988 | 612 |
613 hid_t space_hid = -1, data_hid = -1, type_hid = -1;; | |
614 | |
615 // attach the type of the variable | |
616 type_hid = H5Tcopy (H5T_C_S1); | |
617 H5Tset_size (type_hid, nm.length () + 1); | |
618 if (type_hid < 0) | |
619 { | |
620 H5Gclose (group_hid); | |
621 return false; | |
622 } | |
623 | |
624 OCTAVE_LOCAL_BUFFER (hsize_t, hdims, 2); | |
625 hdims[0] = 0; | |
626 hdims[1] = 0; | |
5760 | 627 space_hid = H5Screate_simple (0 , hdims, 0); |
4988 | 628 if (space_hid < 0) |
629 { | |
630 H5Tclose (type_hid); | |
631 H5Gclose (group_hid); | |
632 return false; | |
633 } | |
634 | |
635 data_hid = H5Dcreate (group_hid, "nm", type_hid, space_hid, H5P_DEFAULT); | |
636 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, | |
5760 | 637 H5P_DEFAULT, nm.c_str ()) < 0) |
4988 | 638 { |
639 H5Sclose (space_hid); | |
640 H5Tclose (type_hid); | |
641 H5Gclose (group_hid); | |
642 return false; | |
643 } | |
644 H5Dclose (data_hid); | |
645 | |
646 if (nm == "@<anonymous>") | |
647 { | |
5765 | 648 std::ostringstream buf; |
4988 | 649 print_raw (buf, true); |
5765 | 650 std::string stmp = buf.str (); |
4988 | 651 |
652 // attach the type of the variable | |
653 H5Tset_size (type_hid, stmp.length () + 1); | |
654 if (type_hid < 0) | |
655 { | |
6695 | 656 H5Sclose (space_hid); |
4988 | 657 H5Gclose (group_hid); |
658 return false; | |
659 } | |
660 | |
661 data_hid = H5Dcreate (group_hid, "fcn", type_hid, space_hid, | |
662 H5P_DEFAULT); | |
663 if (data_hid < 0 || H5Dwrite (data_hid, type_hid, H5S_ALL, H5S_ALL, | |
5760 | 664 H5P_DEFAULT, stmp.c_str ()) < 0) |
4988 | 665 { |
666 H5Sclose (space_hid); | |
667 H5Tclose (type_hid); | |
668 H5Gclose (group_hid); | |
669 return false; | |
670 } | |
671 | |
672 H5Dclose (data_hid); | |
6625 | 673 |
674 octave_user_function *f = fcn.user_function_value (); | |
675 | |
7336 | 676 std::list<symbol_table::symbol_record> vars |
677 = symbol_table::all_variables (f->scope ()); | |
678 | |
679 size_t varlen = vars.size (); | |
6625 | 680 |
681 if (varlen > 0) | |
682 { | |
683 hid_t as_id = H5Screate (H5S_SCALAR); | |
684 | |
685 if (as_id >= 0) | |
686 { | |
687 hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE", | |
688 H5T_NATIVE_IDX, as_id, H5P_DEFAULT); | |
689 | |
690 if (a_id >= 0) | |
691 { | |
692 retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0); | |
693 | |
694 H5Aclose (a_id); | |
695 } | |
696 else | |
697 retval = false; | |
698 | |
699 H5Sclose (as_id); | |
700 } | |
701 else | |
702 retval = false; | |
703 | |
704 data_hid = H5Gcreate (group_hid, "symbol table", 0); | |
705 if (data_hid < 0) | |
706 { | |
707 H5Sclose (space_hid); | |
708 H5Tclose (type_hid); | |
709 H5Gclose (group_hid); | |
710 return false; | |
711 } | |
712 | |
7336 | 713 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin (); |
714 p != vars.end (); p++) | |
6625 | 715 { |
7336 | 716 if (! add_hdf5_data (data_hid, p->varval (), p->name (), |
6625 | 717 "", false, save_as_floats)) |
718 break; | |
719 } | |
720 H5Gclose (data_hid); | |
721 } | |
722 } | |
723 else | |
724 { | |
725 std::string octaveroot = OCTAVE_EXEC_PREFIX; | |
726 std::string fpath = user_function_value ()-> fcn_file_name (); | |
727 | |
728 H5Sclose (space_hid); | |
729 hdims[0] = 1; | |
730 hdims[1] = octaveroot.length (); | |
731 space_hid = H5Screate_simple (0 , hdims, 0); | |
732 if (space_hid < 0) | |
733 { | |
734 H5Tclose (type_hid); | |
735 H5Gclose (group_hid); | |
736 return false; | |
737 } | |
738 | |
739 H5Tclose (type_hid); | |
740 type_hid = H5Tcopy (H5T_C_S1); | |
741 H5Tset_size (type_hid, octaveroot.length () + 1); | |
742 | |
743 hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT", | |
744 type_hid, space_hid, H5P_DEFAULT); | |
745 | |
746 if (a_id >= 0) | |
747 { | |
748 retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0); | |
749 | |
750 H5Aclose (a_id); | |
751 } | |
752 else | |
6695 | 753 { |
754 H5Sclose (space_hid); | |
755 H5Tclose (type_hid); | |
756 H5Gclose (group_hid); | |
757 return false; | |
758 } | |
6625 | 759 |
760 H5Sclose (space_hid); | |
761 hdims[0] = 1; | |
762 hdims[1] = fpath.length (); | |
763 space_hid = H5Screate_simple (0 , hdims, 0); | |
764 if (space_hid < 0) | |
765 { | |
766 H5Tclose (type_hid); | |
767 H5Gclose (group_hid); | |
768 return false; | |
769 } | |
770 | |
771 H5Tclose (type_hid); | |
772 type_hid = H5Tcopy (H5T_C_S1); | |
773 H5Tset_size (type_hid, fpath.length () + 1); | |
774 | |
775 a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, H5P_DEFAULT); | |
776 | |
777 if (a_id >= 0) | |
778 { | |
779 retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0); | |
780 | |
781 H5Aclose (a_id); | |
782 } | |
783 else | |
784 retval = false; | |
4988 | 785 } |
786 | |
787 H5Sclose (space_hid); | |
788 H5Tclose (type_hid); | |
789 H5Gclose (group_hid); | |
790 | |
791 return retval; | |
792 } | |
793 | |
794 bool | |
795 octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name, | |
6625 | 796 bool have_h5giterate_bug) |
4988 | 797 { |
7336 | 798 bool success = true; |
799 | |
4988 | 800 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id; |
801 hsize_t rank; | |
802 int slen; | |
803 | |
804 group_hid = H5Gopen (loc_id, name); | |
7336 | 805 if (group_hid < 0) |
806 return false; | |
4988 | 807 |
808 data_hid = H5Dopen (group_hid, "nm"); | |
809 | |
810 if (data_hid < 0) | |
811 { | |
812 H5Gclose (group_hid); | |
813 return false; | |
814 } | |
815 | |
816 type_hid = H5Dget_type (data_hid); | |
817 type_class_hid = H5Tget_class (type_hid); | |
818 | |
819 if (type_class_hid != H5T_STRING) | |
820 { | |
821 H5Tclose (type_hid); | |
822 H5Dclose (data_hid); | |
823 H5Gclose (group_hid); | |
824 return false; | |
825 } | |
826 | |
827 space_hid = H5Dget_space (data_hid); | |
828 rank = H5Sget_simple_extent_ndims (space_hid); | |
829 | |
830 if (rank != 0) | |
831 { | |
832 H5Sclose (space_hid); | |
833 H5Tclose (type_hid); | |
834 H5Dclose (data_hid); | |
835 H5Gclose (group_hid); | |
836 return false; | |
837 } | |
838 | |
839 slen = H5Tget_size (type_hid); | |
840 if (slen < 0) | |
841 { | |
842 H5Sclose (space_hid); | |
843 H5Tclose (type_hid); | |
844 H5Dclose (data_hid); | |
845 H5Gclose (group_hid); | |
846 return false; | |
847 } | |
848 | |
849 OCTAVE_LOCAL_BUFFER (char, nm_tmp, slen); | |
850 | |
851 // create datatype for (null-terminated) string to read into: | |
852 st_id = H5Tcopy (H5T_C_S1); | |
853 H5Tset_size (st_id, slen); | |
854 | |
5760 | 855 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, nm_tmp) < 0) |
4988 | 856 { |
6695 | 857 H5Tclose (st_id); |
4988 | 858 H5Sclose (space_hid); |
859 H5Tclose (type_hid); | |
6695 | 860 H5Dclose (data_hid); |
4988 | 861 H5Gclose (group_hid); |
862 return false; | |
863 } | |
864 H5Tclose (st_id); | |
865 H5Dclose (data_hid); | |
866 nm = nm_tmp; | |
867 | |
868 if (nm == "@<anonymous>") | |
869 { | |
870 data_hid = H5Dopen (group_hid, "fcn"); | |
871 | |
872 if (data_hid < 0) | |
873 { | |
6695 | 874 H5Sclose (space_hid); |
875 H5Tclose (type_hid); | |
4988 | 876 H5Gclose (group_hid); |
877 return false; | |
878 } | |
879 | |
6695 | 880 H5Tclose (type_hid); |
4988 | 881 type_hid = H5Dget_type (data_hid); |
882 type_class_hid = H5Tget_class (type_hid); | |
883 | |
884 if (type_class_hid != H5T_STRING) | |
885 { | |
6695 | 886 H5Sclose (space_hid); |
4988 | 887 H5Tclose (type_hid); |
888 H5Dclose (data_hid); | |
889 H5Gclose (group_hid); | |
890 return false; | |
891 } | |
892 | |
6695 | 893 H5Sclose (space_hid); |
4988 | 894 space_hid = H5Dget_space (data_hid); |
895 rank = H5Sget_simple_extent_ndims (space_hid); | |
896 | |
897 if (rank != 0) | |
898 { | |
899 H5Sclose (space_hid); | |
900 H5Tclose (type_hid); | |
901 H5Dclose (data_hid); | |
902 H5Gclose (group_hid); | |
903 return false; | |
904 } | |
905 | |
906 slen = H5Tget_size (type_hid); | |
907 if (slen < 0) | |
908 { | |
909 H5Sclose (space_hid); | |
910 H5Tclose (type_hid); | |
911 H5Dclose (data_hid); | |
912 H5Gclose (group_hid); | |
913 return false; | |
914 } | |
915 | |
916 OCTAVE_LOCAL_BUFFER (char, fcn_tmp, slen); | |
917 | |
918 // create datatype for (null-terminated) string to read into: | |
919 st_id = H5Tcopy (H5T_C_S1); | |
920 H5Tset_size (st_id, slen); | |
921 | |
5760 | 922 if (H5Dread (data_hid, st_id, H5S_ALL, H5S_ALL, H5P_DEFAULT, fcn_tmp) < 0) |
4988 | 923 { |
6695 | 924 H5Tclose (st_id); |
4988 | 925 H5Sclose (space_hid); |
926 H5Tclose (type_hid); | |
6695 | 927 H5Dclose (data_hid); |
4988 | 928 H5Gclose (group_hid); |
929 return false; | |
930 } | |
6695 | 931 H5Tclose (st_id); |
4988 | 932 H5Dclose (data_hid); |
6625 | 933 |
934 octave_idx_type len = 0; | |
935 | |
936 // we have to pull some shenanigans here to make sure | |
937 // HDF5 doesn't print out all sorts of error messages if we | |
938 // call H5Aopen for a non-existing attribute | |
939 | |
940 H5E_auto_t err_func; | |
941 void *err_func_data; | |
4988 | 942 |
6625 | 943 // turn off error reporting temporarily, but save the error |
944 // reporting function: | |
945 H5Eget_auto (&err_func, &err_func_data); | |
946 H5Eset_auto (0, 0); | |
947 | |
948 hid_t attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE"); | |
4988 | 949 |
6625 | 950 if (attr_id >= 0) |
951 { | |
952 if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0) | |
953 success = false; | |
954 | |
955 H5Aclose (attr_id); | |
956 } | |
957 | |
958 // restore error reporting: | |
959 H5Eset_auto (err_func, err_func_data); | |
960 | |
7336 | 961 symbol_table::scope_id local_scope = symbol_table::alloc_scope (); |
962 | |
6625 | 963 if (len > 0 && success) |
4989 | 964 { |
6625 | 965 #ifdef HAVE_H5GGET_NUM_OBJS |
966 hsize_t num_obj = 0; | |
967 data_hid = H5Gopen (group_hid, "symbol table"); | |
968 H5Gget_num_objs (data_hid, &num_obj); | |
969 H5Gclose (data_hid); | |
970 | |
971 if (num_obj != static_cast<hsize_t>(len)) | |
972 { | |
973 error ("load: failed to load anonymous function handle"); | |
974 success = false; | |
975 } | |
976 #endif | |
977 | |
978 if (! error_state) | |
979 { | |
980 hdf5_callback_data dsub; | |
981 int current_item = 0; | |
982 for (octave_idx_type i = 0; i < len; i++) | |
983 { | |
984 if (H5Giterate (group_hid, "symbol table", ¤t_item, | |
985 hdf5_read_next_data, &dsub) <= 0) | |
986 { | |
987 error ("load: failed to load anonymous function handle"); | |
988 success = false; | |
989 break; | |
990 } | |
991 | |
992 if (have_h5giterate_bug) | |
993 current_item++; // H5Giterate returns last index processed | |
994 | |
7336 | 995 symbol_table::varref (dsub.name, local_scope) = dsub.tc; |
6625 | 996 } |
997 } | |
998 } | |
999 | |
1000 if (success) | |
1001 { | |
1002 unwind_protect::begin_frame ("anon_hdf5_load"); | |
1003 | |
7336 | 1004 symbol_table::push_scope (local_scope); |
1005 | |
1006 unwind_protect::add (symbol_table::pop_scope); | |
6625 | 1007 |
1008 int parse_status; | |
1009 octave_value anon_fcn_handle = | |
1010 eval_string (fcn_tmp, true, parse_status); | |
1011 | |
1012 if (parse_status == 0) | |
1013 { | |
1014 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); | |
1015 if (fh) | |
1016 fcn = fh->fcn; | |
1017 else | |
1018 success = false; | |
1019 } | |
4989 | 1020 else |
6625 | 1021 success = false; |
1022 | |
1023 unwind_protect::run_frame ("anon_hdf5_load"); | |
4989 | 1024 } |
6625 | 1025 |
7336 | 1026 symbol_table::erase_scope (local_scope); |
4988 | 1027 } |
1028 else | |
1029 { | |
6625 | 1030 std::string octaveroot; |
1031 std::string fpath; | |
1032 | |
1033 // we have to pull some shenanigans here to make sure | |
1034 // HDF5 doesn't print out all sorts of error messages if we | |
1035 // call H5Aopen for a non-existing attribute | |
1036 | |
1037 H5E_auto_t err_func; | |
1038 void *err_func_data; | |
1039 | |
1040 // turn off error reporting temporarily, but save the error | |
1041 // reporting function: | |
1042 H5Eget_auto (&err_func, &err_func_data); | |
1043 H5Eset_auto (0, 0); | |
1044 | |
1045 hid_t attr_id = H5Aopen_name (group_hid, "OCTAVEROOT"); | |
1046 if (attr_id >= 0) | |
6225 | 1047 { |
6695 | 1048 H5Tclose (type_hid); |
6625 | 1049 type_hid = H5Aget_type (attr_id); |
1050 type_class_hid = H5Tget_class (type_hid); | |
1051 | |
1052 if (type_class_hid != H5T_STRING) | |
1053 success = false; | |
1054 else | |
1055 { | |
1056 slen = H5Tget_size (type_hid); | |
1057 st_id = H5Tcopy (H5T_C_S1); | |
1058 H5Tset_size (st_id, slen); | |
1059 OCTAVE_LOCAL_BUFFER (char, root_tmp, slen); | |
1060 | |
1061 if (H5Aread (attr_id, st_id, root_tmp) < 0) | |
1062 success = false; | |
1063 else | |
1064 octaveroot = root_tmp; | |
6695 | 1065 |
1066 H5Tclose (st_id); | |
6625 | 1067 } |
1068 | |
1069 H5Aclose (attr_id); | |
6225 | 1070 } |
6625 | 1071 |
6695 | 1072 if (success) |
6625 | 1073 { |
6695 | 1074 attr_id = H5Aopen_name (group_hid, "FILE"); |
1075 if (attr_id >= 0) | |
1076 { | |
1077 H5Tclose (type_hid); | |
1078 type_hid = H5Aget_type (attr_id); | |
1079 type_class_hid = H5Tget_class (type_hid); | |
6625 | 1080 |
6695 | 1081 if (type_class_hid != H5T_STRING) |
6625 | 1082 success = false; |
1083 else | |
6695 | 1084 { |
1085 slen = H5Tget_size (type_hid); | |
1086 st_id = H5Tcopy (H5T_C_S1); | |
1087 H5Tset_size (st_id, slen); | |
1088 OCTAVE_LOCAL_BUFFER (char, path_tmp, slen); | |
1089 | |
1090 if (H5Aread (attr_id, st_id, path_tmp) < 0) | |
1091 success = false; | |
1092 else | |
1093 fpath = path_tmp; | |
1094 | |
1095 H5Tclose (st_id); | |
1096 } | |
1097 | |
1098 H5Aclose (attr_id); | |
6625 | 1099 } |
1100 } | |
1101 | |
1102 // restore error reporting: | |
1103 H5Eset_auto (err_func, err_func_data); | |
1104 | |
1105 success = (success ? set_fcn (octaveroot, fpath) : success); | |
4988 | 1106 } |
1107 | |
6695 | 1108 H5Tclose (type_hid); |
1109 H5Sclose (space_hid); | |
1110 H5Gclose (group_hid); | |
1111 | |
6625 | 1112 return success; |
4988 | 1113 } |
6625 | 1114 |
1115 /* | |
1116 | |
1117 %!test | |
1118 %! if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_HDF5"))) | |
1119 %! a = 2; | |
1120 %! f = @(x) a + x; | |
1121 %! g = @(x) 2 * x; | |
1122 %! h = @log2; | |
1123 %! f2 = f; | |
1124 %! g2 = g; | |
1125 %! h2 = h; | |
1126 %! nm = tmpnam(); | |
1127 %! unwind_protect | |
1128 %! save ("-hdf5", nm, "f2", "g2", "h2"); | |
1129 %! clear f2 g2 h2 | |
1130 %! load (nm); | |
1131 %! assert (f(2),f2(2)); | |
1132 %! assert (g(2),g2(2)); | |
1133 %! assert (g(3),g2(3)); | |
1134 %! unlink (nm); | |
1135 %! save ("-hdf5", nm, "f2", "g2", "h2"); | |
1136 %! unwind_protect_cleanup | |
1137 %! unlink (nm); | |
1138 %! end_unwind_protect | |
1139 %! endif | |
1140 | |
1141 */ | |
4988 | 1142 #endif |
1143 | |
4343 | 1144 void |
1145 octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const | |
1146 { | |
1147 print_raw (os, pr_as_read_syntax); | |
1148 newline (os); | |
1149 } | |
1150 | |
1151 void | |
1152 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const | |
1153 { | |
4980 | 1154 bool printed = false; |
1155 | |
1156 if (nm == "@<anonymous>") | |
1157 { | |
1158 tree_print_code tpc (os); | |
1159 | |
4989 | 1160 // FCN is const because this member function is, so we can't |
4980 | 1161 // use it to call user_function_value, so we make a copy first. |
1162 | |
1163 octave_value ftmp = fcn; | |
1164 | |
1165 octave_user_function *f = ftmp.user_function_value (); | |
1166 | |
1167 if (f) | |
1168 { | |
1169 tree_parameter_list *p = f->parameter_list (); | |
1170 | |
1171 os << "@("; | |
1172 | |
1173 if (p) | |
1174 p->accept (tpc); | |
1175 | |
1176 os << ") "; | |
1177 | |
1178 tree_statement_list *b = f->body (); | |
1179 | |
1180 if (b) | |
1181 { | |
1182 assert (b->length () == 1); | |
1183 | |
1184 tree_statement *s = b->front (); | |
1185 | |
1186 if (s) | |
1187 { | |
1188 if (s->is_expression ()) | |
1189 { | |
1190 tree_expression *e = s->expression (); | |
1191 | |
1192 if (e) | |
6657 | 1193 e->accept (tpc); |
4980 | 1194 } |
1195 else | |
1196 { | |
1197 tree_command *c = s->command (); | |
1198 | |
1199 tpc.suspend_newline (); | |
1200 c->accept (tpc); | |
1201 tpc.resume_newline (); | |
1202 } | |
1203 } | |
1204 } | |
1205 | |
1206 printed = true; | |
1207 } | |
1208 } | |
1209 | |
1210 if (! printed) | |
1211 octave_print_internal (os, nm, pr_as_read_syntax, | |
1212 current_print_indent_level ()); | |
4343 | 1213 } |
1214 | |
1215 octave_value | |
1216 make_fcn_handle (const std::string& nm) | |
1217 { | |
1218 octave_value retval; | |
1219 | |
7336 | 1220 octave_value f = symbol_table::find_function (nm); |
6481 | 1221 |
7336 | 1222 if (f.is_defined ()) |
4930 | 1223 retval = octave_value (new octave_fcn_handle (f, nm)); |
4343 | 1224 else |
1225 error ("error creating function handle \"@%s\"", nm.c_str ()); | |
1226 | |
1227 return retval; | |
1228 } | |
1229 | |
4933 | 1230 DEFUN (functions, args, , |
4343 | 1231 "-*- texinfo -*-\n\ |
4933 | 1232 @deftypefn {Built-in Function} {} functions (@var{fcn_handle})\n\ |
1233 Return a struct containing information about the function handle\n\ | |
1234 @var{fcn_handle}.\n\ | |
1235 @end deftypefn") | |
4343 | 1236 { |
1237 octave_value retval; | |
1238 | |
4933 | 1239 if (args.length () == 1) |
4343 | 1240 { |
4933 | 1241 octave_fcn_handle *fh = args(0).fcn_handle_value (); |
4343 | 1242 |
1243 if (! error_state) | |
1244 { | |
4933 | 1245 octave_function *fcn = fh ? fh->function_value (true) : 0; |
4343 | 1246 |
4933 | 1247 if (fcn) |
4930 | 1248 { |
4933 | 1249 Octave_map m; |
4649 | 1250 |
4933 | 1251 std::string fh_nm = fh->fcn_name (); |
1252 | |
6625 | 1253 if (fh_nm == "@<anonymous>") |
1254 { | |
1255 std::ostringstream buf; | |
1256 fh->print_raw (buf); | |
1257 m.assign ("function", buf.str ()); | |
1258 | |
1259 m.assign ("type", "anonymous"); | |
1260 } | |
1261 else | |
1262 { | |
1263 m.assign ("function", fh_nm); | |
4343 | 1264 |
6625 | 1265 if (fcn->is_nested_function ()) |
1266 { | |
1267 m.assign ("type", "subfunction"); | |
1268 Cell parentage (dim_vector (1, 2)); | |
1269 parentage.elem(0) = fh_nm; | |
1270 parentage.elem(1) = fcn->parent_fcn_name (); | |
1271 m.assign ("parentage", parentage); | |
1272 } | |
1273 else | |
1274 m.assign ("type", "simple"); | |
1275 } | |
4933 | 1276 |
1277 std::string nm = fcn->fcn_file_name (); | |
4343 | 1278 |
4933 | 1279 if (nm.empty ()) |
4935 | 1280 { |
1281 if (fh_nm == "@<anonymous>") | |
6625 | 1282 { |
1283 m.assign ("file", ""); | |
1284 | |
1285 octave_user_function *fu = fh->user_function_value (); | |
1286 | |
7336 | 1287 std::list<symbol_table::symbol_record> vars |
1288 = symbol_table::all_variables (fu->scope ()); | |
1289 | |
1290 size_t varlen = vars.size (); | |
6625 | 1291 |
1292 if (varlen > 0) | |
1293 { | |
1294 Octave_map ws; | |
7336 | 1295 for (std::list<symbol_table::symbol_record>::const_iterator p = vars.begin (); |
1296 p != vars.end (); p++) | |
6625 | 1297 { |
7336 | 1298 ws.assign (p->name (), p->varval ()); |
6625 | 1299 } |
1300 | |
1301 m.assign ("workspace", ws); | |
1302 } | |
1303 } | |
5313 | 1304 else if (fcn->is_user_function ()) |
6625 | 1305 { |
1306 octave_user_function *fu = fh->user_function_value (); | |
1307 m.assign ("file", fu->fcn_file_name ()); | |
1308 } | |
4935 | 1309 else |
6625 | 1310 m.assign ("file", ""); |
4935 | 1311 } |
4343 | 1312 else |
4933 | 1313 m.assign ("file", nm); |
1314 | |
1315 retval = m; | |
4343 | 1316 } |
1317 else | |
4933 | 1318 error ("functions: invalid function handle object"); |
4343 | 1319 } |
1320 else | |
4933 | 1321 error ("functions: argument must be a function handle object"); |
4343 | 1322 } |
1323 else | |
5823 | 1324 print_usage (); |
4343 | 1325 |
1326 return retval; | |
1327 } | |
1328 | |
4933 | 1329 DEFUN (func2str, args, , |
4343 | 1330 "-*- texinfo -*-\n\ |
4933 | 1331 @deftypefn {Built-in Function} {} func2str (@var{fcn_handle})\n\ |
1332 Return a string containing the name of the function referenced by\n\ | |
1333 the function handle @var{fcn_handle}.\n\ | |
1334 @end deftypefn") | |
4343 | 1335 { |
1336 octave_value retval; | |
1337 | |
4933 | 1338 if (args.length () == 1) |
4930 | 1339 { |
4933 | 1340 octave_fcn_handle *fh = args(0).fcn_handle_value (); |
4930 | 1341 |
4933 | 1342 if (! error_state && fh) |
1343 { | |
1344 std::string fh_nm = fh->fcn_name (); | |
6416 | 1345 |
1346 if (fh_nm == "@<anonymous>") | |
1347 { | |
1348 std::ostringstream buf; | |
1349 | |
1350 fh->print_raw (buf); | |
1351 | |
1352 retval = buf.str (); | |
1353 } | |
1354 else | |
1355 retval = fh_nm; | |
4933 | 1356 } |
4343 | 1357 else |
4933 | 1358 error ("func2str: expecting valid function handle as first argument"); |
4343 | 1359 } |
1360 else | |
5823 | 1361 print_usage (); |
4343 | 1362 |
1363 return retval; | |
1364 } | |
1365 | |
4933 | 1366 DEFUN (str2func, args, , |
4343 | 1367 "-*- texinfo -*-\n\ |
4933 | 1368 @deftypefn {Built-in Function} {} str2func (@var{fcn_name})\n\ |
1369 Return a function handle constructed from the string @var{fcn_name}.\n\ | |
1370 @end deftypefn") | |
4343 | 1371 { |
1372 octave_value retval; | |
1373 | |
4933 | 1374 if (args.length () == 1) |
4343 | 1375 { |
4933 | 1376 std::string nm = args(0).string_value (); |
4343 | 1377 |
4933 | 1378 if (! error_state) |
1379 retval = make_fcn_handle (nm); | |
4343 | 1380 else |
4933 | 1381 error ("str2func: expecting string as first argument"); |
4343 | 1382 } |
1383 else | |
5823 | 1384 print_usage (); |
4343 | 1385 |
1386 return retval; | |
1387 } | |
1388 | |
1389 /* | |
1390 ;;; Local Variables: *** | |
1391 ;;; mode: C++ *** | |
1392 ;;; End: *** | |
1393 */ |