[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: saveing/loading symbol table of annymous functions
From: |
David Bateman |
Subject: |
Re: saveing/loading symbol table of annymous functions |
Date: |
Mon, 14 May 2007 14:45:14 +0200 |
User-agent: |
Thunderbird 1.5.0.7 (X11/20060921) |
David Bateman wrote:
>
> No its missing the header of 116 bytes plus an additional 8 bytes for
> what is called the subsystem data offset and starts with the endianness,
> version number in hex of "0001 494d 0000 0000". One thing I just noticed
> is that the 117 to 124 are different in a file containing an anonymous
> function handle. The file anon2.mat above has "e003 0000 0000 0000",
> whereas a normal file just has 8 spaces (0x20).
>
> Page 1-7 of matfile_format.pdf from the mathworks site states
>
> <quote>
> Header Subsystem Data Offset Field
> Bytes 117 through 124 of the header contain an offset to
> subsystem-specific data in the MAT-file. All zeros or all spaces in this
> field indicate that there is no subsystem-specific data stored in the file.
> </quote>
>
> Funnily the offset 0x3e0 points to the data block containing
> function_handle_workspace which is the embedded matfile....
>
> What I wonder now is if this offset is needed to find the block to
> convert. As at the moment to make my life easy my test files all only
> have a single saved function handle, I now wonder what will happen to
> the file format if it contains multiple variables.. I'll check
>
> In any case the current Octave code ignores bytes 117 to 124 of the
> header of matfiles as well.
>
In fact the function handle workspace doesn't follow the function
handles class 17 block. Rather the header has an offset into the file
where the sub-system workspace is located and all function handle
workspaces have a field MCOS that is a signature and an offset into the
sub-system workspace for the workspace of each of the individual
function handle workspace. There are still some things I don't
understand in the file format for function handles, but I think I have
the loading of function handles working correctly for matlab files. I
think I'd like to see this included in octave and get a little bit of
feedback on issues people have to try and better understand the format
to allow saving to work.
The attached patch also includes a load/save for the octave file formats
for function handles that respects the path to system files, saves the
anonymous handles workspace, includes load/save in mat-file format for
inline functions and updates the Ffunctions function to print the
workspace and be a bit more compatible.
Regards
David
Index: src/load-path.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/load-path.cc,v
retrieving revision 1.14
diff -c -r1.14 load-path.cc
*** src/load-path.cc 27 Feb 2007 19:43:36 -0000 1.14
--- src/load-path.cc 14 May 2007 12:34:40 -0000
***************
*** 50,55 ****
--- 50,61 ----
static std::string Vsystem_path;
+ std::string
+ octave_system_path (void)
+ {
+ return Vsystem_path;
+ }
+
void
load_path::dir_info::update (void)
{
Index: src/load-path.h
===================================================================
RCS file: /usr/local/cvsroot/octave/src/load-path.h,v
retrieving revision 1.6
diff -c -r1.6 load-path.h
*** src/load-path.h 27 Feb 2007 19:43:36 -0000 1.6
--- src/load-path.h 14 May 2007 12:34:40 -0000
***************
*** 341,346 ****
--- 341,348 ----
extern void execute_pkg_add (const std::string& dir);
extern void execute_pkg_del (const std::string& dir);
+ extern std::string octave_system_path (void);
+
#endif
/*
Index: src/load-save.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/load-save.cc,v
retrieving revision 1.221
diff -c -r1.221 load-save.cc
*** src/load-save.cc 26 Apr 2007 15:41:29 -0000 1.221
--- src/load-save.cc 14 May 2007 12:34:41 -0000
***************
*** 348,354 ****
#endif
static load_save_format
! get_file_format (std::istream& file)
{
load_save_format retval = LS_UNKNOWN;
--- 348,354 ----
#endif
static load_save_format
! get_file_format (std::istream& file, const std::string& filename)
{
load_save_format retval = LS_UNKNOWN;
***************
*** 374,380 ****
file.clear ();
file.seekg (0, std::ios::beg);
! err = read_mat5_binary_file_header (file, swap, true);
if (! err)
{
--- 374,380 ----
file.clear ();
file.seekg (0, std::ios::beg);
! err = read_mat5_binary_file_header (file, swap, true, filename);
if (! err)
{
***************
*** 415,421 ****
if (file)
{
! retval = get_file_format (file);
file.close ();
#ifdef HAVE_ZLIB
--- 415,421 ----
if (file)
{
! retval = get_file_format (file, orig_fname);
file.close ();
#ifdef HAVE_ZLIB
***************
*** 426,432 ****
if (gzfile)
{
! retval = get_file_format (gzfile);
gzfile.close ();
}
}
--- 426,432 ----
if (gzfile)
{
! retval = get_file_format (gzfile, orig_fname);
gzfile.close ();
}
}
***************
*** 925,931 ****
else if (format == LS_MAT5_BINARY
|| format == LS_MAT7_BINARY)
{
! if (read_mat5_binary_file_header (file, swap, false) < 0)
{
if (file) file.close ();
return retval;
--- 925,931 ----
else if (format == LS_MAT5_BINARY
|| format == LS_MAT7_BINARY)
{
! if (read_mat5_binary_file_header (file, swap, false,
orig_fname) < 0)
{
if (file) file.close ();
return retval;
***************
*** 959,965 ****
else if (format == LS_MAT5_BINARY
|| format == LS_MAT7_BINARY)
{
! if (read_mat5_binary_file_header (file, swap, false) < 0)
{
if (file) file.close ();
return retval;
--- 959,965 ----
else if (format == LS_MAT5_BINARY
|| format == LS_MAT7_BINARY)
{
! if (read_mat5_binary_file_header (file, swap, false,
orig_fname) < 0)
{
if (file) file.close ();
return retval;
***************
*** 1400,1405 ****
--- 1400,1409 ----
std::ios::openmode mode = std::ios::out;
+ // Matlab v7 files are always compressed
+ if (format == LS_MAT7_BINARY)
+ use_zlib = false;
+
if (format == LS_BINARY
#ifdef HAVE_HDF5
|| format == LS_HDF5
***************
*** 1667,1672 ****
--- 1671,1680 ----
std::ios::openmode mode = std::ios::out;
+ // Matlab v7 files are always compressed
+ if (format == LS_MAT7_BINARY)
+ use_zlib = false;
+
if (format == LS_BINARY
#ifdef HAVE_HDF5
|| format == LS_HDF5
Index: src/ls-mat5.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ls-mat5.cc,v
retrieving revision 1.39
diff -c -r1.39 ls-mat5.cc
*** src/ls-mat5.cc 10 Feb 2007 02:10:21 -0000 1.39
--- src/ls-mat5.cc 14 May 2007 12:34:41 -0000
***************
*** 48,62 ****
--- 48,65 ----
#include "oct-time.h"
#include "quit.h"
#include "str-vec.h"
+ #include "file-stat.h"
#include "Cell.h"
#include "defun.h"
#include "error.h"
#include "gripes.h"
#include "load-save.h"
+ #include "load-path.h"
#include "oct-obj.h"
#include "oct-map.h"
#include "ov-cell.h"
+ #include "ov-fcn-inline.h"
#include "pager.h"
#include "pt-exp.h"
#include "symtab.h"
***************
*** 70,81 ****
--- 73,91 ----
#include "ls-utils.h"
#include "ls-mat5.h"
+ #include "parse.h"
+ #include "defaults.h"
+
#ifdef HAVE_ZLIB
#include <zlib.h>
#endif
#define PAD(l) (((l) > 0 && (l) <= 4) ? 4 : (((l)+7)/8)*8)
+
+ // The subsystem data block
+ static octave_value subsys_ov;
+
// FIXME -- the following enum values should be the same as the
// mxClassID values in mexproto.h, but it seems they have also changed
// over time. What is the correct way to handle this and maintain
***************
*** 100,106 ****
MAT_FILE_UINT32_CLASS, // 32 bit unsigned integer
MAT_FILE_INT64_CLASS, // 64 bit signed integer
MAT_FILE_UINT64_CLASS, // 64 bit unsigned integer
! MAT_FILE_FUNCTION_CLASS // Function handle
};
// Read COUNT elements of data from IS in the format specified by TYPE,
--- 110,117 ----
MAT_FILE_UINT32_CLASS, // 32 bit unsigned integer
MAT_FILE_INT64_CLASS, // 64 bit signed integer
MAT_FILE_UINT64_CLASS, // 64 bit unsigned integer
! MAT_FILE_FUNCTION_CLASS, // Function handle
! MAT_FILE_WORKSPACE_CLASS // Workspace (undocumented)
};
// Read COUNT elements of data from IS in the format specified by TYPE,
***************
*** 397,402 ****
--- 408,415 ----
oct_mach_info::float_format flt_fmt = oct_mach_info::flt_fmt_unknown;
int32_t type = 0;
+ std::string classname;
+ bool isclass = false;
bool imag;
bool logicalvar;
enum arrayclasstype arrayclass;
***************
*** 407,413 ****
int32_t element_length;
std::streampos pos;
int16_t number;
! number = *(int16_t *)"\x00\x01";
global = false;
--- 420,426 ----
int32_t element_length;
std::streampos pos;
int16_t number;
! number = *(reinterpret_cast<const int16_t *>("\x00\x01"));
global = false;
***************
*** 469,474 ****
--- 482,488 ----
if (type != miMATRIX)
{
+ pos = is.tellg ();
error ("load: invalid element type = %d", type);
goto early_read_error;
}
***************
*** 496,522 ****
read_int (is, swap, nzmax); // max number of non-zero in sparse
// dimensions array subelement
! {
! int32_t dim_len;
! if (read_mat5_tag (is, swap, type, dim_len) || type != miINT32)
! {
! error ("load: invalid dimensions array subelement");
! goto early_read_error;
! }
! int ndims = dim_len / 4;
! dims.resize (ndims);
! for (int i = 0; i < ndims; i++)
! {
! int32_t n;
! read_int (is, swap, n);
! dims(i) = n;
! }
! std::streampos tmp_pos = is.tellg ();
! is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (dim_len) -
dim_len));
! }
if (read_mat5_tag (is, swap, type, len) || type != miINT8)
{
--- 510,544 ----
read_int (is, swap, nzmax); // max number of non-zero in sparse
// dimensions array subelement
! if (arrayclass != MAT_FILE_WORKSPACE_CLASS)
! {
! int32_t dim_len;
! if (read_mat5_tag (is, swap, type, dim_len) || type != miINT32)
! {
! error ("load: invalid dimensions array subelement");
! goto early_read_error;
! }
! int ndims = dim_len / 4;
! dims.resize (ndims);
! for (int i = 0; i < ndims; i++)
! {
! int32_t n;
! read_int (is, swap, n);
! dims(i) = n;
! }
! std::streampos tmp_pos = is.tellg ();
! is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (dim_len) -
dim_len));
! }
! else
! {
! // Why did mathworks decide to not have dims for a workspace!!!
! dims.resize(2);
! dims(0) = 1;
! dims(1) = 1;
! }
if (read_mat5_tag (is, swap, type, len) || type != miINT8)
{
***************
*** 571,580 ****
}
break;
- case MAT_FILE_OBJECT_CLASS:
- warning ("load: objects are not implemented");
- goto skip_ahead;
-
case MAT_FILE_SPARSE_CLASS:
#if SIZEOF_INT != SIZEOF_OCTAVE_IDX_TYPE
warning ("load: sparse objects are not implemented");
--- 593,598 ----
***************
*** 707,719 ****
else
tc = sm;
}
- break;
#endif
case MAT_FILE_FUNCTION_CLASS:
! warning ("load: function handles are not implemented");
! goto skip_ahead;
case MAT_FILE_STRUCT_CLASS:
{
Octave_map m (dim_vector (1, 1));
--- 725,1034 ----
else
tc = sm;
}
#endif
+ break;
case MAT_FILE_FUNCTION_CLASS:
! {
! octave_value tc2;
! std::string nm
! = read_mat5_binary_element (is, filename, swap, global, tc2);
!
! if (! is || error_state)
! goto data_read_error;
!
! // Octave can handle both "/" and "\" as a directry seperator
! // and so can ignore the seperator field of m0. I think the
! // sentinel field is also save to ignore.
! Octave_map m0 = tc2.map_value();
! Octave_map m1 = m0.contents("function_handle")(0).map_value();
! std::string ftype = m1.contents("type")(0).string_value();
! std::string fname = m1.contents("function")(0).string_value();
! std::string fpath = m1.contents("file")(0).string_value();
!
! if (ftype == "simple" || ftype == "scopedfunction")
! {
! if (fpath.length() == 0)
! // We have a builtin function
! tc = make_fcn_handle (fname);
! else
! {
! std::string mroot =
! m0.contents("matlabroot")(0).string_value();
!
! if ((fpath.length () >= mroot.length ()) &&
! fpath.substr(0, mroot.length()) == mroot &&
! OCTAVE_EXEC_PREFIX != mroot)
! {
! // If fpath starts with matlabroot, and matlabroot
! // doesn't equal octave_config_info ("exec_prefix")
! // then the function points to a version of Octave
! // or Matlab other than the running version. In that
! // case we replace with the same function in the
! // running version of Octave?
!
! // First check if just replacing matlabroot is enough
! std::string str = OCTAVE_EXEC_PREFIX +
! fpath.substr (mroot.length ());
! file_stat fs (str);
!
! if (fs.exists ())
! {
! symbol_record *sr = fbi_sym_tab->lookup (str, true);
!
! if (sr)
! {
! load_fcn_from_file (sr, false);
!
! tc = octave_value (new octave_fcn_handle
! (sr->def (), fname));
!
! // The next two lines are needed to force the
! // definition of the function back to the one
! // that is on the user path.
! sr = fbi_sym_tab->lookup (fname, true);
!
! load_fcn_from_file (sr, false);
! }
! }
! else
! {
! // Next just search for it anywhere in the
! // system path
! string_vector names(3);
! names(0) = fname + ".oct";
! names(1) = fname + ".mex";
! names(2) = fname + ".m";
!
! dir_path p (octave_system_path ());
!
! str = octave_env::make_absolute
! (p.find_first_of (names), octave_env::getcwd ());
!
! symbol_record *sr = fbi_sym_tab->lookup (str, true);
!
! if (sr)
! {
! load_fcn_from_file (sr, false);
!
! tc = octave_value (new octave_fcn_handle
! (sr->def (), fname));
!
! // The next two lines are needed to force the
! // definition of the function back to the one
! // that is on the user path.
! sr = fbi_sym_tab->lookup (fname, true);
!
! load_fcn_from_file (sr, false);
! }
! else
! {
! warning ("load: can't find the file %s",
! fpath.c_str());
! goto skip_ahead;
! }
! }
! }
! else
! {
! symbol_record *sr = fbi_sym_tab->lookup (fpath, true);
!
! if (sr)
! {
! load_fcn_from_file (sr, false);
!
! tc = octave_value (new octave_fcn_handle (sr->def (),
! fname));
!
! sr = fbi_sym_tab->lookup (fname, true);
!
! load_fcn_from_file (sr, false);
! }
! else
! {
! warning ("load: can't find the file %s",
! fpath.c_str());
! goto skip_ahead;
! }
! }
! }
! }
! else if (ftype == "nested")
! {
! warning ("load: can't load nested function");
! goto skip_ahead;
! }
! else if (ftype == "anonymous")
! {
! Octave_map m2 = m1.contents("workspace")(0).map_value();
! uint32NDArray MCOS = m2.contents("MCOS")(0).uint32_array_value();
! octave_idx_type off = static_cast<octave_idx_type>(double (MCOS
(4)));
! m2 = subsys_ov.map_value();
! m2 = m2.contents("MCOS")(0).map_value();
! tc2 = m2.contents("MCOS")(0).cell_value()(1 + off).cell_value()(1);
! m2 = tc2.map_value();
! symbol_table *local_sym_tab = 0;
! if (m2.length() > 0)
! {
! octave_value tmp;
!
! local_sym_tab = new symbol_table (((m2.length() + 1) & ~1),
! "LOCAL");
!
! for (Octave_map::iterator p0 = m2.begin() ;
! p0 != m2.end(); p0++)
! {
! std::string key = m2.key(p0);
! octave_value val = m2.contents(p0)(0);
!
! symbol_record *sr = local_sym_tab->lookup (key, true);
!
! if (sr)
! sr->define (val);
! else
! {
! error ("load: failed to load anonymous function
handle");
! goto skip_ahead;
! }
! }
! }
!
! unwind_protect::begin_frame ("anon_mat5_load");
! unwind_protect_ptr (curr_sym_tab);
!
! if (local_sym_tab)
! curr_sym_tab = local_sym_tab;
!
! int parse_status;
! octave_value anon_fcn_handle =
! eval_string (fname.substr (4), true, parse_status);
!
! if (parse_status == 0)
! {
! octave_fcn_handle *fh =
! anon_fcn_handle.fcn_handle_value ();
! if (fh)
! tc = new octave_fcn_handle (fh->fcn_val(), "@<anonymous>");
! else
! {
! error ("load: failed to load anonymous function handle");
! goto skip_ahead;
! }
! }
! else
! {
! error ("load: failed to load anonymous function handle");
! goto skip_ahead;
! }
!
! unwind_protect::run_frame ("anon_mat5_load");
!
! if (local_sym_tab)
! delete local_sym_tab;
! }
! else
! {
! error ("load: invalid function handle type");
! goto skip_ahead;
! }
! }
! break;
!
! case MAT_FILE_WORKSPACE_CLASS:
! {
! Octave_map m (dim_vector (1, 1));
! int n_fields = 2;
! string_vector field (n_fields);
!
! for (int i = 0; i < n_fields; i++)
! {
! int32_t fn_type;
! int32_t fn_len;
! if (read_mat5_tag (is, swap, fn_type, fn_len) || fn_type != miINT8)
! {
! error ("load: invalid field name subelement");
! goto data_read_error;
! }
!
! OCTAVE_LOCAL_BUFFER (char, elname, fn_len + 1);
!
! std::streampos tmp_pos = is.tellg ();
!
! if (fn_len)
! {
! if (! is.read (elname, fn_len))
! goto data_read_error;
!
! is.seekg (tmp_pos +
! static_cast<std::streamoff> (PAD (fn_len)));
! }
!
! elname[fn_len] = '\0';
!
! field(i) = elname;
! }
!
! std::vector<Cell> elt (n_fields);
!
! for (octave_idx_type i = 0; i < n_fields; i++)
! elt[i] = Cell (dims);
!
! octave_idx_type n = dims.numel ();
!
! // fields subelements
! for (octave_idx_type j = 0; j < n; j++)
! {
! for (octave_idx_type i = 0; i < n_fields; i++)
! {
! if (field(i) == "MCOS")
! {
! octave_value fieldtc;
! read_mat5_binary_element (is, filename, swap, global,
! fieldtc);
! if (! is || error_state)
! goto data_read_error;
!
! elt[i](j) = fieldtc;
! }
! else
! elt[i](j) = octave_value ();
! }
! }
!
! for (octave_idx_type i = 0; i < n_fields; i++)
! m.assign (field (i), elt[i]);
! tc = m;
! }
! break;
!
! case MAT_FILE_OBJECT_CLASS:
! {
! isclass = true;
!
! if (read_mat5_tag (is, swap, type, len) || type != miINT8)
! {
! error ("load: invalid class name");
! goto skip_ahead;
! }
!
! {
! OCTAVE_LOCAL_BUFFER (char, name, len+1);
!
! std::streampos tmp_pos = is.tellg ();
!
! if (len)
! {
! if (! is.read (name, len ))
! goto data_read_error;
!
! is.seekg (tmp_pos + static_cast<std::streamoff> (PAD (len)));
! }
+ name[len] = '\0';
+ classname = name;
+ }
+ }
+ // Fall-through
case MAT_FILE_STRUCT_CLASS:
{
Octave_map m (dim_vector (1, 1));
***************
*** 784,790 ****
}
}
! tc = m;
}
break;
--- 1099,1122 ----
}
}
! if (isclass)
! {
! if (classname == "inline")
! {
! // inline is not an object in Octave but rather an
! // overload of a function handle. Special case.
! tc =
! new octave_fcn_inline (m.contents("expr")(0).string_value(),
! m.contents("args")(0).string_value());
! }
! else
! {
! warning ("load: objects are not implemented");
! goto skip_ahead;
! }
! }
! else
! tc = m;
}
break;
***************
*** 975,983 ****
}
int
! read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet)
{
int16_t version=0, magic=0;
is.seekg (124, std::ios::beg);
is.read (reinterpret_cast<char *> (&version), 2);
--- 1307,1320 ----
}
int
! read_mat5_binary_file_header (std::istream& is, bool& swap, bool quiet,
! const std::string& filename)
{
int16_t version=0, magic=0;
+ uint64_t subsys_offset;
+
+ is.seekg (116, std::ios::beg);
+ is.read (reinterpret_cast<char *> (&subsys_offset), 8);
is.seekg (124, std::ios::beg);
is.read (reinterpret_cast<char *> (&version), 2);
***************
*** 1001,1006 ****
--- 1338,1385 ----
warning ("load: found version %d binary MAT file, "
"but only prepared for version 1", version);
+ if (swap)
+ swap_bytes<8> (&subsys_offset, 1);
+
+ if (subsys_offset != 0x2020202020202020ULL && subsys_offset != 0ULL)
+ {
+ // Read the subsystem data block
+ is.seekg (subsys_offset, std::ios::beg);
+
+ octave_value tc;
+ bool global;
+ read_mat5_binary_element (is, filename, swap, global, tc);
+
+ if (!is || error_state)
+ return -1;
+
+ if (tc.is_uint8_type ())
+ {
+ const uint8NDArray itmp = tc.uint8_array_value();
+ octave_idx_type ilen = itmp.nelem ();
+
+ // Why should I have to initialize outbuf as just overwrite
+ std::string outbuf (ilen - 7, ' ');
+
+ // FIXME -- find a way to avoid casting away const here
+ char *ctmp = const_cast<char *> (outbuf.c_str ());
+ for (octave_idx_type j = 8; j < ilen; j++)
+ ctmp [j - 8] = itmp (j);
+
+ std::istringstream fh_ws (outbuf);
+
+ read_mat5_binary_element (fh_ws, filename, swap, global, subsys_ov);
+
+ if (error_state)
+ return -1;
+ }
+ else
+ return -1;
+
+ // Reposition to just after the header
+ is.seekg (128, std::ios::beg);
+ }
+
return 0;
}
***************
*** 1415,1426 ****
ret += save_mat5_array_length (m.fortran_vec (), m.nelem (),
save_as_floats);
}
! else if (tc.is_map ())
{
int fieldcnt = 0;
const Octave_map m = tc.map_value ();
int nel = m.numel ();
for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
fieldcnt++;
--- 1794,1809 ----
ret += save_mat5_array_length (m.fortran_vec (), m.nelem (),
save_as_floats);
}
! else if (tc.is_map () || tc.is_inline_function ())
{
int fieldcnt = 0;
const Octave_map m = tc.map_value ();
int nel = m.numel ();
+ if (tc.is_inline_function ())
+ // length of "inline" is 6
+ ret += 8 + PAD (6 > max_namelen ? max_namelen : 6);
+
for (Octave_map::const_iterator i = m.begin (); i != m.end (); i++)
fieldcnt++;
***************
*** 1559,1564 ****
--- 1942,1949 ----
flags |= MAT_FILE_STRUCT_CLASS;
else if (tc.is_cell ())
flags |= MAT_FILE_CELL_CLASS;
+ else if (tc.is_inline_function ())
+ flags |= MAT_FILE_OBJECT_CLASS;
else
{
gripe_wrong_type_arg ("save", tc, false);
***************
*** 1746,1757 ****
write_mat5_array (os, ::real (m_cmplx), save_as_floats);
write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
}
! else if (tc.is_map ())
{
- // an Octave structure */
- // recursively write each element of the structure
const Octave_map m = tc.map_value ();
{
char buf[64];
int32_t maxfieldnamelength = max_namelen + 1;
--- 2131,2158 ----
write_mat5_array (os, ::real (m_cmplx), save_as_floats);
write_mat5_array (os, ::imag (m_cmplx), save_as_floats);
}
! else if (tc.is_map () || tc.is_inline_function())
{
const Octave_map m = tc.map_value ();
+ if (tc.is_inline_function ())
+ {
+ std::string classname = "inline";
+ int namelen = classname.length ();
+ if (namelen > max_namelen)
+ namelen = max_namelen; // only 31 or 63 char names permitted
+
+ int paddedlength = PAD (namelen);
+
+ write_mat5_tag (os, miINT8, namelen);
+ OCTAVE_LOCAL_BUFFER (char, paddedname, paddedlength);
+ memset (paddedname, 0, paddedlength);
+ strncpy (paddedname, classname.c_str (), namelen);
+ os.write (paddedname, paddedlength);
+ }
+
+ // an Octave structure */
+ // recursively write each element of the structure
{
char buf[64];
int32_t maxfieldnamelength = max_namelen + 1;
Index: src/ls-mat5.h
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ls-mat5.h,v
retrieving revision 1.3
diff -c -r1.3 ls-mat5.h
*** src/ls-mat5.h 26 Apr 2005 19:24:33 -0000 1.3
--- src/ls-mat5.h 14 May 2007 12:34:41 -0000
***************
*** 48,54 ****
extern int
read_mat5_binary_file_header (std::istream& is, bool& swap,
! bool quiet = false);
extern std::string
read_mat5_binary_element (std::istream& is, const std::string& filename,
bool swap, bool& global, octave_value& tc);
--- 48,55 ----
extern int
read_mat5_binary_file_header (std::istream& is, bool& swap,
! bool quiet = false,
! const std::string& filename = std::string());
extern std::string
read_mat5_binary_element (std::istream& is, const std::string& filename,
bool swap, bool& global, octave_value& tc);
Index: src/ov-fcn-handle.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-fcn-handle.cc,v
retrieving revision 1.37
diff -c -r1.37 ov-fcn-handle.cc
*** src/ov-fcn-handle.cc 3 Apr 2007 19:39:12 -0000 1.37
--- src/ov-fcn-handle.cc 14 May 2007 12:34:41 -0000
***************
*** 46,54 ****
--- 46,60 ----
#include "pt-assign.h"
#include "variables.h"
#include "parse.h"
+ #include "unwind-prot.h"
+ #include "defaults.h"
+ #include "file-stat.h"
+ #include "load-path.h"
+ #include "oct-env.h"
#include "byte-swap.h"
#include "ls-oct-ascii.h"
+ #include "ls-oct-binary.h"
#include "ls-hdf5.h"
#include "ls-utils.h"
***************
*** 144,157 ****
}
bool
! octave_fcn_handle::save_ascii (std::ostream& os, bool&)
{
! os << nm << "\n";
if (nm == "@<anonymous>")
{
print_raw (os, true);
os << "\n";
}
return true;
--- 150,308 ----
}
bool
! octave_fcn_handle::set_fcn (const std::string &octaveroot,
! const std::string& fpath)
{
! bool success = true;
+ if (octaveroot.length () != 0 &&
+ fpath.length () >= octaveroot.length () &&
+ fpath.substr (0, octaveroot.length ()) == octaveroot &&
+ OCTAVE_EXEC_PREFIX != octaveroot)
+ {
+ // First check if just replacing matlabroot is enough
+ std::string str = OCTAVE_EXEC_PREFIX +
+ fpath.substr (octaveroot.length ());
+ file_stat fs (str);
+
+ if (fs.exists ())
+ {
+ symbol_record *sr = fbi_sym_tab->lookup (str, true);
+
+ if (sr)
+ {
+ load_fcn_from_file (sr, false);
+
+ fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
+
+ // The next two lines are needed to force the
+ // definition of the function back to the one
+ // that is on the user path.
+ sr = fbi_sym_tab->lookup (nm, true);
+
+ load_fcn_from_file (sr, false);
+
+ }
+ else
+ {
+ error ("function handle points to non-existent function");
+ success = false;
+ }
+ }
+ else
+ {
+ // Next just search for it anywhere in the system path
+ string_vector names(3);
+ names(0) = nm + ".oct";
+ names(1) = nm + ".mex";
+ names(2) = nm + ".m";
+
+ dir_path p (octave_system_path ());
+
+ str = octave_env::make_absolute
+ (p.find_first_of (names), octave_env::getcwd ());
+
+ symbol_record *sr = fbi_sym_tab->lookup (str, true);
+
+ if (sr)
+ {
+ load_fcn_from_file (sr, false);
+
+ fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
+
+ // The next two lines are needed to force the
+ // definition of the function back to the one
+ // that is on the user path.
+ sr = fbi_sym_tab->lookup (nm, true);
+
+ load_fcn_from_file (sr, false);
+ }
+ else
+ {
+ error ("function handle points to non-existent function");
+ success = false;
+ }
+ }
+ }
+ else
+ {
+ if (fpath.length () > 0)
+ {
+ symbol_record *sr = fbi_sym_tab->lookup (fpath, true);
+
+ if (sr)
+ {
+ load_fcn_from_file (sr, false);
+
+ fcn = octave_value (new octave_fcn_handle (sr->def (), nm));
+
+ sr = fbi_sym_tab->lookup (nm, true);
+
+ load_fcn_from_file (sr, false);
+ }
+ else
+ {
+ error ("function handle points to non-existent function");
+ success = false;
+ }
+ }
+ else
+ {
+ fcn = lookup_function (nm);
+ if (! fcn.is_function ())
+ {
+ error ("function handle points to non-existent function");
+ success = false;
+ }
+ }
+ }
+
+ return success;
+ }
+
+ bool
+ octave_fcn_handle::save_ascii (std::ostream& os, bool& infnan_warned)
+ {
if (nm == "@<anonymous>")
{
+ os << nm << "\n";
+
print_raw (os, true);
os << "\n";
+
+ if (fcn.is_undefined())
+ return false;
+
+ octave_user_function *f = fcn.user_function_value ();
+
+ Array<symbol_record *> vars = f->sym_tab()->symbol_list();
+ octave_idx_type varlen = vars.length();
+
+ // Exclude undefined values like __retval__
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (! vars(i)->is_defined ())
+ varlen--;
+ }
+
+ if (varlen > 0)
+ {
+ os << "# length: " << varlen << "\n";
+
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (vars(i)->is_defined () &&
+ ! save_ascii_data (os, vars(i)->def(), vars(i)->name(),
+ infnan_warned, false, 0))
+ return os;
+ }
+ }
+ }
+ else
+ {
+ os << "# octaveroot: " << OCTAVE_EXEC_PREFIX << "\n";
+ os << "# path: " << user_function_value ()-> fcn_file_name () << "\n";
+ os << nm << "\n";
}
return true;
***************
*** 160,169 ****
--- 311,338 ----
bool
octave_fcn_handle::load_ascii (std::istream& is)
{
+ bool success = true;
+
+ std::streampos pos = is.tellg ();
+ std::string octaveroot = extract_keyword (is, "octaveroot", true);
+ if (octaveroot.length() == 0)
+ {
+ is.seekg (pos);
+ is.clear ();
+ }
+ pos = is.tellg ();
+ std::string fpath = extract_keyword (is, "path", true);
+ if (fpath.length() == 0)
+ {
+ is.seekg (pos);
+ is.clear ();
+ }
+
is >> nm;
if (nm == "@<anonymous>")
{
+ octave_idx_type len = 0;
char c;
std::ostringstream buf;
***************
*** 187,242 ****
}
}
! int parse_status;
! octave_value anon_fcn_handle = eval_string (buf.str (), true,
! parse_status);
! if (parse_status == 0)
{
! octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
! if (fh)
! fcn = fh->fcn;
! else
! return false;
}
else
- return false;
- }
- else
- {
- fcn = lookup_function (nm);
- if (! fcn.is_function ())
{
! error ("function handle points to non-existent function");
! return false;
}
}
! return true;
}
bool
! octave_fcn_handle::save_binary (std::ostream& os, bool&)
{
- int32_t tmp = nm.length ();
- os.write (reinterpret_cast<char *> (&tmp), 4);
- os.write (nm.c_str (), nm.length ());
if (nm == "@<anonymous>")
{
std::ostringstream buf;
print_raw (buf, true);
std::string stmp = buf.str ();
tmp = stmp.length ();
os.write (reinterpret_cast<char *> (&tmp), 4);
os.write (stmp.c_str (), stmp.length ());
}
return true;
}
bool
octave_fcn_handle::load_binary (std::istream& is, bool swap,
! oct_mach_info::float_format)
{
int32_t tmp;
if (! is.read (reinterpret_cast<char *> (&tmp), 4))
return false;
--- 356,541 ----
}
}
! pos = is.tellg ();
! symbol_table *local_sym_tab = 0;
! if (extract_keyword (is, "length", len, true) && len >= 0)
{
! if (len > 0)
! {
! octave_idx_type nlen = len;
! if (nlen % 2)
! nlen++;
!
! local_sym_tab = new symbol_table (((nlen + 1) & ~1) , "LOCAL");
!
! for (octave_idx_type i = 0; i < len; i++)
! {
! octave_value t2;
! bool dummy;
!
! std::string name
! = read_ascii_data (is, std::string (), dummy, t2, i);
!
! if (!is)
! {
! error ("load: failed to load anonymous function handle");
! break;
! }
!
! symbol_record *sr = local_sym_tab->lookup (name, true);
!
! if (sr)
! sr->define (t2);
! else
! {
! error ("load: failed to load anonymous function handle");
! success = false;
! break;
! }
! }
! }
}
else
{
! is.seekg (pos);
! is.clear ();
}
+
+ if (is && success)
+ {
+ unwind_protect::begin_frame ("anon_ascii_load");
+ unwind_protect_ptr (curr_sym_tab);
+
+ if (local_sym_tab)
+ curr_sym_tab = local_sym_tab;
+
+ int parse_status;
+ octave_value anon_fcn_handle =
+ eval_string (buf.str (), true, parse_status);
+
+ if (parse_status == 0)
+ {
+ octave_fcn_handle *fh =
+ anon_fcn_handle.fcn_handle_value ();
+ if (fh)
+ fcn = fh->fcn;
+ else
+ success = false;
+ }
+ else
+ success = false;
+
+ unwind_protect::run_frame ("anon_ascii_load");
+ }
+ else
+ success = false;
+
+ if (local_sym_tab)
+ delete local_sym_tab;
}
+ else
+ success = set_fcn (octaveroot, fpath);
! return success;
}
+ /*
+
+ %!test
+ %! a = 2;
+ %! f = @(x) a + x;
+ %! g = @(x) 2 * x;
+ %! h = @log2;
+ %! f2 = f;
+ %! g2 = g;
+ %! h2 = h;
+ %! nm = tmpnam();
+ %! unwind_protect
+ %! save ("-text", nm, "f2", "g2", "h2");
+ %! clear f2 g2 h2
+ %! load (nm);
+ %! assert (f(2),f2(2));
+ %! assert (g(2),g2(2));
+ %! assert (g(3),g2(3));
+ %! unlink ("test.mat");
+ %! save ("-text", nm, "f2", "g2", "h2");
+ %! unwind_protect_cleanup
+ %! unlink (nm);
+ %! end_unwind_protect
+
+ */
+
bool
! octave_fcn_handle::save_binary (std::ostream& os, bool& save_as_floats)
{
if (nm == "@<anonymous>")
{
+ std::ostringstream nmbuf;
+
+ if (fcn.is_undefined())
+ return false;
+
+ octave_user_function *f = fcn.user_function_value ();
+
+ Array<symbol_record *> vars = f->sym_tab()->symbol_list();
+ octave_idx_type varlen = vars.length();
+
+ // Exclude undefined values like __retval__
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (! vars(i)->is_defined ())
+ varlen--;
+ }
+
+ if (varlen > 0)
+ nmbuf << nm << " " << varlen;
+ else
+ nmbuf << nm;
+
+ std::string buf_str = nmbuf.str();
+ int32_t tmp = buf_str.length ();
+ os.write (reinterpret_cast<char *> (&tmp), 4);
+ os.write (buf_str.c_str (), buf_str.length ());
+
std::ostringstream buf;
print_raw (buf, true);
std::string stmp = buf.str ();
tmp = stmp.length ();
os.write (reinterpret_cast<char *> (&tmp), 4);
os.write (stmp.c_str (), stmp.length ());
+
+ if (varlen > 0)
+ {
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (vars(i)->is_defined () &&
+ ! save_binary_data (os, vars(i)->def(), vars(i)->name(),
+ "", 0, save_as_floats))
+ return os;
+ }
+ }
+ }
+ else
+ {
+ std::ostringstream nmbuf;
+
+ nmbuf << nm << "\n" << OCTAVE_EXEC_PREFIX << "\n"
+ << user_function_value ()-> fcn_file_name () ;
+
+ std::string buf_str = nmbuf.str ();
+ int32_t tmp = buf_str.length ();
+ os.write (reinterpret_cast<char *> (&tmp), 4);
+ os.write (buf_str.c_str (), buf_str.length ());
}
return true;
}
bool
octave_fcn_handle::load_binary (std::istream& is, bool swap,
! oct_mach_info::float_format fmt)
{
+ bool success = true;
int32_t tmp;
if (! is.read (reinterpret_cast<char *> (&tmp), 4))
return false;
***************
*** 250,257 ****
if (! is)
return false;
! if (nm == "@<anonymous>")
{
if (! is.read (reinterpret_cast<char *> (&tmp), 4))
return false;
if (swap)
--- 549,565 ----
if (! is)
return false;
! if (nm.length() >= 12 && nm.substr (0, 12) == "@<anonymous>")
{
+ octave_idx_type len = 0;
+
+ if (nm.length() > 12)
+ {
+ std::istringstream nm_is (nm.substr(12));
+ nm_is >> len;
+ nm = nm.substr(0,12);
+ }
+
if (! is.read (reinterpret_cast<char *> (&tmp), 4))
return false;
if (swap)
***************
*** 260,295 ****
OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
is.read (ctmp2, tmp);
! int parse_status;
! octave_value anon_fcn_handle = eval_string (ctmp2, true, parse_status);
! if (parse_status == 0)
{
! octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
! if (fh)
! fcn = fh->fcn;
else
! return false;
}
! else
! return false;
}
else
{
! fcn = lookup_function (nm);
! if (! fcn.is_function ())
{
! error ("function handle points to non-existent function");
! return false;
}
! }
! return true;
}
#if defined (HAVE_HDF5)
bool
octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name,
! bool /* save_as_floats */)
{
hid_t group_hid = -1;
group_hid = H5Gcreate (loc_id, name, 0);
--- 568,693 ----
OCTAVE_LOCAL_BUFFER (char, ctmp2, tmp+1);
is.read (ctmp2, tmp);
! symbol_table *local_sym_tab = 0;
! if (len > 0)
! {
! octave_idx_type nlen = len;
! if (nlen % 2)
! nlen++;
!
! local_sym_tab = new symbol_table (nlen, "LOCAL");
!
! for (octave_idx_type i = 0; i < len; i++)
! {
! octave_value t2;
! bool dummy;
! std::string doc;
!
! std::string name =
! read_binary_data (is, swap, fmt, std::string (),
! dummy, t2, doc);
!
! if (!is)
! {
! error ("load: failed to load anonymous function handle");
! break;
! }
!
! symbol_record *sr = local_sym_tab->lookup (name, true);
!
! if (sr)
! {
! sr->define (t2);
! sr->document (doc);
! }
! else
! {
! error ("load: failed to load anonymous function handle");
! success = false;
! break;
! }
! }
! }
! if (is && success)
{
! unwind_protect::begin_frame ("anon_binary_load");
! unwind_protect_ptr (curr_sym_tab);
!
! if (local_sym_tab)
! curr_sym_tab = local_sym_tab;
!
! int parse_status;
! octave_value anon_fcn_handle =
! eval_string (ctmp2, true, parse_status);
!
! if (parse_status == 0)
! {
! octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
! if (fh)
! fcn = fh->fcn;
! else
! success = false;
! }
else
! success = false;
!
! unwind_protect::run_frame ("anon_binary_load");
}
!
! if (local_sym_tab)
! delete local_sym_tab;
}
else
{
! std::string octaveroot;
! std::string fpath;
!
! if (nm.find_first_of ("\n") != NPOS)
{
! size_t pos1 = nm.find_first_of ("\n");
! size_t pos2 = nm.find_first_of ("\n", pos1 + 1);
! octaveroot = nm.substr (pos1 + 1, pos2 - pos1 - 1);
! fpath = nm.substr (pos2 + 1);
! nm = nm.substr (0, pos1);
}
!
! success = set_fcn (octaveroot, fpath);
! }
!
! return success;
}
+ /*
+
+ %!test
+ %! a = 2;
+ %! f = @(x) a + x;
+ %! g = @(x) 2 * x;
+ %! h = @log2;
+ %! f2 = f;
+ %! g2 = g;
+ %! h2 = h;
+ %! nm = tmpnam();
+ %! unwind_protect
+ %! save ("-binary", nm, "f2", "g2", "h2");
+ %! clear f2 g2 h2
+ %! load (nm);
+ %! assert (f(2),f2(2));
+ %! assert (g(2),g2(2));
+ %! assert (g(3),g2(3));
+ %! unlink ("test.mat");
+ %! save ("-binary", nm, "f2", "g2", "h2");
+ %! unwind_protect_cleanup
+ %! unlink (nm);
+ %! end_unwind_protect
+
+ */
+
#if defined (HAVE_HDF5)
bool
octave_fcn_handle::save_hdf5 (hid_t loc_id, const char *name,
! bool save_as_floats)
{
hid_t group_hid = -1;
group_hid = H5Gcreate (loc_id, name, 0);
***************
*** 355,360 ****
--- 753,869 ----
}
H5Dclose (data_hid);
+
+ octave_user_function *f = fcn.user_function_value ();
+ Array<symbol_record *> vars = f->sym_tab()->symbol_list();
+ octave_idx_type varlen = vars.length();
+
+ // Exclude undefined values like __retval__
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (! vars(i)->is_defined ())
+ varlen--;
+ }
+
+ if (varlen > 0)
+ {
+ hid_t as_id = H5Screate (H5S_SCALAR);
+
+ if (as_id >= 0)
+ {
+ hid_t a_id = H5Acreate (group_hid, "SYMBOL_TABLE",
+ H5T_NATIVE_IDX, as_id, H5P_DEFAULT);
+
+ if (a_id >= 0)
+ {
+ retval = (H5Awrite (a_id, H5T_NATIVE_IDX, &varlen) >= 0);
+
+ H5Aclose (a_id);
+ }
+ else
+ retval = false;
+
+ H5Sclose (as_id);
+ }
+ else
+ retval = false;
+
+ data_hid = H5Gcreate (group_hid, "symbol table", 0);
+ if (data_hid < 0)
+ {
+ H5Sclose (space_hid);
+ H5Tclose (type_hid);
+ H5Gclose (group_hid);
+ return false;
+ }
+
+ for (octave_idx_type i = 0; i < vars.length(); i++)
+ {
+ if (vars(i)->is_defined () &&
+ ! add_hdf5_data (data_hid, vars(i)->def(), vars(i)->name(),
+ "", false, save_as_floats))
+ break;
+ }
+ H5Gclose (data_hid);
+ }
+ }
+ else
+ {
+ std::string octaveroot = OCTAVE_EXEC_PREFIX;
+ std::string fpath = user_function_value ()-> fcn_file_name ();
+
+ H5Sclose (space_hid);
+ hdims[0] = 1;
+ hdims[1] = octaveroot.length ();
+ space_hid = H5Screate_simple (0 , hdims, 0);
+ if (space_hid < 0)
+ {
+ H5Tclose (type_hid);
+ H5Gclose (group_hid);
+ return false;
+ }
+
+ H5Tclose (type_hid);
+ type_hid = H5Tcopy (H5T_C_S1);
+ H5Tset_size (type_hid, octaveroot.length () + 1);
+
+ hid_t a_id = H5Acreate (group_hid, "OCTAVEROOT",
+ type_hid, space_hid, H5P_DEFAULT);
+
+ if (a_id >= 0)
+ {
+ retval = (H5Awrite (a_id, type_hid, octaveroot.c_str ()) >= 0);
+
+ H5Aclose (a_id);
+ }
+ else
+ retval = false;
+
+ H5Sclose (space_hid);
+ hdims[0] = 1;
+ hdims[1] = fpath.length ();
+ space_hid = H5Screate_simple (0 , hdims, 0);
+ if (space_hid < 0)
+ {
+ H5Tclose (type_hid);
+ H5Gclose (group_hid);
+ return false;
+ }
+
+ H5Tclose (type_hid);
+ type_hid = H5Tcopy (H5T_C_S1);
+ H5Tset_size (type_hid, fpath.length () + 1);
+
+ a_id = H5Acreate (group_hid, "FILE", type_hid, space_hid, H5P_DEFAULT);
+
+ if (a_id >= 0)
+ {
+ retval = (H5Awrite (a_id, type_hid, fpath.c_str ()) >= 0);
+
+ H5Aclose (a_id);
+ }
+ else
+ retval = false;
}
H5Sclose (space_hid);
***************
*** 366,376 ****
bool
octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name,
! bool /* have_h5giterate_bug */)
{
hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
hsize_t rank;
int slen;
group_hid = H5Gopen (loc_id, name);
if (group_hid < 0 ) return false;
--- 875,886 ----
bool
octave_fcn_handle::load_hdf5 (hid_t loc_id, const char *name,
! bool have_h5giterate_bug)
{
hid_t group_hid, data_hid, space_hid, type_hid, type_class_hid, st_id;
hsize_t rank;
int slen;
+ bool success = true;
group_hid = H5Gopen (loc_id, name);
if (group_hid < 0 ) return false;
***************
*** 490,523 ****
return false;
}
H5Dclose (data_hid);
- H5Tclose (st_id);
! int parse_status;
! octave_value anon_fcn_handle = eval_string (fcn_tmp, true,
parse_status);
! if (parse_status == 0)
{
! octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
! if (fh)
! fcn = fh->fcn;
else
! return false;
}
! else
! return false;
}
else
{
! fcn = lookup_function (nm);
! if (! fcn.is_function ())
{
! error ("function handle points to non-existent function");
! return false;
}
}
! return true;
}
#endif
void
--- 1000,1219 ----
return false;
}
H5Dclose (data_hid);
! symbol_table *local_sym_tab = 0;
! octave_idx_type len = 0;
!
! // we have to pull some shenanigans here to make sure
! // HDF5 doesn't print out all sorts of error messages if we
! // call H5Aopen for a non-existing attribute
! H5E_auto_t err_func;
! void *err_func_data;
!
! // turn off error reporting temporarily, but save the error
! // reporting function:
! H5Eget_auto (&err_func, &err_func_data);
! H5Eset_auto (0, 0);
!
! hid_t attr_id = H5Aopen_name (group_hid, "SYMBOL_TABLE");
!
! if (attr_id >= 0)
! {
! if (H5Aread (attr_id, H5T_NATIVE_IDX, &len) < 0)
! success = false;
!
! H5Aclose (attr_id);
! }
!
! // restore error reporting:
! H5Eset_auto (err_func, err_func_data);
!
! if (len > 0 && success)
{
! octave_idx_type nlen = len;
! if (nlen % 2)
! nlen++;
!
! local_sym_tab = new symbol_table (nlen, "LOCAL");
!
! #ifdef HAVE_H5GGET_NUM_OBJS
! hsize_t num_obj = 0;
! data_hid = H5Gopen (group_hid, "symbol table");
! H5Gget_num_objs (data_hid, &num_obj);
! H5Gclose (data_hid);
!
! if (num_obj != static_cast<hsize_t>(len))
! {
! error ("load: failed to load anonymous function handle");
! success = false;
! }
! #endif
!
! if (! error_state)
! {
! hdf5_callback_data dsub;
! int current_item = 0;
! for (octave_idx_type i = 0; i < len; i++)
! {
! if (H5Giterate (group_hid, "symbol table", ¤t_item,
! hdf5_read_next_data, &dsub) <= 0)
! {
! error ("load: failed to load anonymous function handle");
! success = false;
! break;
! }
!
! if (have_h5giterate_bug)
! current_item++; // H5Giterate returns last index processed
!
! symbol_record *sr = local_sym_tab->lookup (dsub.name, true);
!
! if (sr)
! sr->define (dsub.tc);
! else
! {
! error ("load: failed to load anonymous function handle");
! success = false;
! break;
! }
! }
! }
! }
!
! H5Tclose (st_id);
! H5Gclose (group_hid);
!
! if (success)
! {
! unwind_protect::begin_frame ("anon_hdf5_load");
! unwind_protect_ptr (curr_sym_tab);
!
! if (local_sym_tab)
! curr_sym_tab = local_sym_tab;
!
! int parse_status;
! octave_value anon_fcn_handle =
! eval_string (fcn_tmp, true, parse_status);
!
! if (parse_status == 0)
! {
! octave_fcn_handle *fh = anon_fcn_handle.fcn_handle_value ();
! if (fh)
! fcn = fh->fcn;
! else
! success = false;
! }
else
! success = false;
!
! unwind_protect::run_frame ("anon_hdf5_load");
}
!
! if (local_sym_tab)
! delete local_sym_tab;
}
else
{
! std::string octaveroot;
! std::string fpath;
!
! // we have to pull some shenanigans here to make sure
! // HDF5 doesn't print out all sorts of error messages if we
! // call H5Aopen for a non-existing attribute
!
! H5E_auto_t err_func;
! void *err_func_data;
!
! // turn off error reporting temporarily, but save the error
! // reporting function:
! H5Eget_auto (&err_func, &err_func_data);
! H5Eset_auto (0, 0);
!
! hid_t attr_id = H5Aopen_name (group_hid, "OCTAVEROOT");
! if (attr_id >= 0)
{
! type_hid = H5Aget_type (attr_id);
! type_class_hid = H5Tget_class (type_hid);
!
! if (type_class_hid != H5T_STRING)
! success = false;
! else
! {
! slen = H5Tget_size (type_hid);
! st_id = H5Tcopy (H5T_C_S1);
! H5Tset_size (st_id, slen);
! OCTAVE_LOCAL_BUFFER (char, root_tmp, slen);
!
! if (H5Aread (attr_id, st_id, root_tmp) < 0)
! success = false;
! else
! octaveroot = root_tmp;
! }
!
! H5Aclose (attr_id);
! }
!
! attr_id = H5Aopen_name (group_hid, "FILE");
! if (attr_id >= 0)
! {
! type_hid = H5Aget_type (attr_id);
! type_class_hid = H5Tget_class (type_hid);
!
! if (type_class_hid != H5T_STRING)
! success = false;
! else
! {
! slen = H5Tget_size (type_hid);
! st_id = H5Tcopy (H5T_C_S1);
! H5Tset_size (st_id, slen);
! OCTAVE_LOCAL_BUFFER (char, path_tmp, slen);
!
! if (H5Aread (attr_id, st_id, path_tmp) < 0)
! success = false;
! else
! fpath = path_tmp;
! }
!
! H5Aclose (attr_id);
}
+
+ // restore error reporting:
+ H5Eset_auto (err_func, err_func_data);
+
+ success = (success ? set_fcn (octaveroot, fpath) : success);
}
! return success;
}
+
+ /*
+
+ %!test
+ %! if (!isempty(findstr(octave_config_info ("DEFS"),"HAVE_HDF5")))
+ %! a = 2;
+ %! f = @(x) a + x;
+ %! g = @(x) 2 * x;
+ %! h = @log2;
+ %! f2 = f;
+ %! g2 = g;
+ %! h2 = h;
+ %! nm = tmpnam();
+ %! unwind_protect
+ %! save ("-hdf5", nm, "f2", "g2", "h2");
+ %! clear f2 g2 h2
+ %! load (nm);
+ %! assert (f(2),f2(2));
+ %! assert (g(2),g2(2));
+ %! assert (g(3),g2(3));
+ %! unlink ("test.mat");
+ %! save ("-hdf5", nm, "f2", "g2", "h2");
+ %! unwind_protect_cleanup
+ %! unlink (nm);
+ %! end_unwind_protect
+ %! endif
+
+ */
#endif
void
***************
*** 657,679 ****
std::string fh_nm = fh->fcn_name ();
! m.assign ("function", fh_nm);
! if (fcn->is_nested_function ())
! m.assign ("type", "subfunction");
else
! m.assign ("type", "simple");
std::string nm = fcn->fcn_file_name ();
if (nm.empty ())
{
if (fh_nm == "@<anonymous>")
! m.assign ("file", "none");
else if (fcn->is_user_function ())
! m.assign ("file", "command-line function");
else
! m.assign ("file", "built-in function");
}
else
m.assign ("file", nm);
--- 1353,1422 ----
std::string fh_nm = fh->fcn_name ();
! if (fh_nm == "@<anonymous>")
! {
! std::ostringstream buf;
! fh->print_raw (buf);
! m.assign ("function", buf.str ());
! m.assign ("type", "anonymous");
! }
else
! {
! m.assign ("function", fh_nm);
!
! if (fcn->is_nested_function ())
! {
! m.assign ("type", "subfunction");
! Cell parentage (dim_vector (1, 2));
! parentage.elem(0) = fh_nm;
! parentage.elem(1) = fcn->parent_fcn_name ();
! m.assign ("parentage", parentage);
! }
! else
! m.assign ("type", "simple");
! }
std::string nm = fcn->fcn_file_name ();
if (nm.empty ())
{
if (fh_nm == "@<anonymous>")
! {
! m.assign ("file", "");
!
! octave_user_function *fu = fh->user_function_value ();
! Array <symbol_record *> vars =
! fu->sym_tab ()->symbol_list ();
! octave_idx_type varlen = vars.length ();
!
! // Exclude undefined values like __retval__
! for (int i = 0; i < vars.length (); i++)
! {
! if (! vars (i)->is_defined ())
! varlen--;
! }
!
! if (varlen > 0)
! {
! Octave_map ws;
! for (octave_idx_type i = 0; i < vars.length (); i++)
! {
! if (vars (i)->is_defined ())
! ws.assign (vars (i)->name (),
! vars (i)->def ());
! }
!
! m.assign ("workspace", ws);
! }
! }
else if (fcn->is_user_function ())
! {
! octave_user_function *fu = fh->user_function_value ();
! m.assign ("file", fu->fcn_file_name ());
! }
else
! m.assign ("file", "");
}
else
m.assign ("file", nm);
Index: src/ov-fcn-handle.h
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-fcn-handle.h,v
retrieving revision 1.22
diff -c -r1.22 ov-fcn-handle.h
*** src/ov-fcn-handle.h 23 Aug 2006 18:35:39 -0000 1.22
--- src/ov-fcn-handle.h 14 May 2007 12:34:41 -0000
***************
*** 78,83 ****
--- 78,86 ----
octave_function *function_value (bool = false)
{ return fcn.function_value (); }
+ octave_user_function *user_function_value (bool = false)
+ { return fcn.user_function_value (); }
+
octave_fcn_handle *fcn_handle_value (bool = false) { return this; }
octave_value fcn_val (void) const { return fcn; }
***************
*** 105,110 ****
--- 108,115 ----
private:
+ bool set_fcn (const std::string &octaveroot, const std::string& fpath);
+
DECLARE_OCTAVE_ALLOCATOR
DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
Index: src/ov-fcn-inline.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-fcn-inline.cc,v
retrieving revision 1.31
diff -c -r1.31 ov-fcn-inline.cc
*** src/ov-fcn-inline.cc 19 Apr 2007 21:47:41 -0000 1.31
--- src/ov-fcn-inline.cc 14 May 2007 12:34:41 -0000
***************
*** 89,94 ****
--- 89,114 ----
error ("inline: unable to define function");
}
+ // This function is supplied to allow a Matlab style class structure
+ // to be returned..
+ Octave_map
+ octave_fcn_inline::map_value (void) const
+ {
+ Octave_map m;
+ string_vector args = fcn_arg_names ();
+ m.assign ("version", octave_value (1.0));
+ m.assign ("isEmpty", octave_value (0.0));
+ m.assign ("expr", octave_value (fcn_text ()));
+ m.assign ("numArgs", octave_value (args.length ()));
+ m.assign ("args", octave_value (args));
+ std::ostringstream buf;
+ for (int i = 0; i < args.length (); i++)
+ buf << args(i) << " = INLINE_INPUTS_{" << i + 1 << "}; ";
+ m.assign ("inputExpr", octave_value (buf.str ()));
+
+ return m;
+ }
+
bool
octave_fcn_inline::save_ascii (std::ostream& os, bool&)
{
Index: src/ov-fcn-inline.h
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-fcn-inline.h,v
retrieving revision 1.11
diff -c -r1.11 ov-fcn-inline.h
*** src/ov-fcn-inline.h 23 Aug 2006 18:35:39 -0000 1.11
--- src/ov-fcn-inline.h 14 May 2007 12:34:41 -0000
***************
*** 65,70 ****
--- 65,72 ----
octave_value convert_to_str_internal (bool, bool, char) const;
+ Octave_map map_value (void) const;
+
bool save_ascii (std::ostream& os, bool& infnan_warned);
bool load_ascii (std::istream& is);
2007-04-11 David Bateman <address@hidden>
* load_pathc.cc (std::string octave_system_path (void)): New
function.
* load-path.h (std::string octave_system_path (void)): Declare it.
* load-save.cc (static load_save_format get_file_format
(std::istream&, const std::string&)): Add filename argument, and
pass it to read_mat5_binary_header. Use new format throughout file.
(Fload): Don't allow gzip of matlab v7 files as the files
themselves include compression.
* ls-mat.cc (arrayclsstype:MAT_FILE_WORKSPACE_CLASS): New class
type.
(read_mat5_binary_element): Workspaces, don't have dimensions, so
don't read them. Implement read of matlab objects, but only use
them for inline functions. Implement reading of function and
workspace classes.
(read_mat5_binary_header): Add filename argument. Read sub-system
specific data block given as an offset in bytes 117 to 124.
(save_mat5_binary_element): Include saving of inline functions.
* ls-mat5.h (read_mat5_binary_header): Include filename.
* ov-fcn-handle.cc (octave_fcn_handle_save_ascii,
octave_fcn_handle::load_ascii, octave_fcn_handle::save_binary,
octave_fcn_handle::load_binary, octave_fcn_handle::save_hdf5,
octave_fcn_handle::load_hdf5): Save and reload the local symbol
table of the user function associated with anonymous function
handles. Save and load the absolute path and the exec_prefix for
normal function handles and use then to find equivalent functions
between different installations of Octave. Attempt to maintain
backward and forward compatibility.
(Ffunctions): Additional outputs, including the workspace of
anonymous functions, and more compatiable outputs.
* ov-fcn-handle.h (user_function_value): Expose the user function
value of a function handle.
* ov-fcn-inline.cc (Octave_map octave_fcn_inline::map_value
(void) const): Return a structure compatiable with matlab's class
implementation of inline functions.
* ov-fcn-inline.h (map_value): Declare it.
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/09
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/09
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/09
- Re: saveing/loading symbol table of annymous functions,
David Bateman <=
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/14
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/15
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/15
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/16
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/16
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/16
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/16
- Re: saveing/loading symbol table of annymous functions, David Bateman, 2007/05/16
- Re: saveing/loading symbol table of annymous functions, John W. Eaton, 2007/05/16