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