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