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