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