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