Mercurial > hg > octave-lyh
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", ¤t_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; |