comparison src/ov-fcn-handle.cc @ 6625:5d02dfacfc9e

[project @ 2007-05-16 08:49:47 by dbateman]
author dbateman
date Wed, 16 May 2007 08:49:48 +0000
parents 89ed13fec6fe
children af16354ea09c
comparison
equal deleted inserted replaced
6624:0d69a50fc5a9 6625:5d02dfacfc9e
44 #include "pt-cmd.h" 44 #include "pt-cmd.h"
45 #include "pt-exp.h" 45 #include "pt-exp.h"
46 #include "pt-assign.h" 46 #include "pt-assign.h"
47 #include "variables.h" 47 #include "variables.h"
48 #include "parse.h" 48 #include "parse.h"
49 #include "unwind-prot.h"
50 #include "defaults.h"
51 #include "file-stat.h"
52 #include "load-path.h"
53 #include "oct-env.h"
49 54
50 #include "byte-swap.h" 55 #include "byte-swap.h"
51 #include "ls-oct-ascii.h" 56 #include "ls-oct-ascii.h"
57 #include "ls-oct-binary.h"
52 #include "ls-hdf5.h" 58 #include "ls-hdf5.h"
53 #include "ls-utils.h" 59 #include "ls-utils.h"
54 60
55 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle); 61 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle);
56 62
142 148
143 return retval; 149 return retval;
144 } 150 }
145 151
146 bool 152 bool
147 octave_fcn_handle::save_ascii (std::ostream& os, bool&) 153 octave_fcn_handle::set_fcn (const std::string &octaveroot,
154 const std::string& fpath)
148 { 155 {
149 os << nm << "\n"; 156 bool success = true;
150 157
158 if (octaveroot.length () != 0 &&
159 fpath.length () >= octaveroot.length () &&
160 fpath.substr (0, octaveroot.length ()) == octaveroot &&
161 OCTAVE_EXEC_PREFIX != octaveroot)
162 {
163 // First check if just replacing matlabroot is enough
164 std::string str = OCTAVE_EXEC_PREFIX +
165 fpath.substr (octaveroot.length ());
166 file_stat fs (str);
167
168 if (fs.exists ())
169 {
170 symbol_record *sr = fbi_sym_tab->lookup (str, true);
171
172 if (sr)
173 {
174 load_fcn_from_file (sr, false);
175
176 fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
177
178 // The next two lines are needed to force the
179 // definition of the function back to the one
180 // that is on the user path.
181 sr = fbi_sym_tab->lookup (nm, true);
182
183 load_fcn_from_file (sr, false);
184
185 }
186 else
187 {
188 error ("function handle points to non-existent function");
189 success = false;
190 }
191 }
192 else
193 {
194 // Next just search for it anywhere in the system path
195 string_vector names(3);
196 names(0) = nm + ".oct";
197 names(1) = nm + ".mex";
198 names(2) = nm + ".m";
199
200 dir_path p (octave_system_path ());
201
202 str = octave_env::make_absolute
203 (p.find_first_of (names), octave_env::getcwd ());
204
205 symbol_record *sr = fbi_sym_tab->lookup (str, true);
206
207 if (sr)
208 {
209 load_fcn_from_file (sr, false);
210
211 fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
212
213 // The next two lines are needed to force the
214 // definition of the function back to the one
215 // that is on the user path.
216 sr = fbi_sym_tab->lookup (nm, true);
217
218 load_fcn_from_file (sr, false);
219 }
220 else
221 {
222 error ("function handle points to non-existent function");
223 success = false;
224 }
225 }
226 }
227 else
228 {
229 if (fpath.length () > 0)
230 {
231 symbol_record *sr = fbi_sym_tab->lookup (fpath, true);
232
233 if (sr)
234 {
235 load_fcn_from_file (sr, false);
236
237 fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
238
239 sr = fbi_sym_tab->lookup (nm, true);
240
241 load_fcn_from_file (sr, false);
242 }
243 else
244 {
245 error ("function handle points to non-existent function");
246 success = false;
247 }
248 }
249 else
250 {
251 fcn = lookup_function (nm);
252 if (! fcn.is_function ())
253 {
254 error ("function handle points to non-existent function");
255 success = false;
256 }
257 }
258 }
259
260 return success;
261 }
262
263 bool
264 octave_fcn_handle::save_ascii (std::ostream& os, bool& infnan_warned)
265 {
151 if (nm == "@<anonymous>") 266 if (nm == "@<anonymous>")
152 { 267 {
268 os << nm << "\n";
269
153 print_raw (os, true); 270 print_raw (os, true);
154 os << "\n"; 271 os << "\n";
272
273 if (fcn.is_undefined())
274 return false;
275
276 octave_user_function *f = fcn.user_function_value ();
277
278 Array<symbol_record *> vars = f->sym_tab()->symbol_list();
279 octave_idx_type varlen = vars.length();
280
281 // Exclude undefined values like __retval__
282 for (octave_idx_type i = 0; i < vars.length(); i++)
283 {
284 if (! vars(i)->is_defined ())
285 varlen--;
286 }
287
288 if (varlen > 0)
289 {
290 os << "# length: " << varlen << "\n";
291
292 for (octave_idx_type i = 0; i < vars.length(); i++)
293 {
294 if (vars(i)->is_defined () &&
295 ! save_ascii_data (os, vars(i)->def(), vars(i)->name(),
296 infnan_warned, false, 0))
297 return os;
298 }
299 }
300 }
301 else
302 {
303 os << "# octaveroot: " << OCTAVE_EXEC_PREFIX << "\n";
304 os << "# path: " << user_function_value ()-> fcn_file_name () << "\n";
305 os << nm << "\n";
155 } 306 }
156 307
157 return true; 308 return true;
158 } 309 }
159 310
160 bool 311 bool
161 octave_fcn_handle::load_ascii (std::istream& is) 312 octave_fcn_handle::load_ascii (std::istream& is)
162 { 313 {
314 bool success = true;
315
316 std::streampos pos = is.tellg ();
317 std::string octaveroot = extract_keyword (is, "octaveroot", true);
318 if (octaveroot.length() == 0)
319 {
320 is.seekg (pos);
321 is.clear ();
322 }
323 pos = is.tellg ();
324 std::string fpath = extract_keyword (is, "path", true);
325 if (fpath.length() == 0)
326 {
327 is.seekg (pos);
328 is.clear ();
329 }
330
163 is >> nm; 331 is >> nm;
164 332
165 if (nm == "@<anonymous>") 333 if (nm == "@<anonymous>")
166 { 334 {
335 octave_idx_type len = 0;
167 char c; 336 char c;
168 std::ostringstream buf; 337 std::ostringstream buf;
169 338
170 // Skip preceeding newline(s). 339 // Skip preceeding newline(s).
171 while (is.get (c) && c == '\n') 340 while (is.get (c) && c == '\n')
185 break; 354 break;
186 buf << c; 355 buf << c;
187 } 356 }
188 } 357 }
189 358
190 int parse_status; 359 pos = is.tellg ();
191 octave_value anon_fcn_handle = eval_string (buf.str (), true, 360 symbol_table *local_sym_tab = 0;
192 parse_status); 361
193 362 if (extract_keyword (is, "length", len, true) && len >= 0)
194 if (parse_status == 0) 363 {
195 { 364 if (len > 0)
196 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); 365 {
197 if (fh) 366 octave_idx_type nlen = len;
198 fcn = fh->fcn; 367 if (nlen % 2)
368 nlen++;
369
370 local_sym_tab = new symbol_table (((nlen + 1) & ~1) , "LOCAL");
371
372 for (octave_idx_type i = 0; i < len; i++)
373 {
374 octave_value t2;
375 bool dummy;
376
377 std::string name
378 = read_ascii_data (is, std::string (), dummy, t2, i);
379
380 if (!is)
381 {
382 error ("load: failed to load anonymous function handle");
383 break;
384 }
385
386 symbol_record *sr = local_sym_tab->lookup (name, true);
387
388 if (sr)
389 sr->define (t2);
390 else
391 {
392 error ("load: failed to load anonymous function handle");
393 success = false;
394 break;
395 }
396 }
397 }
398 }
399 else
400 {
401 is.seekg (pos);
402 is.clear ();
403 }
404
405 if (is && success)
406 {
407 unwind_protect::begin_frame ("anon_ascii_load");
408 unwind_protect_ptr (curr_sym_tab);
409
410 if (local_sym_tab)
411 curr_sym_tab = local_sym_tab;
412
413 int parse_status;
414 octave_value anon_fcn_handle =
415 eval_string (buf.str (), true, parse_status);
416
417 if (parse_status == 0)
418 {
419 octave_fcn_handle *fh =
420 anon_fcn_handle.fcn_handle_value ();
421 if (fh)
422 fcn = fh->fcn;
423 else
424 success = false;
425 }
199 else 426 else
200 return false; 427 success = false;
428
429 unwind_protect::run_frame ("anon_ascii_load");
201 } 430 }
202 else 431 else
432 success = false;
433
434 if (local_sym_tab)
435 delete local_sym_tab;
436 }
437 else
438 success = set_fcn (octaveroot, fpath);
439
440 return success;
441 }
442
443 /*
444
445 %!test
446 %! a = 2;
447 %! f = @(x) a + x;
448 %! g = @(x) 2 * x;
449 %! h = @log2;
450 %! f2 = f;
451 %! g2 = g;
452 %! h2 = h;
453 %! nm = tmpnam();
454 %! unwind_protect
455 %! save ("-text", nm, "f2", "g2", "h2");
456 %! clear f2 g2 h2
457 %! load (nm);
458 %! assert (f(2),f2(2));
459 %! assert (g(2),g2(2));
460 %! assert (g(3),g2(3));
461 %! unlink (nm);
462 %! save ("-text", nm, "f2", "g2", "h2");
463 %! unwind_protect_cleanup
464 %! unlink (nm);
465 %! end_unwind_protect
466
467 */
468
469 bool
470 octave_fcn_handle::save_binary (std::ostream& os, bool& save_as_floats)
471 {
472 if (nm == "@<anonymous>")
473 {
474 std::ostringstream nmbuf;
475
476 if (fcn.is_undefined())
203 return false; 477 return false;
204 } 478
205 else 479 octave_user_function *f = fcn.user_function_value ();
206 { 480
207 fcn = lookup_function (nm); 481 Array<symbol_record *> vars = f->sym_tab()->symbol_list();
208 if (! fcn.is_function ()) 482 octave_idx_type varlen = vars.length();
209 { 483
210 error ("function handle points to non-existent function"); 484 // Exclude undefined values like __retval__
211 return false; 485 for (octave_idx_type i = 0; i < vars.length(); i++)
212 } 486 {
213 } 487 if (! vars(i)->is_defined ())
214 488 varlen--;
215 return true; 489 }
216 } 490
217 491 if (varlen > 0)
218 bool 492 nmbuf << nm << " " << varlen;
219 octave_fcn_handle::save_binary (std::ostream& os, bool&) 493 else
220 { 494 nmbuf << nm;
221 int32_t tmp = nm.length (); 495
222 os.write (reinterpret_cast<char *> (&tmp), 4); 496 std::string buf_str = nmbuf.str();
223 os.write (nm.c_str (), nm.length ()); 497 int32_t tmp = buf_str.length ();
224 if (nm == "@<anonymous>") 498 os.write (reinterpret_cast<char *> (&tmp), 4);
225 { 499 os.write (buf_str.c_str (), buf_str.length ());
500
226 std::ostringstream buf; 501 std::ostringstream buf;
227 print_raw (buf, true); 502 print_raw (buf, true);
228 std::string stmp = buf.str (); 503 std::string stmp = buf.str ();
229 tmp = stmp.length (); 504 tmp = stmp.length ();
230 os.write (reinterpret_cast<char *> (&tmp), 4); 505 os.write (reinterpret_cast<char *> (&tmp), 4);
231 os.write (stmp.c_str (), stmp.length ()); 506 os.write (stmp.c_str (), stmp.length ());
507
508 if (varlen > 0)
509 {
510 for (octave_idx_type i = 0; i < vars.length(); i++)
511 {
512 if (vars(i)->is_defined () &&
513 ! save_binary_data (os, vars(i)->def(), vars(i)->name(),
514 "", 0, save_as_floats))
515 return os;
516 }
517 }
518 }
519 else
520 {
521 std::ostringstream nmbuf;
522
523 nmbuf << nm << "\n" << OCTAVE_EXEC_PREFIX << "\n"
524 << user_function_value ()-> fcn_file_name () ;
525
526 std::string buf_str = nmbuf.str ();
527 int32_t tmp = buf_str.length ();
528 os.write (reinterpret_cast<char *> (&tmp), 4);
529 os.write (buf_str.c_str (), buf_str.length ());
232 } 530 }
233 return true; 531 return true;
234 } 532 }
235 533
236 bool 534 bool
237 octave_fcn_handle::load_binary (std::istream& is, bool swap, 535 octave_fcn_handle::load_binary (std::istream& is, bool swap,
238 oct_mach_info::float_format) 536 oct_mach_info::float_format fmt)
239 { 537 {
538 bool success = true;
240 int32_t tmp; 539 int32_t tmp;
241 if (! is.read (reinterpret_cast<char *> (&tmp), 4)) 540 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
242 return false; 541 return false;
243 if (swap) 542 if (swap)
244 swap_bytes<4> (&tmp); 543 swap_bytes<4> (&tmp);
248 nm = std::string (ctmp1); 547 nm = std::string (ctmp1);
249 548
250 if (! is) 549 if (! is)
251 return false; 550 return false;
252 551
253 if (nm == "@<anonymous>") 552 if (nm.length() >= 12 && nm.substr (0, 12) == "@<anonymous>")
254 { 553 {
554 octave_idx_type len = 0;
555
556 if (nm.length() > 12)
557 {
558 std::istringstream nm_is (nm.substr(12));
559 nm_is >> len;
560 nm = nm.substr(0,12);
561 }
562
255 if (! is.read (reinterpret_cast<char *> (&tmp), 4)) 563 if (! is.read (reinterpret_cast<char *> (&tmp), 4))
256 return false; 564 return false;
257 if (swap) 565 if (swap)
258 swap_bytes<4> (&tmp); 566 swap_bytes<4> (&tmp);
259 567
260 OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1); 568 OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
261 is.read (ctmp2, tmp); 569 is.read (ctmp2, tmp);
262 570
263 int parse_status; 571 symbol_table *local_sym_tab = 0;
264 octave_value anon_fcn_handle = eval_string (ctmp2, true, parse_status); 572 if (len > 0)
265 573 {
266 if (parse_status == 0) 574 octave_idx_type nlen = len;
267 { 575 if (nlen % 2)
268 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); 576 nlen++;
269 if (fh) 577
270 fcn = fh->fcn; 578 local_sym_tab = new symbol_table (nlen, "LOCAL");
579
580 for (octave_idx_type i = 0; i < len; i++)
581 {
582 octave_value t2;
583 bool dummy;
584 std::string doc;
585
586 std::string name =
587 read_binary_data (is, swap, fmt, std::string (),
588 dummy, t2, doc);
589
590 if (!is)
591 {
592 error ("load: failed to load anonymous function handle");
593 break;
594 }
595
596 symbol_record *sr = local_sym_tab->lookup (name, true);
597
598 if (sr)
599 {
600 sr->define (t2);
601 sr->document (doc);
602 }
603 else
604 {
605 error ("load: failed to load anonymous function handle");
606 success = false;
607 break;
608 }
609 }
610 }
611
612 if (is && success)
613 {
614 unwind_protect::begin_frame ("anon_binary_load");
615 unwind_protect_ptr (curr_sym_tab);
616
617 if (local_sym_tab)
618 curr_sym_tab = local_sym_tab;
619
620 int parse_status;
621 octave_value anon_fcn_handle =
622 eval_string (ctmp2, true, parse_status);
623
624 if (parse_status == 0)
625 {
626 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
627 if (fh)
628 fcn = fh->fcn;
629 else
630 success = false;
631 }
271 else 632 else
272 return false; 633 success = false;
273 } 634
274 else 635 unwind_protect::run_frame ("anon_binary_load");
275 return false; 636 }
637
638 if (local_sym_tab)
639 delete local_sym_tab;
276 } 640 }
277 else 641 else
278 { 642 {
279 fcn = lookup_function (nm); 643 std::string octaveroot;
280 if (! fcn.is_function ()) 644 std::string fpath;
281 { 645
282 error ("function handle points to non-existent function"); 646 if (nm.find_first_of ("\n") != NPOS)
283 return false; 647 {
284 } 648 size_t pos1 = nm.find_first_of ("\n");
285 } 649 size_t pos2 = nm.find_first_of ("\n", pos1 + 1);
286 return true; 650 octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1);
651 fpath = nm.substr (pos2 + 1);
652 nm = nm.substr (0, pos1);
653 }
654
655 success = set_fcn (octaveroot, fpath);
656 }
657
658 return success;
287 } 659 }
660
661 /*
662
663 %!test
664 %! a = 2;
665 %! f = @(x) a + x;
666 %! g = @(x) 2 * x;
667 %! h = @log2;
668 %! f2 = f;
669 %! g2 = g;
670 %! h2 = h;
671 %! nm = tmpnam();
672 %! unwind_protect
673 %! save ("-binary", nm, "f2", "g2", "h2");
674 %! clear f2 g2 h2
675 %! load (nm);
676 %! assert (f(2),f2(2));
677 %! assert (g(2),g2(2));
678 %! assert (g(3),g2(3));
679 %! unlink (nm);
680 %! save ("-binary", nm, "f2", "g2", "h2");
681 %! unwind_protect_cleanup
682 %! unlink (nm);
683 %! end_unwind_protect
684
685 */
288 686
289 #if defined (HAVE_HDF5) 687 #if defined (HAVE_HDF5)
290 bool 688 bool
291 octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name, 689 octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name,
292 bool /* save_as_floats */) 690 bool save_as_floats)
293 { 691 {
294 hid_t group_hid = -1; 692 hid_t group_hid = -1;
295 group_hid = H5Gcreate (loc_id, name, 0); 693 group_hid = H5Gcreate (loc_id, name, 0);
296 if (group_hid < 0 ) return false; 694 if (group_hid < 0 ) return false;
297 695
353 H5Gclose (group_hid); 751 H5Gclose (group_hid);
354 return false; 752 return false;
355 } 753 }
356 754
357 H5Dclose (data_hid); 755 H5Dclose (data_hid);
756
757 octave_user_function *f = fcn.user_function_value ();
758 Array<symbol_record *> vars = f->sym_tab()->symbol_list();
759 octave_idx_type varlen = vars.length();
760
761 // Exclude undefined values like __retval__
762 for (octave_idx_type i = 0; i < vars.length(); i++)
763 {
764 if (! vars(i)->is_defined ())
765 varlen--;
766 }
767
768 if (varlen > 0)
769 {
770 hid_t as_id = H5Screate (H5S_SCALAR);
771
772 if (as_id >= 0)
773 {
774 hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
775 H5T_NATIVE_IDX, as_id, H5P_DEFAULT);
776
777 if (a_id >= 0)
778 {
779 retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0);
780
781 H5Aclose (a_id);
782 }
783 else
784 retval = false;
785
786 H5Sclose (as_id);
787 }
788 else
789 retval = false;
790
791 data_hid = H5Gcreate (group_hid, "symbol table", 0);
792 if (data_hid < 0)
793 {
794 H5Sclose (space_hid);
795 H5Tclose (type_hid);
796 H5Gclose (group_hid);
797 return false;
798 }
799
800 for (octave_idx_type i = 0; i < vars.length(); i++)
801 {
802 if (vars(i)->is_defined () &&
803 ! add_hdf5_data (data_hid, vars(i)->def(), vars(i)->name(),
804 "", false, save_as_floats))
805 break;
806 }
807 H5Gclose (data_hid);
808 }
809 }
810 else
811 {
812 std::string octaveroot = OCTAVE_EXEC_PREFIX;
813 std::string fpath = user_function_value ()-> fcn_file_name ();
814
815 H5Sclose (space_hid);
816 hdims[0] = 1;
817 hdims[1] = octaveroot.length ();
818 space_hid = H5Screate_simple (0 , hdims, 0);
819 if (space_hid < 0)
820 {
821 H5Tclose (type_hid);
822 H5Gclose (group_hid);
823 return false;
824 }
825
826 H5Tclose (type_hid);
827 type_hid = H5Tcopy (H5T_C_S1);
828 H5Tset_size (type_hid, octaveroot.length () + 1);
829
830 hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
831 type_hid, space_hid, H5P_DEFAULT);
832
833 if (a_id >= 0)
834 {
835 retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0);
836
837 H5Aclose (a_id);
838 }
839 else
840 retval = false;
841
842 H5Sclose (space_hid);
843 hdims[0] = 1;
844 hdims[1] = fpath.length ();
845 space_hid = H5Screate_simple (0 , hdims, 0);
846 if (space_hid < 0)
847 {
848 H5Tclose (type_hid);
849 H5Gclose (group_hid);
850 return false;
851 }
852
853 H5Tclose (type_hid);
854 type_hid = H5Tcopy (H5T_C_S1);
855 H5Tset_size (type_hid, fpath.length () + 1);
856
857 a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, H5P_DEFAULT);
858
859 if (a_id >= 0)
860 {
861 retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0);
862
863 H5Aclose (a_id);
864 }
865 else
866 retval = false;
358 } 867 }
359 868
360 H5Sclose (space_hid); 869 H5Sclose (space_hid);
361 H5Tclose (type_hid); 870 H5Tclose (type_hid);
362 H5Gclose (group_hid); 871 H5Gclose (group_hid);
364 return retval; 873 return retval;
365 } 874 }
366 875
367 bool 876 bool
368 octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name, 877 octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name,
369 bool /* have_h5giterate_bug */) 878 bool have_h5giterate_bug)
370 { 879 {
371 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id; 880 hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
372 hsize_t rank; 881 hsize_t rank;
373 int slen; 882 int slen;
883 bool success = true;
374 884
375 group_hid = H5Gopen (loc_id, name); 885 group_hid = H5Gopen (loc_id, name);
376 if (group_hid < 0 ) return false; 886 if (group_hid < 0 ) return false;
377 887
378 data_hid = H5Dopen (group_hid, "nm"); 888 data_hid = H5Dopen (group_hid, "nm");
488 H5Tclose (type_hid); 998 H5Tclose (type_hid);
489 H5Gclose (group_hid); 999 H5Gclose (group_hid);
490 return false; 1000 return false;
491 } 1001 }
492 H5Dclose (data_hid); 1002 H5Dclose (data_hid);
1003
1004 symbol_table *local_sym_tab = 0;
1005 octave_idx_type len = 0;
1006
1007 // we have to pull some shenanigans here to make sure
1008 // HDF5 doesn't print out all sorts of error messages if we
1009 // call H5Aopen for a non-existing attribute
1010
1011 H5E_auto_t err_func;
1012 void *err_func_data;
1013
1014 // turn off error reporting temporarily, but save the error
1015 // reporting function:
1016 H5Eget_auto (&err_func, &err_func_data);
1017 H5Eset_auto (0, 0);
1018
1019 hid_t attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE");
1020
1021 if (attr_id >= 0)
1022 {
1023 if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0)
1024 success = false;
1025
1026 H5Aclose (attr_id);
1027 }
1028
1029 // restore error reporting:
1030 H5Eset_auto (err_func, err_func_data);
1031
1032 if (len > 0 && success)
1033 {
1034 octave_idx_type nlen = len;
1035 if (nlen % 2)
1036 nlen++;
1037
1038 local_sym_tab = new symbol_table (nlen, "LOCAL");
1039
1040 #ifdef HAVE_H5GGET_NUM_OBJS
1041 hsize_t num_obj = 0;
1042 data_hid = H5Gopen (group_hid, "symbol table");
1043 H5Gget_num_objs (data_hid, &num_obj);
1044 H5Gclose (data_hid);
1045
1046 if (num_obj != static_cast<hsize_t>(len))
1047 {
1048 error ("load: failed to load anonymous function handle");
1049 success = false;
1050 }
1051 #endif
1052
1053 if (! error_state)
1054 {
1055 hdf5_callback_data dsub;
1056 int current_item = 0;
1057 for (octave_idx_type i = 0; i < len; i++)
1058 {
1059 if (H5Giterate (group_hid, "symbol table", &current_item,
1060 hdf5_read_next_data, &dsub) <= 0)
1061 {
1062 error ("load: failed to load anonymous function handle");
1063 success = false;
1064 break;
1065 }
1066
1067 if (have_h5giterate_bug)
1068 current_item++; // H5Giterate returns last index processed
1069
1070 symbol_record *sr = local_sym_tab->lookup (dsub.name, true);
1071
1072 if (sr)
1073 sr->define (dsub.tc);
1074 else
1075 {
1076 error ("load: failed to load anonymous function handle");
1077 success = false;
1078 break;
1079 }
1080 }
1081 }
1082 }
1083
493 H5Tclose (st_id); 1084 H5Tclose (st_id);
494 1085 H5Gclose (group_hid);
495 int parse_status; 1086
496 octave_value anon_fcn_handle = eval_string (fcn_tmp, true, parse_status); 1087 if (success)
497 1088 {
498 if (parse_status == 0) 1089 unwind_protect::begin_frame ("anon_hdf5_load");
499 { 1090 unwind_protect_ptr (curr_sym_tab);
500 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value (); 1091
501 if (fh) 1092 if (local_sym_tab)
502 fcn = fh->fcn; 1093 curr_sym_tab = local_sym_tab;
1094
1095 int parse_status;
1096 octave_value anon_fcn_handle =
1097 eval_string (fcn_tmp, true, parse_status);
1098
1099 if (parse_status == 0)
1100 {
1101 octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
1102 if (fh)
1103 fcn = fh->fcn;
1104 else
1105 success = false;
1106 }
503 else 1107 else
504 return false; 1108 success = false;
505 } 1109
506 else 1110 unwind_protect::run_frame ("anon_hdf5_load");
507 return false; 1111 }
1112
1113 if (local_sym_tab)
1114 delete local_sym_tab;
508 } 1115 }
509 else 1116 else
510 { 1117 {
511 fcn = lookup_function (nm); 1118 std::string octaveroot;
512 if (! fcn.is_function ()) 1119 std::string fpath;
513 { 1120
514 error ("function handle points to non-existent function"); 1121 // we have to pull some shenanigans here to make sure
515 return false; 1122 // HDF5 doesn't print out all sorts of error messages if we
516 } 1123 // call H5Aopen for a non-existing attribute
517 } 1124
518 1125 H5E_auto_t err_func;
519 return true; 1126 void *err_func_data;
1127
1128 // turn off error reporting temporarily, but save the error
1129 // reporting function:
1130 H5Eget_auto (&err_func, &err_func_data);
1131 H5Eset_auto (0, 0);
1132
1133 hid_t attr_id = H5Aopen_name (group_hid, "OCTAVEROOT");
1134 if (attr_id >= 0)
1135 {
1136 type_hid = H5Aget_type (attr_id);
1137 type_class_hid = H5Tget_class (type_hid);
1138
1139 if (type_class_hid != H5T_STRING)
1140 success = false;
1141 else
1142 {
1143 slen = H5Tget_size (type_hid);
1144 st_id = H5Tcopy (H5T_C_S1);
1145 H5Tset_size (st_id, slen);
1146 OCTAVE_LOCAL_BUFFER (char, root_tmp, slen);
1147
1148 if (H5Aread (attr_id, st_id, root_tmp) < 0)
1149 success = false;
1150 else
1151 octaveroot = root_tmp;
1152 }
1153
1154 H5Aclose (attr_id);
1155 }
1156
1157 attr_id = H5Aopen_name (group_hid, "FILE");
1158 if (attr_id >= 0)
1159 {
1160 type_hid = H5Aget_type (attr_id);
1161 type_class_hid = H5Tget_class (type_hid);
1162
1163 if (type_class_hid != H5T_STRING)
1164 success = false;
1165 else
1166 {
1167 slen = H5Tget_size (type_hid);
1168 st_id = H5Tcopy (H5T_C_S1);
1169 H5Tset_size (st_id, slen);
1170 OCTAVE_LOCAL_BUFFER (char, path_tmp, slen);
1171
1172 if (H5Aread (attr_id, st_id, path_tmp) < 0)
1173 success = false;
1174 else
1175 fpath = path_tmp;
1176 }
1177
1178 H5Aclose (attr_id);
1179 }
1180
1181 // restore error reporting:
1182 H5Eset_auto (err_func, err_func_data);
1183
1184 success = (success ? set_fcn (octaveroot, fpath) : success);
1185 }
1186
1187 return success;
520 } 1188 }
1189
1190 /*
1191
1192 %!test
1193 %! if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_HDF5")))
1194 %! a = 2;
1195 %! f = @(x) a + x;
1196 %! g = @(x) 2 * x;
1197 %! h = @log2;
1198 %! f2 = f;
1199 %! g2 = g;
1200 %! h2 = h;
1201 %! nm = tmpnam();
1202 %! unwind_protect
1203 %! save ("-hdf5", nm, "f2", "g2", "h2");
1204 %! clear f2 g2 h2
1205 %! load (nm);
1206 %! assert (f(2),f2(2));
1207 %! assert (g(2),g2(2));
1208 %! assert (g(3),g2(3));
1209 %! unlink (nm);
1210 %! save ("-hdf5", nm, "f2", "g2", "h2");
1211 %! unwind_protect_cleanup
1212 %! unlink (nm);
1213 %! end_unwind_protect
1214 %! endif
1215
1216 */
521 #endif 1217 #endif
522 1218
523 void 1219 void
524 octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const 1220 octave_fcn_handle::print (std::ostream& os, bool pr_as_read_syntax) const
525 { 1221 {
655 { 1351 {
656 Octave_map m; 1352 Octave_map m;
657 1353
658 std::string fh_nm = fh->fcn_name (); 1354 std::string fh_nm = fh->fcn_name ();
659 1355
660 m.assign ("function", fh_nm); 1356 if (fh_nm == "@<anonymous>")
661 1357 {
662 if (fcn->is_nested_function ()) 1358 std::ostringstream buf;
663 m.assign ("type", "subfunction"); 1359 fh->print_raw (buf);
1360 m.assign ("function", buf.str ());
1361
1362 m.assign ("type", "anonymous");
1363 }
664 else 1364 else
665 m.assign ("type", "simple"); 1365 {
1366 m.assign ("function", fh_nm);
1367
1368 if (fcn->is_nested_function ())
1369 {
1370 m.assign ("type", "subfunction");
1371 Cell parentage (dim_vector (1, 2));
1372 parentage.elem(0) = fh_nm;
1373 parentage.elem(1) = fcn->parent_fcn_name ();
1374 m.assign ("parentage", parentage);
1375 }
1376 else
1377 m.assign ("type", "simple");
1378 }
666 1379
667 std::string nm = fcn->fcn_file_name (); 1380 std::string nm = fcn->fcn_file_name ();
668 1381
669 if (nm.empty ()) 1382 if (nm.empty ())
670 { 1383 {
671 if (fh_nm == "@<anonymous>") 1384 if (fh_nm == "@<anonymous>")
672 m.assign ("file", "none"); 1385 {
1386 m.assign ("file", "");
1387
1388 octave_user_function *fu = fh->user_function_value ();
1389 Array <symbol_record *> vars =
1390 fu->sym_tab ()->symbol_list ();
1391 octave_idx_type varlen = vars.length ();
1392
1393 // Exclude undefined values like __retval__
1394 for (int i = 0; i < vars.length (); i++)
1395 {
1396 if (! vars (i)->is_defined ())
1397 varlen--;
1398 }
1399
1400 if (varlen > 0)
1401 {
1402 Octave_map ws;
1403 for (octave_idx_type i = 0; i < vars.length (); i++)
1404 {
1405 if (vars (i)->is_defined ())
1406 ws.assign (vars (i)->name (),
1407 vars (i)->def ());
1408 }
1409
1410 m.assign ("workspace", ws);
1411 }
1412 }
673 else if (fcn->is_user_function ()) 1413 else if (fcn->is_user_function ())
674 m.assign ("file", "command-line function"); 1414 {
1415 octave_user_function *fu = fh->user_function_value ();
1416 m.assign ("file", fu->fcn_file_name ());
1417 }
675 else 1418 else
676 m.assign ("file", "built-in function"); 1419 m.assign ("file", "");
677 } 1420 }
678 else 1421 else
679 m.assign ("file", nm); 1422 m.assign ("file", nm);
680 1423
681 retval = m; 1424 retval = m;