File: | libinterp/corefcn/load-save.cc |
Location: | line 1618, column 7 |
Description: | Value stored to 'argc' during its initialization is never read |
1 | /* |
2 | |
3 | Copyright (C) 1994-2013 John W. Eaton |
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 |
9 | Free Software Foundation; either version 3 of the License, or (at your |
10 | option) any later version. |
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 |
18 | along with Octave; see the file COPYING. If not, see |
19 | <http://www.gnu.org/licenses/>. |
20 | |
21 | */ |
22 | |
23 | // Author: John W. Eaton. |
24 | // HDF5 support by Steven G. Johnson <stevenj@alum.mit.edu> |
25 | // Matlab v5 support by James R. Van Zandt <jrv@vanzandt.mv.com> |
26 | |
27 | #ifdef HAVE_CONFIG_H1 |
28 | #include <config.h> |
29 | #endif |
30 | |
31 | #include <cfloat> |
32 | #include <cstring> |
33 | #include <cctype> |
34 | |
35 | #include <fstream> |
36 | #include <iomanip> |
37 | #include <iostream> |
38 | #include <sstream> |
39 | #include <string> |
40 | |
41 | #include "strftime.h" |
42 | |
43 | #include "byte-swap.h" |
44 | #include "data-conv.h" |
45 | #include "file-ops.h" |
46 | #include "file-stat.h" |
47 | #include "glob-match.h" |
48 | #include "lo-mappers.h" |
49 | #include "mach-info.h" |
50 | #include "oct-env.h" |
51 | #include "oct-time.h" |
52 | #include "quit.h" |
53 | #include "str-vec.h" |
54 | #include "oct-locbuf.h" |
55 | |
56 | #include "Cell.h" |
57 | #include "defun.h" |
58 | #include "error.h" |
59 | #include "gripes.h" |
60 | #include "load-path.h" |
61 | #include "load-save.h" |
62 | #include "oct-obj.h" |
63 | #include "oct-map.h" |
64 | #include "ov-cell.h" |
65 | #include "pager.h" |
66 | #include "pt-exp.h" |
67 | #include "symtab.h" |
68 | #include "sysdep.h" |
69 | #include "unwind-prot.h" |
70 | #include "utils.h" |
71 | #include "variables.h" |
72 | #include "version.h" |
73 | #include "dMatrix.h" |
74 | |
75 | #include "ls-hdf5.h" |
76 | #include "ls-mat-ascii.h" |
77 | #include "ls-mat4.h" |
78 | #include "ls-mat5.h" |
79 | #include "ls-oct-ascii.h" |
80 | #include "ls-oct-binary.h" |
81 | |
82 | // Remove gnulib definitions, if any. |
83 | #ifdef close |
84 | #undef close |
85 | #endif |
86 | #ifdef open |
87 | #undef open |
88 | #endif |
89 | |
90 | #ifdef HAVE_ZLIB1 |
91 | #include "zfstream.h" |
92 | #endif |
93 | |
94 | // Write octave-workspace file if Octave crashes or is killed by a signal. |
95 | static bool Vcrash_dumps_octave_core = true; |
96 | |
97 | // The maximum amount of memory (in kilobytes) that we will attempt to |
98 | // write to the Octave core file. |
99 | static double Voctave_core_file_limit = -1.0; |
100 | |
101 | // The name of the Octave core file. |
102 | static std::string Voctave_core_file_name = "octave-workspace"; |
103 | |
104 | // The default output format. May be one of "binary", "text", |
105 | // "mat-binary", or "hdf5". |
106 | static std::string Vsave_default_options = "-text"; |
107 | |
108 | // The output format for Octave core files. |
109 | static std::string Voctave_core_file_options = "-binary"; |
110 | |
111 | static std::string |
112 | default_save_header_format (void) |
113 | { |
114 | return |
115 | std::string ("# Created by Octave " OCTAVE_VERSION"3.7.7+" |
116 | ", %a %b %d %H:%M:%S %Y %Z <") |
117 | + octave_env::get_user_name () |
118 | + std::string ("@") |
119 | + octave_env::get_host_name () |
120 | + std::string (">"); |
121 | } |
122 | |
123 | // The format string for the comment line at the top of text-format |
124 | // save files. Passed to strftime. Should begin with '#' and contain |
125 | // no newline characters. |
126 | static std::string Vsave_header_format_string = default_save_header_format (); |
127 | |
128 | static void |
129 | gripe_file_open (const std::string& fcn, const std::string& file) |
130 | { |
131 | if (fcn == "load") |
132 | error ("%s: unable to open input file '%s'", fcn.c_str (), file.c_str ()); |
133 | else if (fcn == "save") |
134 | error ("%s: unable to open output file '%s'", fcn.c_str (), file.c_str ()); |
135 | else |
136 | error ("%s: unable to open file '%s'", fcn.c_str (), file.c_str ()); |
137 | } |
138 | |
139 | // Install a variable with name NAME and the value VAL in the |
140 | // symbol table. If GLOBAL is TRUE, make the variable global. |
141 | |
142 | static void |
143 | install_loaded_variable (const std::string& name, |
144 | const octave_value& val, |
145 | bool global, const std::string& /*doc*/) |
146 | { |
147 | if (global) |
148 | { |
149 | symbol_table::clear (name); |
150 | symbol_table::mark_global (name); |
151 | symbol_table::global_assign (name, val); |
152 | } |
153 | else |
154 | symbol_table::assign (name, val); |
155 | } |
156 | |
157 | // Return TRUE if NAME matches one of the given globbing PATTERNS. |
158 | |
159 | static bool |
160 | matches_patterns (const string_vector& patterns, int pat_idx, |
161 | int num_pat, const std::string& name) |
162 | { |
163 | for (int i = pat_idx; i < num_pat; i++) |
164 | { |
165 | glob_match pattern (patterns[i]); |
166 | |
167 | if (pattern.match (name)) |
168 | return true; |
169 | } |
170 | |
171 | return false; |
172 | } |
173 | |
174 | int |
175 | read_binary_file_header (std::istream& is, bool& swap, |
176 | oct_mach_info::float_format& flt_fmt, bool quiet) |
177 | { |
178 | const int magic_len = 10; |
179 | char magic[magic_len+1]; |
180 | is.read (magic, magic_len); |
181 | magic[magic_len] = '\0'; |
182 | |
183 | if (strncmp (magic, "Octave-1-L", magic_len) == 0) |
184 | swap = oct_mach_info::words_big_endian (); |
185 | else if (strncmp (magic, "Octave-1-B", magic_len) == 0) |
186 | swap = ! oct_mach_info::words_big_endian (); |
187 | else |
188 | { |
189 | if (! quiet) |
190 | error ("load: unable to read read binary file"); |
191 | return -1; |
192 | } |
193 | |
194 | char tmp = 0; |
195 | is.read (&tmp, 1); |
196 | |
197 | flt_fmt = mopt_digit_to_float_format (tmp); |
198 | |
199 | if (flt_fmt == oct_mach_info::flt_fmt_unknown) |
200 | { |
201 | if (! quiet) |
202 | error ("load: unrecognized binary format!"); |
203 | |
204 | return -1; |
205 | } |
206 | |
207 | return 0; |
208 | } |
209 | |
210 | #ifdef HAVE_ZLIB1 |
211 | static bool |
212 | check_gzip_magic (const std::string& fname) |
213 | { |
214 | bool retval = false; |
215 | std::ifstream file (fname.c_str ()); |
216 | OCTAVE_LOCAL_BUFFER (unsigned char, magic, 2)octave_local_buffer<unsigned char> _buffer_magic (2); unsigned char *magic = _buffer_magic; |
217 | |
218 | if (file.read (reinterpret_cast<char *> (magic), 2) && magic[0] == 0x1f && |
219 | magic[1] == 0x8b) |
220 | retval = true; |
221 | |
222 | file.close (); |
223 | return retval; |
224 | } |
225 | #endif |
226 | |
227 | static load_save_format |
228 | get_file_format (std::istream& file, const std::string& filename) |
229 | { |
230 | load_save_format retval = LS_UNKNOWN; |
231 | |
232 | oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown; |
233 | |
234 | bool swap = false; |
235 | |
236 | if (read_binary_file_header (file, swap, flt_fmt, true) == 0) |
237 | retval = LS_BINARY; |
238 | else |
239 | { |
240 | file.clear (); |
241 | file.seekg (0, std::ios::beg); |
242 | |
243 | int32_t mopt, nr, nc, imag, len; |
244 | |
245 | int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, |
246 | true); |
247 | |
248 | if (! err) |
249 | retval = LS_MAT_BINARY; |
250 | else |
251 | { |
252 | file.clear (); |
253 | file.seekg (0, std::ios::beg); |
254 | |
255 | err = read_mat5_binary_file_header (file, swap, true, filename); |
256 | |
257 | if (! err) |
258 | { |
259 | file.clear (); |
260 | file.seekg (0, std::ios::beg); |
261 | retval = LS_MAT5_BINARY; |
262 | } |
263 | else |
264 | { |
265 | file.clear (); |
266 | file.seekg (0, std::ios::beg); |
267 | |
268 | std::string tmp = extract_keyword (file, "name"); |
269 | |
270 | if (! tmp.empty ()) |
271 | retval = LS_ASCII; |
272 | else |
273 | { |
274 | file.clear (); |
275 | file.seekg (0, std::ios::beg); |
276 | |
277 | // FIXME: looks_like_mat_ascii_file does not check to see |
278 | // whether the file contains numbers. It just skips comments |
279 | // and checks for the same number of words on each line. We |
280 | // may need a better check here. The best way to do that |
281 | // might be just to try to read the file and see if it works. |
282 | |
283 | if (looks_like_mat_ascii_file (file, filename)) |
284 | retval = LS_MAT_ASCII; |
285 | } |
286 | } |
287 | } |
288 | } |
289 | |
290 | return retval; |
291 | } |
292 | |
293 | static load_save_format |
294 | get_file_format (const std::string& fname, const std::string& orig_fname, |
295 | bool &use_zlib, bool quiet = false) |
296 | { |
297 | load_save_format retval = LS_UNKNOWN; |
298 | |
299 | #ifdef HAVE_HDF51 |
300 | // check this before we open the file |
301 | if (H5Fis_hdf5 (fname.c_str ()) > 0) |
302 | return LS_HDF5; |
303 | #endif /* HAVE_HDF5 */ |
304 | |
305 | #ifdef HAVE_ZLIB1 |
306 | use_zlib = check_gzip_magic (fname); |
307 | #else |
308 | use_zlib = false; |
309 | #endif |
310 | |
311 | if (! use_zlib) |
312 | { |
313 | std::ifstream file (fname.c_str ()); |
314 | if (file) |
315 | { |
316 | retval = get_file_format (file, orig_fname); |
317 | file.close (); |
318 | } |
319 | else if (! quiet) |
320 | gripe_file_open ("load", orig_fname); |
321 | } |
322 | #ifdef HAVE_ZLIB1 |
323 | else |
324 | { |
325 | gzifstream gzfile (fname.c_str ()); |
326 | if (gzfile) |
327 | { |
328 | retval = get_file_format (gzfile, orig_fname); |
329 | gzfile.close (); |
330 | } |
331 | else if (! quiet) |
332 | gripe_file_open ("load", orig_fname); |
333 | } |
334 | #endif |
335 | |
336 | return retval; |
337 | } |
338 | |
339 | octave_value |
340 | do_load (std::istream& stream, const std::string& orig_fname, |
341 | load_save_format format, oct_mach_info::float_format flt_fmt, |
342 | bool list_only, bool swap, bool verbose, |
343 | const string_vector& argv, int argv_idx, int argc, int nargout) |
344 | { |
345 | octave_value retval; |
346 | |
347 | octave_scalar_map retstruct; |
348 | |
349 | std::ostringstream output_buf; |
350 | std::list<std::string> symbol_names; |
351 | |
352 | octave_idx_type count = 0; |
353 | |
354 | for (;;) |
355 | { |
356 | bool global = false; |
357 | octave_value tc; |
358 | |
359 | std::string name; |
360 | std::string doc; |
361 | |
362 | switch (format.type) |
363 | { |
364 | case LS_ASCII: |
365 | name = read_ascii_data (stream, orig_fname, global, tc, count); |
366 | break; |
367 | |
368 | case LS_BINARY: |
369 | name = read_binary_data (stream, swap, flt_fmt, orig_fname, |
370 | global, tc, doc); |
371 | break; |
372 | |
373 | case LS_MAT_ASCII: |
374 | name = read_mat_ascii_data (stream, orig_fname, tc); |
375 | break; |
376 | |
377 | case LS_MAT_BINARY: |
378 | name = read_mat_binary_data (stream, orig_fname, tc); |
379 | break; |
380 | |
381 | #ifdef HAVE_HDF51 |
382 | case LS_HDF5: |
383 | name = read_hdf5_data (stream, orig_fname, global, tc, doc, |
384 | argv, argv_idx, argc); |
385 | break; |
386 | #endif /* HAVE_HDF5 */ |
387 | |
388 | case LS_MAT5_BINARY: |
389 | case LS_MAT7_BINARY: |
390 | name = read_mat5_binary_element (stream, orig_fname, swap, |
391 | global, tc); |
392 | break; |
393 | |
394 | default: |
395 | gripe_unrecognized_data_fmt ("load"); |
396 | break; |
397 | } |
398 | |
399 | if (error_state || stream.eof () || name.empty ()) |
400 | break; |
401 | else if (! error_state && ! name.empty ()) |
402 | { |
403 | if (tc.is_defined ()) |
404 | { |
405 | if (format == LS_MAT_ASCII && argv_idx < argc) |
406 | warning ("load: loaded ASCII file '%s' -- ignoring extra args", |
407 | orig_fname.c_str ()); |
408 | |
409 | if (format == LS_MAT_ASCII |
410 | || argv_idx == argc |
411 | || matches_patterns (argv, argv_idx, argc, name)) |
412 | { |
413 | count++; |
414 | if (list_only) |
415 | { |
416 | if (verbose) |
417 | { |
418 | if (count == 1) |
419 | output_buf |
420 | << "type rows cols name\n" |
421 | << "==== ==== ==== ====\n"; |
422 | |
423 | output_buf |
424 | << std::setiosflags (std::ios::left) |
425 | << std::setw (16) << tc.type_name () . c_str () |
426 | << std::setiosflags (std::ios::right) |
427 | << std::setw (7) << tc.rows () |
428 | << std::setw (7) << tc.columns () |
429 | << " " << name << "\n"; |
430 | } |
431 | else |
432 | symbol_names.push_back (name); |
433 | } |
434 | else |
435 | { |
436 | if (nargout == 1) |
437 | { |
438 | if (format == LS_MAT_ASCII) |
439 | retval = tc; |
440 | else |
441 | retstruct.assign (name, tc); |
442 | } |
443 | else |
444 | install_loaded_variable (name, tc, global, doc); |
445 | } |
446 | } |
447 | |
448 | // Only attempt to read one item from a headless text file. |
449 | |
450 | if (format == LS_MAT_ASCII) |
451 | break; |
452 | } |
453 | else |
454 | error ("load: unable to load variable '%s'", name.c_str ()); |
455 | } |
456 | else |
457 | { |
458 | if (count == 0) |
459 | error ("load: are you sure '%s' is an Octave data file?", |
460 | orig_fname.c_str ()); |
461 | |
462 | break; |
463 | } |
464 | } |
465 | |
466 | if (list_only && count) |
467 | { |
468 | if (verbose) |
469 | { |
470 | std::string msg = output_buf.str (); |
471 | |
472 | if (nargout > 0) |
473 | retval = msg; |
474 | else |
475 | octave_stdout(octave_pager_stream::stream ()) << msg; |
476 | } |
477 | else |
478 | { |
479 | if (nargout > 0) |
480 | retval = Cell (string_vector (symbol_names)); |
481 | else |
482 | { |
483 | string_vector names (symbol_names); |
484 | |
485 | names.list_in_columns (octave_stdout(octave_pager_stream::stream ())); |
486 | |
487 | octave_stdout(octave_pager_stream::stream ()) << "\n"; |
488 | } |
489 | } |
490 | } |
491 | else if (retstruct.nfields () != 0) |
492 | retval = retstruct; |
493 | |
494 | return retval; |
495 | } |
496 | |
497 | std::string |
498 | find_file_to_load (const std::string& name, const std::string& orig_name) |
499 | { |
500 | std::string fname = name; |
501 | |
502 | if (! (octave_env::absolute_pathname (fname) |
503 | || octave_env::rooted_relative_pathname (fname))) |
504 | { |
505 | file_stat fs (fname); |
506 | |
507 | if (! (fs.exists () && fs.is_reg ())) |
508 | { |
509 | std::string tmp |
510 | = octave_env::make_absolute (load_path::find_file (fname)); |
511 | |
512 | if (! tmp.empty ()) |
513 | { |
514 | warning_with_id ("Octave:load-file-in-path", |
515 | "load: file found in load path"); |
516 | fname = tmp; |
517 | } |
518 | } |
519 | } |
520 | |
521 | size_t dot_pos = fname.rfind ("."); |
522 | size_t sep_pos = fname.find_last_of (file_ops::dir_sep_chars ()); |
523 | |
524 | if (dot_pos == std::string::npos |
525 | || (sep_pos != std::string::npos && dot_pos < sep_pos)) |
526 | { |
527 | // Either no '.' in name or no '.' appears after last directory |
528 | // separator. |
529 | |
530 | file_stat fs (fname); |
531 | |
532 | if (! (fs.exists () && fs.is_reg ())) |
533 | fname = find_file_to_load (fname + ".mat", orig_name); |
534 | } |
535 | else |
536 | { |
537 | file_stat fs (fname); |
538 | |
539 | if (! (fs.exists () && fs.is_reg ())) |
540 | { |
541 | fname = ""; |
542 | |
543 | error ("load: unable to find file %s", orig_name.c_str ()); |
544 | } |
545 | } |
546 | |
547 | return fname; |
548 | } |
549 | |
550 | bool |
551 | is_octave_data_file (const std::string& fname) |
552 | { |
553 | bool use_zlib = false; |
554 | return get_file_format (fname, fname, use_zlib, true) != LS_UNKNOWN; |
555 | } |
556 | |
557 | DEFUN (load, args, nargout,octave_value_list Fload (const octave_value_list& args, int nargout) |
558 | "-*- texinfo -*-\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
559 | @deftypefn {Command} {} load file\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
560 | @deftypefnx {Command} {} load options file\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
561 | @deftypefnx {Command} {} load options file v1 v2 @dots{}\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
562 | @deftypefnx {Command} {S =} load (\"options\", \"file\", \"v1\", \"v2\", @dots{})\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
563 | @deftypefnx {Command} {} load file options\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
564 | @deftypefnx {Command} {} load file options v1 v2 @dots{}\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
565 | @deftypefnx {Command} {S =} load (\"file\", \"options\", \"v1\", \"v2\", @dots{})\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
566 | Load the named variables @var{v1}, @var{v2}, @dots{}, from the file\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
567 | @var{file}. If no variables are specified then all variables found in the\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
568 | file will be loaded. As with @code{save}, the list of variables to extract\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
569 | can be full names or use a pattern syntax. The format of the file is\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
570 | automatically detected but may be overridden by supplying the appropriate\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
571 | option.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
572 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
573 | If load is invoked using the functional form\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
574 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
575 | @example\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
576 | load (\"-option1\", @dots{}, \"file\", \"v1\", @dots{})\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
577 | @end example\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
578 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
579 | @noindent\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
580 | then the @var{options}, @var{file}, and variable name arguments\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
581 | (@var{v1}, @dots{}) must be specified as character strings.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
582 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
583 | If a variable that is not marked as global is loaded from a file when a\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
584 | global symbol with the same name already exists, it is loaded in the\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
585 | global symbol table. Also, if a variable is marked as global in a file\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
586 | and a local symbol exists, the local symbol is moved to the global\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
587 | symbol table and given the value from the file.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
588 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
589 | If invoked with a single output argument, Octave returns data instead\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
590 | of inserting variables in the symbol table. If the data file contains\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
591 | only numbers (TAB- or space-delimited columns), a matrix of values is\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
592 | returned. Otherwise, @code{load} returns a structure with members\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
593 | corresponding to the names of the variables in the file.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
594 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
595 | The @code{load} command can read data stored in Octave's text and\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
596 | binary formats, and @sc{matlab}'s binary format. If compiled with zlib\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
597 | support, it can also load gzip-compressed files. It will automatically\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
598 | detect the type of file and do conversion from different floating point\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
599 | formats (currently only IEEE big and little endian, though other formats\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
600 | may be added in the future).\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
601 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
602 | Valid options for @code{load} are listed in the following table.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
603 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
604 | @table @code\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
605 | @item -force\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
606 | This option is accepted for backward compatibility but is ignored.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
607 | Octave now overwrites variables currently in memory with\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
608 | those of the same name found in the file.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
609 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
610 | @item -ascii\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
611 | Force Octave to assume the file contains columns of numbers in text format\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
612 | without any header or other information. Data in the file will be loaded\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
613 | as a single numeric matrix with the name of the variable derived from the\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
614 | name of the file.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
615 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
616 | @item -binary\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
617 | Force Octave to assume the file is in Octave's binary format.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
618 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
619 | @item -hdf5\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
620 | Force Octave to assume the file is in @sc{hdf5} format.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
621 | (@sc{hdf5} is a free, portable binary format developed by the National\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
622 | Center for Supercomputing Applications at the University of Illinois.)\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
623 | Note that Octave can read @sc{hdf5} files not created by itself, but may\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
624 | skip some datasets in formats that it cannot support. This format is\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
625 | only available if Octave was built with a link to the @sc{hdf5} libraries.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
626 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
627 | @item -import\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
628 | This option is accepted for backward compatibility but is ignored.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
629 | Octave can now support multi-dimensional HDF data and automatically\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
630 | modifies variable names if they are invalid Octave identifiers.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
631 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
632 | @item -mat\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
633 | @itemx -mat-binary\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
634 | @itemx -6\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
635 | @itemx -v6\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
636 | @itemx -7\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
637 | @itemx -v7\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
638 | Force Octave to assume the file is in @sc{matlab}'s version 6 or 7 binary\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
639 | format.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
640 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
641 | @item -mat4-binary\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
642 | @itemx -4\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
643 | @itemx -v4\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
644 | @itemx -V4\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
645 | Force Octave to assume the file is in the binary format written by\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
646 | @sc{matlab} version 4.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
647 | \n\octave_value_list Fload (const octave_value_list& args, int nargout) |
648 | @item -text\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
649 | Force Octave to assume the file is in Octave's text format.\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
650 | @end table\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
651 | @seealso{save, dlmwrite, csvwrite, fwrite}\n\octave_value_list Fload (const octave_value_list& args, int nargout) |
652 | @end deftypefn")octave_value_list Fload (const octave_value_list& args, int nargout) |
653 | { |
654 | octave_value_list retval; |
655 | |
656 | int argc = args.length () + 1; |
657 | |
658 | string_vector argv = args.make_argv ("load"); |
659 | |
660 | if (error_state) |
661 | return retval; |
662 | |
663 | int i = 1; |
664 | std::string orig_fname = ""; |
665 | |
666 | // Function called with Matlab-style ["filename", options] syntax |
667 | if (argc > 1 && ! argv[1].empty () && argv[1].at (0) != '-') |
668 | { |
669 | orig_fname = argv[1]; |
670 | i++; |
671 | } |
672 | |
673 | // It isn't necessary to have the default load format stored in a |
674 | // user preference variable since we can determine the type of file |
675 | // as we are reading. |
676 | |
677 | load_save_format format = LS_UNKNOWN; |
678 | |
679 | bool list_only = false; |
680 | bool verbose = false; |
681 | |
682 | //for (i; i < argc; i++) |
683 | for (; i < argc; i++) |
684 | { |
685 | if (argv[i] == "-force" || argv[i] == "-f") |
686 | { |
687 | // Silently ignore this |
688 | // warning ("load: -force ignored"); |
689 | } |
690 | else if (argv[i] == "-list" || argv[i] == "-l") |
691 | { |
692 | list_only = true; |
693 | } |
694 | else if (argv[i] == "-verbose" || argv[i] == "-v") |
695 | { |
696 | verbose = true; |
697 | } |
698 | else if (argv[i] == "-ascii" || argv[i] == "-a") |
699 | { |
700 | format = LS_MAT_ASCII; |
701 | } |
702 | else if (argv[i] == "-binary" || argv[i] == "-b") |
703 | { |
704 | format = LS_BINARY; |
705 | } |
706 | else if (argv[i] == "-mat-binary" || argv[i] == "-mat" || argv[i] == "-m" |
707 | || argv[i] == "-6" || argv[i] == "-v6") |
708 | { |
709 | format = LS_MAT5_BINARY; |
710 | } |
711 | else if (argv[i] == "-7" || argv[i] == "-v7") |
712 | { |
713 | format = LS_MAT7_BINARY; |
714 | } |
715 | else if (argv[i] == "-mat4-binary" || argv[i] == "-V4" |
716 | || argv[i] == "-v4" || argv[i] == "-4") |
717 | { |
718 | format = LS_MAT_BINARY; |
719 | } |
720 | else if (argv[i] == "-hdf5" || argv[i] == "-h") |
721 | { |
722 | #ifdef HAVE_HDF51 |
723 | format = LS_HDF5; |
724 | #else /* ! HAVE_HDF5 */ |
725 | error ("load: octave executable was not linked with HDF5 library"); |
726 | return retval; |
727 | #endif /* ! HAVE_HDF5 */ |
728 | } |
729 | else if (argv[i] == "-import" || argv[i] == "-i") |
730 | { |
731 | warning ("load: -import ignored"); |
732 | } |
733 | else if (argv[i] == "-text" || argv[i] == "-t") |
734 | { |
735 | format = LS_ASCII; |
736 | } |
737 | else |
738 | break; |
739 | } |
740 | |
741 | if (orig_fname == "") |
742 | { |
743 | if (i == argc) |
744 | { |
745 | print_usage (); |
746 | return retval; |
747 | } |
748 | else |
749 | orig_fname = argv[i]; |
750 | } |
751 | else |
752 | i--; |
753 | |
754 | oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown; |
755 | |
756 | bool swap = false; |
757 | |
758 | if (orig_fname == "-") |
759 | { |
760 | i++; |
761 | |
762 | #ifdef HAVE_HDF51 |
763 | if (format == LS_HDF5) |
764 | error ("load: cannot read HDF5 format from stdin"); |
765 | else |
766 | #endif /* HAVE_HDF5 */ |
767 | if (format != LS_UNKNOWN) |
768 | { |
769 | // FIXME: if we have already seen EOF on a previous call, |
770 | // how do we fix up the state of std::cin so that we can get |
771 | // additional input? I'm afraid that we can't fix this |
772 | // using std::cin only. |
773 | |
774 | retval = do_load (std::cin, orig_fname, format, flt_fmt, |
775 | list_only, swap, verbose, argv, i, argc, |
776 | nargout); |
777 | } |
778 | else |
779 | error ("load: must specify file format if reading from stdin"); |
780 | } |
781 | else |
782 | { |
783 | std::string fname = file_ops::tilde_expand (orig_fname); |
784 | |
785 | fname = find_file_to_load (fname, orig_fname); |
786 | |
787 | if (error_state) |
788 | return retval; |
789 | |
790 | bool use_zlib = false; |
791 | |
792 | if (format == LS_UNKNOWN) |
793 | format = get_file_format (fname, orig_fname, use_zlib); |
794 | |
795 | #ifdef HAVE_HDF51 |
796 | if (format == LS_HDF5) |
797 | { |
798 | i++; |
799 | |
800 | hdf5_ifstream hdf5_file (fname.c_str ()); |
801 | |
802 | if (hdf5_file.file_id >= 0) |
803 | { |
804 | retval = do_load (hdf5_file, orig_fname, format, |
805 | flt_fmt, list_only, swap, verbose, |
806 | argv, i, argc, nargout); |
807 | |
808 | hdf5_file.close (); |
809 | } |
810 | else |
811 | gripe_file_open ("load", orig_fname); |
812 | } |
813 | else |
814 | #endif /* HAVE_HDF5 */ |
815 | // don't insert any statements here; the "else" above has to |
816 | // go with the "if" below!!!!! |
817 | if (format != LS_UNKNOWN) |
818 | { |
819 | i++; |
820 | |
821 | // Always open in binary mode and handle various |
822 | // line-endings explicitly. |
823 | std::ios::openmode mode = std::ios::in | std::ios::binary; |
824 | |
825 | #ifdef HAVE_ZLIB1 |
826 | if (use_zlib) |
827 | { |
828 | gzifstream file (fname.c_str (), mode); |
829 | |
830 | if (file) |
831 | { |
832 | if (format == LS_BINARY) |
833 | { |
834 | if (read_binary_file_header (file, swap, flt_fmt) < 0) |
835 | { |
836 | if (file) file.close (); |
837 | return retval; |
838 | } |
839 | } |
840 | else if (format == LS_MAT5_BINARY |
841 | || format == LS_MAT7_BINARY) |
842 | { |
843 | if (read_mat5_binary_file_header (file, swap, false, |
844 | orig_fname) < 0) |
845 | { |
846 | if (file) file.close (); |
847 | return retval; |
848 | } |
849 | } |
850 | |
851 | retval = do_load (file, orig_fname, format, |
852 | flt_fmt, list_only, swap, verbose, |
853 | argv, i, argc, nargout); |
854 | |
855 | file.close (); |
856 | } |
857 | else |
858 | gripe_file_open ("load", orig_fname); |
859 | } |
860 | else |
861 | #endif |
862 | { |
863 | std::ifstream file (fname.c_str (), mode); |
864 | |
865 | if (file) |
866 | { |
867 | if (format == LS_BINARY) |
868 | { |
869 | if (read_binary_file_header (file, swap, flt_fmt) < 0) |
870 | { |
871 | if (file) file.close (); |
872 | return retval; |
873 | } |
874 | } |
875 | else if (format == LS_MAT5_BINARY |
876 | || format == LS_MAT7_BINARY) |
877 | { |
878 | if (read_mat5_binary_file_header (file, swap, false, |
879 | orig_fname) < 0) |
880 | { |
881 | if (file) file.close (); |
882 | return retval; |
883 | } |
884 | } |
885 | |
886 | retval = do_load (file, orig_fname, format, |
887 | flt_fmt, list_only, swap, verbose, |
888 | argv, i, argc, nargout); |
889 | |
890 | file.close (); |
891 | } |
892 | else |
893 | error ("load: unable to open input file '%s'", |
894 | orig_fname.c_str ()); |
895 | } |
896 | } |
897 | } |
898 | |
899 | return retval; |
900 | } |
901 | |
902 | // Return TRUE if PATTERN has any special globbing chars in it. |
903 | |
904 | static bool |
905 | glob_pattern_p (const std::string& pattern) |
906 | { |
907 | int open = 0; |
908 | |
909 | int len = pattern.length (); |
910 | |
911 | for (int i = 0; i < len; i++) |
912 | { |
913 | char c = pattern[i]; |
914 | |
915 | switch (c) |
916 | { |
917 | case '?': |
918 | case '*': |
919 | return true; |
920 | |
921 | case '[': // Only accept an open brace if there is a close |
922 | open++; // brace to match it. Bracket expressions must be |
923 | continue; // complete, according to Posix.2 |
924 | |
925 | case ']': |
926 | if (open) |
927 | return true; |
928 | continue; |
929 | |
930 | case '\\': |
931 | if (i == len - 1) |
932 | return false; |
933 | |
934 | default: |
935 | continue; |
936 | } |
937 | } |
938 | |
939 | return false; |
940 | } |
941 | |
942 | static void |
943 | do_save (std::ostream& os, const octave_value& tc, |
944 | const std::string& name, const std::string& help, |
945 | bool global, load_save_format fmt, bool save_as_floats) |
946 | { |
947 | switch (fmt.type) |
948 | { |
949 | case LS_ASCII: |
950 | save_ascii_data (os, tc, name, global, 0); |
951 | break; |
952 | |
953 | case LS_BINARY: |
954 | save_binary_data (os, tc, name, help, global, save_as_floats); |
955 | break; |
956 | |
957 | case LS_MAT_ASCII: |
958 | if (! save_mat_ascii_data (os, tc, fmt.opts & LS_MAT_ASCII_LONG ? 16 : 8, |
959 | fmt.opts & LS_MAT_ASCII_TABS)) |
960 | warning ("save: unable to save %s in ASCII format", name.c_str ()); |
961 | break; |
962 | |
963 | case LS_MAT_BINARY: |
964 | save_mat_binary_data (os, tc, name); |
965 | break; |
966 | |
967 | #ifdef HAVE_HDF51 |
968 | case LS_HDF5: |
969 | save_hdf5_data (os, tc, name, help, global, save_as_floats); |
970 | break; |
971 | #endif /* HAVE_HDF5 */ |
972 | |
973 | case LS_MAT5_BINARY: |
974 | save_mat5_binary_element (os, tc, name, global, false, save_as_floats); |
975 | break; |
976 | |
977 | case LS_MAT7_BINARY: |
978 | save_mat5_binary_element (os, tc, name, global, true, save_as_floats); |
979 | break; |
980 | |
981 | default: |
982 | gripe_unrecognized_data_fmt ("save"); |
983 | break; |
984 | } |
985 | } |
986 | |
987 | // Save the info from SR on stream OS in the format specified by FMT. |
988 | |
989 | void |
990 | do_save (std::ostream& os, const symbol_table::symbol_record& sr, |
991 | load_save_format fmt, bool save_as_floats) |
992 | { |
993 | octave_value val = sr.varval (); |
994 | |
995 | if (val.is_defined ()) |
996 | { |
997 | std::string name = sr.name (); |
998 | std::string help; |
999 | bool global = sr.is_global (); |
1000 | |
1001 | do_save (os, val, name, help, global, fmt, save_as_floats); |
1002 | } |
1003 | } |
1004 | |
1005 | // save fields of a scalar structure STR matching PATTERN on stream OS |
1006 | // in the format specified by FMT. |
1007 | |
1008 | static size_t |
1009 | save_fields (std::ostream& os, const octave_scalar_map& m, |
1010 | const std::string& pattern, |
1011 | load_save_format fmt, bool save_as_floats) |
1012 | { |
1013 | glob_match pat (pattern); |
1014 | |
1015 | size_t saved = 0; |
1016 | |
1017 | for (octave_scalar_map::const_iterator p = m.begin (); p != m.end (); p++) |
1018 | { |
1019 | std::string empty_str; |
1020 | |
1021 | if (pat.match (m.key (p))) |
1022 | { |
1023 | do_save (os, m.contents (p), m.key (p), empty_str, |
1024 | 0, fmt, save_as_floats); |
1025 | |
1026 | saved++; |
1027 | } |
1028 | } |
1029 | |
1030 | return saved; |
1031 | } |
1032 | |
1033 | // Save variables with names matching PATTERN on stream OS in the |
1034 | // format specified by FMT. |
1035 | |
1036 | static size_t |
1037 | save_vars (std::ostream& os, const std::string& pattern, |
1038 | load_save_format fmt, bool save_as_floats) |
1039 | { |
1040 | std::list<symbol_table::symbol_record> vars = symbol_table::glob (pattern); |
1041 | |
1042 | size_t saved = 0; |
1043 | |
1044 | typedef std::list<symbol_table::symbol_record>::const_iterator |
1045 | const_vars_iterator; |
1046 | |
1047 | for (const_vars_iterator p = vars.begin (); p != vars.end (); p++) |
1048 | { |
1049 | do_save (os, *p, fmt, save_as_floats); |
1050 | |
1051 | if (error_state) |
1052 | break; |
1053 | |
1054 | saved++; |
1055 | } |
1056 | |
1057 | return saved; |
1058 | } |
1059 | |
1060 | static string_vector |
1061 | parse_save_options (const string_vector &argv, |
1062 | load_save_format &format, bool &append, |
1063 | bool &save_as_floats, bool &use_zlib) |
1064 | { |
1065 | string_vector retval; |
1066 | int argc = argv.length (); |
1067 | |
1068 | bool do_double = false, do_tabs = false; |
1069 | |
1070 | for (int i = 0; i < argc; i++) |
1071 | { |
1072 | if (argv[i] == "-append") |
1073 | { |
1074 | append = true; |
1075 | } |
1076 | else if (argv[i] == "-ascii" || argv[i] == "-a") |
1077 | { |
1078 | format = LS_MAT_ASCII; |
1079 | } |
1080 | else if (argv[i] == "-double") |
1081 | { |
1082 | do_double = true; |
1083 | } |
1084 | else if (argv[i] == "-tabs") |
1085 | { |
1086 | do_tabs = true; |
1087 | } |
1088 | else if (argv[i] == "-text" || argv[i] == "-t") |
1089 | { |
1090 | format = LS_ASCII; |
1091 | } |
1092 | else if (argv[i] == "-binary" || argv[i] == "-b") |
1093 | { |
1094 | format = LS_BINARY; |
1095 | } |
1096 | else if (argv[i] == "-hdf5" || argv[i] == "-h") |
1097 | { |
1098 | #ifdef HAVE_HDF51 |
1099 | format = LS_HDF5; |
1100 | #else /* ! HAVE_HDF5 */ |
1101 | error ("save: octave executable was not linked with HDF5 library"); |
1102 | #endif /* ! HAVE_HDF5 */ |
1103 | } |
1104 | else if (argv[i] == "-mat-binary" || argv[i] == "-mat" |
1105 | || argv[i] == "-m" || argv[i] == "-6" || argv[i] == "-v6" |
1106 | || argv[i] == "-V6") |
1107 | { |
1108 | format = LS_MAT5_BINARY; |
1109 | } |
1110 | #ifdef HAVE_ZLIB1 |
1111 | else if (argv[i] == "-mat7-binary" || argv[i] == "-7" |
1112 | || argv[i] == "-v7" || argv[i] == "-V7") |
1113 | { |
1114 | format = LS_MAT7_BINARY; |
1115 | } |
1116 | #endif |
1117 | else if (argv[i] == "-mat4-binary" || argv[i] == "-V4" |
1118 | || argv[i] == "-v4" || argv[i] == "-4") |
1119 | { |
1120 | format = LS_MAT_BINARY; |
1121 | } |
1122 | else if (argv[i] == "-float-binary" || argv[i] == "-f") |
1123 | { |
1124 | format = LS_BINARY; |
1125 | save_as_floats = true; |
1126 | } |
1127 | else if (argv[i] == "-float-hdf5") |
1128 | { |
1129 | #ifdef HAVE_HDF51 |
1130 | format = LS_HDF5; |
1131 | save_as_floats = true; |
1132 | #else /* ! HAVE_HDF5 */ |
1133 | error ("save: octave executable was not linked with HDF5 library"); |
1134 | #endif /* ! HAVE_HDF5 */ |
1135 | } |
1136 | #ifdef HAVE_ZLIB1 |
1137 | else if (argv[i] == "-zip" || argv[i] == "-z") |
1138 | { |
1139 | use_zlib = true; |
1140 | } |
1141 | #endif |
1142 | else if (argv[i] == "-struct") |
1143 | { |
1144 | retval.append (argv[i]); |
1145 | } |
1146 | else if (argv[i][0] == '-') |
1147 | { |
1148 | error ("save: Unrecognized option '%s'", argv[i].c_str ()); |
1149 | } |
1150 | else |
1151 | retval.append (argv[i]); |
1152 | } |
1153 | |
1154 | if (do_double) |
1155 | { |
1156 | if (format == LS_MAT_ASCII) |
1157 | format.opts |= LS_MAT_ASCII_LONG; |
1158 | else |
1159 | warning ("save: \"-double\" option only has an effect with \"-ascii\""); |
1160 | } |
1161 | |
1162 | if (do_tabs) |
1163 | { |
1164 | if (format == LS_MAT_ASCII) |
1165 | format.opts |= LS_MAT_ASCII_TABS; |
1166 | else |
1167 | warning ("save: \"-tabs\" option only has an effect with \"-ascii\""); |
1168 | } |
1169 | |
1170 | return retval; |
1171 | } |
1172 | |
1173 | static string_vector |
1174 | parse_save_options (const std::string &arg, load_save_format &format, |
1175 | bool &append, bool &save_as_floats, |
1176 | bool &use_zlib) |
1177 | { |
1178 | std::istringstream is (arg); |
1179 | std::string str; |
1180 | string_vector argv; |
1181 | |
1182 | while (! is.eof ()) |
1183 | { |
1184 | is >> str; |
1185 | argv.append (str); |
1186 | } |
1187 | |
1188 | return parse_save_options (argv, format, append, save_as_floats, |
1189 | use_zlib); |
1190 | } |
1191 | |
1192 | void |
1193 | write_header (std::ostream& os, load_save_format format) |
1194 | { |
1195 | switch (format.type) |
1196 | { |
1197 | case LS_BINARY: |
1198 | { |
1199 | os << (oct_mach_info::words_big_endian () |
1200 | ? "Octave-1-B" : "Octave-1-L"); |
1201 | |
1202 | oct_mach_info::float_format flt_fmt = |
1203 | oct_mach_info::native_float_format (); |
1204 | |
1205 | char tmp = static_cast<char> (float_format_to_mopt_digit (flt_fmt)); |
1206 | |
1207 | os.write (&tmp, 1); |
1208 | } |
1209 | break; |
1210 | |
1211 | case LS_MAT5_BINARY: |
1212 | case LS_MAT7_BINARY: |
1213 | { |
1214 | char const * versionmagic; |
1215 | int16_t number = *(reinterpret_cast<const int16_t *>("\x00\x01")); |
1216 | struct tm bdt; |
1217 | time_t now; |
1218 | char headertext[128]; |
1219 | |
1220 | time (&now); |
1221 | bdt = *gmtime (&now); |
1222 | memset (headertext, ' ', 124); |
1223 | // ISO 8601 format date |
1224 | nstrftime (headertext, 124, "MATLAB 5.0 MAT-file, written by Octave " |
1225 | OCTAVE_VERSION"3.7.7+" ", %Y-%m-%d %T UTC", &bdt, 1, 0); |
1226 | |
1227 | // The first pair of bytes give the version of the MAT file |
1228 | // format. The second pair of bytes form a magic number which |
1229 | // signals a MAT file. MAT file data are always written in |
1230 | // native byte order. The order of the bytes in the second |
1231 | // pair indicates whether the file was written by a big- or |
1232 | // little-endian machine. However, the version number is |
1233 | // written in the *opposite* byte order from everything else! |
1234 | if (number == 1) |
1235 | versionmagic = "\x01\x00\x4d\x49"; // this machine is big endian |
1236 | else |
1237 | versionmagic = "\x00\x01\x49\x4d"; // this machine is little endian |
1238 | |
1239 | memcpy (headertext+124, versionmagic, 4); |
1240 | os.write (headertext, 128); |
1241 | } |
1242 | |
1243 | break; |
1244 | |
1245 | #ifdef HAVE_HDF51 |
1246 | case LS_HDF5: |
1247 | #endif /* HAVE_HDF5 */ |
1248 | case LS_ASCII: |
1249 | { |
1250 | octave_localtime now; |
1251 | |
1252 | std::string comment_string = now.strftime (Vsave_header_format_string); |
1253 | |
1254 | if (! comment_string.empty ()) |
1255 | { |
1256 | #ifdef HAVE_HDF51 |
1257 | if (format == LS_HDF5) |
1258 | { |
1259 | hdf5_ofstream& hs = dynamic_cast<hdf5_ofstream&> (os); |
1260 | H5Gset_comment (hs.file_id, "/", comment_string.c_str ()); |
1261 | } |
1262 | else |
1263 | #endif /* HAVE_HDF5 */ |
1264 | os << comment_string << "\n"; |
1265 | } |
1266 | } |
1267 | break; |
1268 | |
1269 | default: |
1270 | break; |
1271 | } |
1272 | } |
1273 | |
1274 | void |
1275 | octave_prepare_hdf5 (void) |
1276 | { |
1277 | #ifdef HAVE_HDF51 |
1278 | H5dont_atexit (); |
1279 | #endif |
1280 | } |
1281 | |
1282 | void |
1283 | octave_finalize_hdf5 (void) |
1284 | { |
1285 | #ifdef HAVE_HDF51 |
1286 | H5close (); |
1287 | #endif |
1288 | } |
1289 | |
1290 | static void |
1291 | save_vars (const string_vector& argv, int argv_idx, int argc, |
1292 | std::ostream& os, load_save_format fmt, |
1293 | bool save_as_floats, bool write_header_info) |
1294 | { |
1295 | if (write_header_info) |
1296 | write_header (os, fmt); |
1297 | |
1298 | if (argv_idx == argc) |
1299 | { |
1300 | save_vars (os, "*", fmt, save_as_floats); |
1301 | } |
1302 | else if (argv[argv_idx] == "-struct") |
1303 | { |
1304 | if (++argv_idx >= argc) |
1305 | { |
1306 | error ("save: missing struct name"); |
1307 | return; |
1308 | } |
1309 | |
1310 | std::string struct_name = argv[argv_idx]; |
1311 | |
1312 | if (! symbol_table::is_variable (struct_name)) |
1313 | { |
1314 | error ("save: no such variable: '%s'", struct_name.c_str ()); |
1315 | return; |
1316 | } |
1317 | |
1318 | octave_value struct_var = symbol_table::varval (struct_name); |
1319 | |
1320 | if (! struct_var.is_map () || struct_var.numel () != 1) |
1321 | { |
1322 | error ("save: '%s' is not a scalar structure", |
1323 | struct_name.c_str ()); |
1324 | return; |
1325 | } |
1326 | octave_scalar_map struct_var_map = struct_var.scalar_map_value (); |
1327 | |
1328 | ++argv_idx; |
1329 | |
1330 | if (argv_idx < argc) |
1331 | { |
1332 | for (int i = argv_idx; i < argc; i++) |
1333 | { |
1334 | if (! save_fields (os, struct_var_map, argv[i], fmt, |
1335 | save_as_floats)) |
1336 | { |
1337 | warning ("save: no such field '%s.%s'", |
1338 | struct_name.c_str (), argv[i].c_str ()); |
1339 | } |
1340 | } |
1341 | } |
1342 | else |
1343 | save_fields (os, struct_var_map, "*", fmt, save_as_floats); |
1344 | } |
1345 | else |
1346 | { |
1347 | for (int i = argv_idx; i < argc; i++) |
1348 | { |
1349 | if (argv[i] == "") |
1350 | continue; // Skip empty vars for Matlab compatibility |
1351 | if (! save_vars (os, argv[i], fmt, save_as_floats)) |
1352 | warning ("save: no such variable '%s'", argv[i].c_str ()); |
1353 | } |
1354 | } |
1355 | } |
1356 | |
1357 | static void |
1358 | dump_octave_core (std::ostream& os, const char *fname, load_save_format fmt, |
1359 | bool save_as_floats) |
1360 | { |
1361 | write_header (os, fmt); |
1362 | |
1363 | std::list<symbol_table::symbol_record> vars |
1364 | = symbol_table::all_variables (symbol_table::top_scope (), 0); |
1365 | |
1366 | double save_mem_size = 0; |
1367 | |
1368 | typedef std::list<symbol_table::symbol_record>::const_iterator |
1369 | const_vars_iterator; |
1370 | |
1371 | for (const_vars_iterator p = vars.begin (); p != vars.end (); p++) |
1372 | { |
1373 | octave_value val = p->varval (); |
1374 | |
1375 | if (val.is_defined ()) |
1376 | { |
1377 | std::string name = p->name (); |
1378 | std::string help; |
1379 | bool global = p->is_global (); |
1380 | |
1381 | double val_size = val.byte_size () / 1024; |
1382 | |
1383 | // FIXME: maybe we should try to throw out the largest first... |
1384 | |
1385 | if (Voctave_core_file_limit < 0 |
1386 | || save_mem_size + val_size < Voctave_core_file_limit) |
1387 | { |
1388 | save_mem_size += val_size; |
1389 | |
1390 | do_save (os, val, name, help, global, fmt, save_as_floats); |
1391 | |
1392 | if (error_state) |
1393 | break; |
1394 | } |
1395 | } |
1396 | } |
1397 | |
1398 | message (0, "save to '%s' complete", fname); |
1399 | } |
1400 | |
1401 | void |
1402 | dump_octave_core (void) |
1403 | { |
1404 | if (Vcrash_dumps_octave_core) |
1405 | { |
1406 | // FIXME: should choose better file name? |
1407 | |
1408 | const char *fname = Voctave_core_file_name.c_str (); |
1409 | |
1410 | message (0, "attempting to save variables to '%s'...", fname); |
1411 | |
1412 | load_save_format format = LS_BINARY; |
1413 | |
1414 | bool save_as_floats = false; |
1415 | |
1416 | bool append = false; |
1417 | |
1418 | bool use_zlib = false; |
1419 | |
1420 | parse_save_options (Voctave_core_file_options, format, append, |
1421 | save_as_floats, use_zlib); |
1422 | |
1423 | std::ios::openmode mode = std::ios::out; |
1424 | |
1425 | // Matlab v7 files are always compressed |
1426 | if (format == LS_MAT7_BINARY) |
1427 | use_zlib = false; |
1428 | |
1429 | if (format == LS_BINARY |
1430 | #ifdef HAVE_HDF51 |
1431 | || format == LS_HDF5 |
1432 | #endif |
1433 | || format == LS_MAT_BINARY |
1434 | || format == LS_MAT5_BINARY |
1435 | || format == LS_MAT7_BINARY) |
1436 | mode |= std::ios::binary; |
1437 | |
1438 | mode |= append ? std::ios::ate : std::ios::trunc; |
1439 | |
1440 | #ifdef HAVE_HDF51 |
1441 | if (format == LS_HDF5) |
1442 | { |
1443 | hdf5_ofstream file (fname, mode); |
1444 | |
1445 | if (file.file_id >= 0) |
1446 | { |
1447 | dump_octave_core (file, fname, format, save_as_floats); |
1448 | |
1449 | file.close (); |
1450 | } |
1451 | else |
1452 | warning ("unable to open '%s' for writing...", fname); |
1453 | } |
1454 | else |
1455 | #endif /* HAVE_HDF5 */ |
1456 | // don't insert any commands here! The open brace below must |
1457 | // go with the else above! |
1458 | { |
1459 | #ifdef HAVE_ZLIB1 |
1460 | if (use_zlib) |
1461 | { |
1462 | gzofstream file (fname, mode); |
1463 | |
1464 | if (file) |
1465 | { |
1466 | dump_octave_core (file, fname, format, save_as_floats); |
1467 | |
1468 | file.close (); |
1469 | } |
1470 | else |
1471 | warning ("unable to open '%s' for writing...", fname); |
1472 | } |
1473 | else |
1474 | #endif |
1475 | { |
1476 | std::ofstream file (fname, mode); |
1477 | |
1478 | if (file) |
1479 | { |
1480 | dump_octave_core (file, fname, format, save_as_floats); |
1481 | |
1482 | file.close (); |
1483 | } |
1484 | else |
1485 | warning ("unable to open '%s' for writing...", fname); |
1486 | } |
1487 | } |
1488 | } |
1489 | } |
1490 | |
1491 | DEFUN (save, args, ,octave_value_list Fsave (const octave_value_list& args, int ) |
1492 | "-*- texinfo -*-\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1493 | @deftypefn {Command} {} save file\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1494 | @deftypefnx {Command} {} save options file\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1495 | @deftypefnx {Command} {} save options file @var{v1} @var{v2} @dots{}\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1496 | @deftypefnx {Command} {} save options file -struct @var{STRUCT} @var{f1} @var{f2} @dots{}\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1497 | Save the named variables @var{v1}, @var{v2}, @dots{}, in the file\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1498 | @var{file}. The special filename @samp{-} may be used to write\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1499 | output to the terminal. If no variable names are listed, Octave saves\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1500 | all the variables in the current scope. Otherwise, full variable names or\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1501 | pattern syntax can be used to specify the variables to save.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1502 | If the @option{-struct} modifier is used, fields @var{f1} @var{f2} @dots{}\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1503 | of the scalar structure @var{STRUCT} are saved as if they were variables\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1504 | with corresponding names.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1505 | Valid options for the @code{save} command are listed in the following table.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1506 | Options that modify the output format override the format specified by\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1507 | @code{save_default_options}.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1508 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1509 | If save is invoked using the functional form\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1510 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1511 | @example\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1512 | save (\"-option1\", @dots{}, \"file\", \"v1\", @dots{})\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1513 | @end example\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1514 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1515 | @noindent\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1516 | then the @var{options}, @var{file}, and variable name arguments\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1517 | (@var{v1}, @dots{}) must be specified as character strings.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1518 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1519 | @table @code\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1520 | @item -append\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1521 | Append to the destination instead of overwriting.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1522 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1523 | @item -ascii\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1524 | Save a single matrix in a text file without header or any other information.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1525 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1526 | @item -binary\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1527 | Save the data in Octave's binary data format.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1528 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1529 | @item -float-binary\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1530 | Save the data in Octave's binary data format but only using single\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1531 | precision. Only use this format if you know that all the\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1532 | values to be saved can be represented in single precision.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1533 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1534 | @item -hdf5\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1535 | Save the data in @sc{hdf5} format.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1536 | (HDF5 is a free, portable binary format developed by the National\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1537 | Center for Supercomputing Applications at the University of Illinois.)\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1538 | This format is only available if Octave was built with a link to the\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1539 | @sc{hdf5} libraries.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1540 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1541 | @item -float-hdf5\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1542 | Save the data in @sc{hdf5} format but only using single precision.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1543 | Only use this format if you know that all the\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1544 | values to be saved can be represented in single precision.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1545 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1546 | @item -V7\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1547 | @itemx -v7\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1548 | @itemx -7\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1549 | @itemx -mat7-binary\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1550 | Save the data in @sc{matlab}'s v7 binary data format.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1551 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1552 | @item -V6\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1553 | @itemx -v6\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1554 | @itemx -6\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1555 | @itemx -mat\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1556 | @itemx -mat-binary\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1557 | Save the data in @sc{matlab}'s v6 binary data format.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1558 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1559 | @item -V4\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1560 | @itemx -v4\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1561 | @itemx -4\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1562 | @itemx -mat4-binary\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1563 | Save the data in the binary format written by @sc{matlab} version 4.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1564 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1565 | @item -text\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1566 | Save the data in Octave's text data format. (default).\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1567 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1568 | @item -zip\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1569 | @itemx -z\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1570 | Use the gzip algorithm to compress the file. This works equally on files\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1571 | that are compressed with gzip outside of octave, and gzip can equally be\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1572 | used to convert the files for backward compatibility.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1573 | This option is only available if Octave was built with a link to the zlib\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1574 | libraries.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1575 | @end table\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1576 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1577 | The list of variables to save may use wildcard patterns containing\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1578 | the following special characters:\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1579 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1580 | @table @code\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1581 | @item ?\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1582 | Match any single character.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1583 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1584 | @item *\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1585 | Match zero or more characters.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1586 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1587 | @item [ @var{list} ]\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1588 | Match the list of characters specified by @var{list}. If the first\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1589 | character is @code{!} or @code{^}, match all characters except those\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1590 | specified by @var{list}. For example, the pattern @code{[a-zA-Z]} will\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1591 | match all lower and uppercase alphabetic characters.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1592 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1593 | Wildcards may also be used in the field name specifications when using\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1594 | the @option{-struct} modifier (but not in the struct name itself).\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1595 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1596 | @end table\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1597 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1598 | Except when using the @sc{matlab} binary data file format or the\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1599 | @samp{-ascii} format, saving global\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1600 | variables also saves the global status of the variable. If the variable\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1601 | is restored at a later time using @samp{load}, it will be restored as a\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1602 | global variable.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1603 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1604 | The command\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1605 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1606 | @example\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1607 | save -binary data a b*\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1608 | @end example\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1609 | \n\octave_value_list Fsave (const octave_value_list& args, int ) |
1610 | @noindent\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1611 | saves the variable @samp{a} and all variables beginning with @samp{b} to\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1612 | the file @file{data} in Octave's binary format.\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1613 | @seealso{load, save_default_options, save_header_format_string, dlmread, csvread, fread}\n\octave_value_list Fsave (const octave_value_list& args, int ) |
1614 | @end deftypefn")octave_value_list Fsave (const octave_value_list& args, int ) |
1615 | { |
1616 | octave_value_list retval; |
1617 | |
1618 | int argc = args.length (); |
Value stored to 'argc' during its initialization is never read | |
1619 | |
1620 | string_vector argv = args.make_argv (); |
1621 | |
1622 | if (error_state) |
1623 | return retval; |
1624 | |
1625 | // Here is where we would get the default save format if it were |
1626 | // stored in a user preference variable. |
1627 | |
1628 | bool save_as_floats = false; |
1629 | |
1630 | load_save_format format = LS_ASCII; |
1631 | |
1632 | bool append = false; |
1633 | |
1634 | bool use_zlib = false; |
1635 | |
1636 | // get default options |
1637 | parse_save_options (Vsave_default_options, format, append, save_as_floats, |
1638 | use_zlib); |
1639 | |
1640 | // override from command line |
1641 | argv = parse_save_options (argv, format, append, save_as_floats, |
1642 | use_zlib); |
1643 | argc = argv.length (); |
1644 | int i = 0; |
1645 | |
1646 | if (error_state) |
1647 | return retval; |
1648 | |
1649 | if (i == argc) |
1650 | { |
1651 | print_usage (); |
1652 | return retval; |
1653 | } |
1654 | |
1655 | if (save_as_floats && format == LS_ASCII) |
1656 | { |
1657 | error ("save: cannot specify both -ascii and -float-binary"); |
1658 | return retval; |
1659 | } |
1660 | |
1661 | if (argv[i] == "-") |
1662 | { |
1663 | i++; |
1664 | |
1665 | #ifdef HAVE_HDF51 |
1666 | if (format == LS_HDF5) |
1667 | error ("save: cannot write HDF5 format to stdout"); |
1668 | else |
1669 | #endif /* HAVE_HDF5 */ |
1670 | // don't insert any commands here! the brace below must go |
1671 | // with the "else" above! |
1672 | { |
1673 | if (append) |
1674 | warning ("save: ignoring -append option for output to stdout"); |
1675 | |
1676 | // FIXME: should things intended for the screen |
1677 | // end up in an octave_value (string)? |
1678 | |
1679 | save_vars (argv, i, argc, octave_stdout(octave_pager_stream::stream ()), format, |
1680 | save_as_floats, true); |
1681 | } |
1682 | } |
1683 | |
1684 | // Guard against things like 'save a*', which are probably mistakes... |
1685 | |
1686 | else if (i == argc - 1 && glob_pattern_p (argv[i])) |
1687 | { |
1688 | print_usage (); |
1689 | return retval; |
1690 | } |
1691 | else |
1692 | { |
1693 | std::string fname = file_ops::tilde_expand (argv[i]); |
1694 | |
1695 | i++; |
1696 | |
1697 | // Matlab v7 files are always compressed |
1698 | if (format == LS_MAT7_BINARY) |
1699 | use_zlib = false; |
1700 | |
1701 | std::ios::openmode mode |
1702 | = append ? (std::ios::app | std::ios::ate) : std::ios::out; |
1703 | |
1704 | if (format == LS_BINARY |
1705 | #ifdef HAVE_HDF51 |
1706 | || format == LS_HDF5 |
1707 | #endif |
1708 | || format == LS_MAT_BINARY |
1709 | || format == LS_MAT5_BINARY |
1710 | || format == LS_MAT7_BINARY) |
1711 | mode |= std::ios::binary; |
1712 | |
1713 | #ifdef HAVE_HDF51 |
1714 | if (format == LS_HDF5) |
1715 | { |
1716 | // FIXME: It should be possible to append to HDF5 files. |
1717 | if (append) |
1718 | { |
1719 | error ("save: appending to HDF5 files is not implemented"); |
1720 | return retval; |
1721 | } |
1722 | |
1723 | bool write_header_info = ! (append && |
1724 | H5Fis_hdf5 (fname.c_str ()) > 0); |
1725 | |
1726 | hdf5_ofstream hdf5_file (fname.c_str (), mode); |
1727 | |
1728 | if (hdf5_file.file_id != -1) |
1729 | { |
1730 | save_vars (argv, i, argc, hdf5_file, format, |
1731 | save_as_floats, write_header_info); |
1732 | |
1733 | hdf5_file.close (); |
1734 | } |
1735 | else |
1736 | { |
1737 | gripe_file_open ("save", fname); |
1738 | return retval; |
1739 | } |
1740 | } |
1741 | else |
1742 | #endif /* HAVE_HDF5 */ |
1743 | // don't insert any statements here! The brace below must go |
1744 | // with the "else" above! |
1745 | { |
1746 | #ifdef HAVE_ZLIB1 |
1747 | if (use_zlib) |
1748 | { |
1749 | gzofstream file (fname.c_str (), mode); |
1750 | |
1751 | if (file) |
1752 | { |
1753 | bool write_header_info = ! file.tellp (); |
1754 | |
1755 | save_vars (argv, i, argc, file, format, |
1756 | save_as_floats, write_header_info); |
1757 | |
1758 | file.close (); |
1759 | } |
1760 | else |
1761 | { |
1762 | gripe_file_open ("save", fname); |
1763 | return retval; |
1764 | } |
1765 | } |
1766 | else |
1767 | #endif |
1768 | { |
1769 | std::ofstream file (fname.c_str (), mode); |
1770 | |
1771 | if (file) |
1772 | { |
1773 | bool write_header_info = ! file.tellp (); |
1774 | |
1775 | save_vars (argv, i, argc, file, format, |
1776 | save_as_floats, write_header_info); |
1777 | |
1778 | file.close (); |
1779 | } |
1780 | else |
1781 | { |
1782 | gripe_file_open ("save", fname); |
1783 | return retval; |
1784 | } |
1785 | } |
1786 | } |
1787 | } |
1788 | |
1789 | return retval; |
1790 | } |
1791 | |
1792 | DEFUN (crash_dumps_octave_core, args, nargout,octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1793 | "-*- texinfo -*-\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1794 | @deftypefn {Built-in Function} {@var{val} =} crash_dumps_octave_core ()\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1795 | @deftypefnx {Built-in Function} {@var{old_val} =} crash_dumps_octave_core (@var{new_val})\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1796 | @deftypefnx {Built-in Function} {} crash_dumps_octave_core (@var{new_val}, \"local\")\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1797 | Query or set the internal variable that controls whether Octave tries\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1798 | to save all current variables to the file @file{octave-workspace} if it\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1799 | crashes or receives a hangup, terminate or similar signal.\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1800 | \n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1801 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1802 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1803 | The original variable value is restored when exiting the function.\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1804 | @seealso{octave_core_file_limit, octave_core_file_name, octave_core_file_options}\n\octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1805 | @end deftypefn")octave_value_list Fcrash_dumps_octave_core (const octave_value_list & args, int nargout) |
1806 | { |
1807 | return SET_INTERNAL_VARIABLE (crash_dumps_octave_core)set_internal_variable (Vcrash_dumps_octave_core, args, nargout , "crash_dumps_octave_core"); |
1808 | } |
1809 | |
1810 | DEFUN (save_default_options, args, nargout,octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1811 | "-*- texinfo -*-\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1812 | @deftypefn {Built-in Function} {@var{val} =} save_default_options ()\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1813 | @deftypefnx {Built-in Function} {@var{old_val} =} save_default_options (@var{new_val})\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1814 | @deftypefnx {Built-in Function} {} save_default_options (@var{new_val}, \"local\")\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1815 | Query or set the internal variable that specifies the default options\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1816 | for the @code{save} command, and defines the default format.\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1817 | Typical values include @qcode{\"-ascii\"}, @qcode{\"-text -zip\"}.\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1818 | The default value is @option{-text}.\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1819 | \n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1820 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1821 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1822 | The original variable value is restored when exiting the function.\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1823 | @seealso{save}\n\octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1824 | @end deftypefn")octave_value_list Fsave_default_options (const octave_value_list & args, int nargout) |
1825 | { |
1826 | return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (save_default_options)set_internal_variable (Vsave_default_options, args, nargout, "save_default_options" , false); |
1827 | } |
1828 | |
1829 | DEFUN (octave_core_file_limit, args, nargout,octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1830 | "-*- texinfo -*-\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1831 | @deftypefn {Built-in Function} {@var{val} =} octave_core_file_limit ()\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1832 | @deftypefnx {Built-in Function} {@var{old_val} =} octave_core_file_limit (@var{new_val})\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1833 | @deftypefnx {Built-in Function} {} octave_core_file_limit (@var{new_val}, \"local\")\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1834 | Query or set the internal variable that specifies the maximum amount\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1835 | of memory (in kilobytes) of the top-level workspace that Octave will\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1836 | attempt to save when writing data to the crash dump file (the name of\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1837 | the file is specified by @var{octave_core_file_name}). If\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1838 | @var{octave_core_file_options} flags specify a binary format,\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1839 | then @var{octave_core_file_limit} will be approximately the maximum\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1840 | size of the file. If a text file format is used, then the file could\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1841 | be much larger than the limit. The default value is -1 (unlimited)\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1842 | \n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1843 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1844 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1845 | The original variable value is restored when exiting the function.\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1846 | @seealso{crash_dumps_octave_core, octave_core_file_name, octave_core_file_options}\n\octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1847 | @end deftypefn")octave_value_list Foctave_core_file_limit (const octave_value_list & args, int nargout) |
1848 | { |
1849 | return SET_INTERNAL_VARIABLE (octave_core_file_limit)set_internal_variable (Voctave_core_file_limit, args, nargout , "octave_core_file_limit"); |
1850 | } |
1851 | |
1852 | DEFUN (octave_core_file_name, args, nargout,octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1853 | "-*- texinfo -*-\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1854 | @deftypefn {Built-in Function} {@var{val} =} octave_core_file_name ()\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1855 | @deftypefnx {Built-in Function} {@var{old_val} =} octave_core_file_name (@var{new_val})\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1856 | @deftypefnx {Built-in Function} {} octave_core_file_name (@var{new_val}, \"local\")\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1857 | Query or set the internal variable that specifies the name of the file\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1858 | used for saving data from the top-level workspace if Octave aborts.\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1859 | The default value is @qcode{\"octave-workspace\"}\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1860 | \n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1861 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1862 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1863 | The original variable value is restored when exiting the function.\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1864 | @seealso{crash_dumps_octave_core, octave_core_file_name, octave_core_file_options}\n\octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1865 | @end deftypefn")octave_value_list Foctave_core_file_name (const octave_value_list & args, int nargout) |
1866 | { |
1867 | return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (octave_core_file_name)set_internal_variable (Voctave_core_file_name, args, nargout, "octave_core_file_name", false); |
1868 | } |
1869 | |
1870 | DEFUN (octave_core_file_options, args, nargout,octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1871 | "-*- texinfo -*-\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1872 | @deftypefn {Built-in Function} {@var{val} =} octave_core_file_options ()\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1873 | @deftypefnx {Built-in Function} {@var{old_val} =} octave_core_file_options (@var{new_val})\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1874 | @deftypefnx {Built-in Function} {} octave_core_file_options (@var{new_val}, \"local\")\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1875 | Query or set the internal variable that specifies the options used for\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1876 | saving the workspace data if Octave aborts. The value of\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1877 | @code{octave_core_file_options} should follow the same format as the\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1878 | options for the @code{save} function. The default value is Octave's binary\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1879 | format.\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1880 | \n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1881 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1882 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1883 | The original variable value is restored when exiting the function.\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1884 | @seealso{crash_dumps_octave_core, octave_core_file_name, octave_core_file_limit}\n\octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1885 | @end deftypefn")octave_value_list Foctave_core_file_options (const octave_value_list & args, int nargout) |
1886 | { |
1887 | return SET_NONEMPTY_INTERNAL_STRING_VARIABLE (octave_core_file_options)set_internal_variable (Voctave_core_file_options, args, nargout , "octave_core_file_options", false); |
1888 | } |
1889 | |
1890 | DEFUN (save_header_format_string, args, nargout,octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1891 | "-*- texinfo -*-\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1892 | @deftypefn {Built-in Function} {@var{val} =} save_header_format_string ()\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1893 | @deftypefnx {Built-in Function} {@var{old_val} =} save_header_format_string (@var{new_val})\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1894 | @deftypefnx {Built-in Function} {} save_header_format_string (@var{new_val}, \"local\")\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1895 | Query or set the internal variable that specifies the format\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1896 | string used for the comment line written at the beginning of\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1897 | text-format data files saved by Octave. The format string is\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1898 | passed to @code{strftime} and should begin with the character\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1899 | @samp{#} and contain no newline characters. If the value of\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1900 | @code{save_header_format_string} is the empty string,\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1901 | the header comment is omitted from text-format data files. The\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1902 | default value is\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1903 | @c Set example in small font to prevent overfull line\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1904 | \n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1905 | @smallexample\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1906 | \"# Created by Octave VERSION, %a %b %d %H:%M:%S %Y %Z <USER@@HOST>\"\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1907 | @end smallexample\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1908 | \n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1909 | When called from inside a function with the @qcode{\"local\"} option, the\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1910 | variable is changed locally for the function and any subroutines it calls. \n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1911 | The original variable value is restored when exiting the function.\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1912 | @seealso{strftime, save}\n\octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1913 | @end deftypefn")octave_value_list Fsave_header_format_string (const octave_value_list & args, int nargout) |
1914 | { |
1915 | return SET_INTERNAL_VARIABLE (save_header_format_string)set_internal_variable (Vsave_header_format_string, args, nargout , "save_header_format_string"); |
1916 | } |