# HG changeset patch
# User Stefan Miereis <stefan.miereis@gmx.de>
# Date 1464278598 -7200
#      Thu May 26 18:03:18 2016 +0200
# Node ID f8df8fb30210177ab8801b7ec45a132cd8c74476
# Parent  895971cb50f0f9439e870366269e0436aa76ae34
Changed octave_hdf5_id to int64_t and added a wrapper function for H5Giterate (Bug #47858)
* ls-hdf5.cc: moved make_valid_identifier, hdf5_read_next_data
* oct-hdf5.cc: created new file containing make_valid_identifier, hdf5_read_next_data, octave_H5Giterate
* oct-hdf5-types.h: Changed type of octave_hdf5_id to int64_t
* ov-cell.cc: Replaced H5Giterate with octave_H5Giterate
* ov-class.cc: Replaced H5Giterate with octave_H5Giterate
* ov-fcn-handle.cc: Replaced H5Giterate with octave_H5Giterate
* ov-struct.cc: Replaced H5Giterate with octave_H5Giterate

diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/ls-hdf5.cc
--- a/libinterp/corefcn/ls-hdf5.cc	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/corefcn/ls-hdf5.cc	Thu May 26 18:03:18 2016 +0200
@@ -147,28 +147,6 @@
 #endif
 }
 
-static std::string
-make_valid_identifier (const std::string& nm)
-{
-  std::string retval;
-
-  size_t nm_len = nm.length ();
-
-  if (nm_len > 0)
-    {
-      if (! isalpha (nm[0]))
-        retval += '_';
-
-      for (size_t i = 0; i < nm_len; i++)
-        {
-          char c = nm[i];
-          retval += (isalnum (c) || c == '_') ? c : '_';
-        }
-    }
-
-  return retval;
-}
-
 // Given two compound types t1 and t2, determine whether they
 // are compatible for reading/writing.  This function only
 // works for non-nested types composed of simple elements (ints, floats...),
@@ -307,7 +285,7 @@
 // The following subroutines creates an HDF5 representations of the way
 // we will store Octave complex types (pairs of floating-point numbers).
 // NUM_TYPE is the HDF5 numeric type to use for storage (e.g.
-// H5T_NATIVE_DOUBLE to save as 'double').  Note that any necessary
+// H5T_NATIVE_DOUBLE to save as 'double'). Note that any necessary
 // conversions are handled automatically by HDF5.
 
 octave_hdf5_id
@@ -327,355 +305,6 @@
 #endif
 }
 
-// This function is designed to be passed to H5Giterate, which calls it
-// on each data item in an HDF5 file.  For the item whose name is NAME in
-// the group GROUP_ID, this function sets dv->tc to an Octave representation
-// of that item.  (dv must be a pointer to hdf5_callback_data.)  (It also
-// sets the other fields of dv).
-//
-// It returns 1 on success (in which case H5Giterate stops and returns),
-// -1 on error, and 0 to tell H5Giterate to continue on to the next item
-// (e.g., if NAME was a data type we don't recognize).
-
-octave_hdf5_err
-hdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv)
-{
-#if defined (HAVE_HDF5)
-
-  hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv);
-  hid_t type_id = -1;
-  hid_t type_class_id = -1;
-  hid_t data_id = -1;
-  hid_t subgroup_id = -1;
-  hid_t space_id = -1;;
-
-  H5G_stat_t info;
-  herr_t retval = 0;
-  bool ident_valid = valid_identifier (name);
-
-  std::string vname = name;
-
-  // Allow identifiers as all digits so we can load lists saved by
-  // earlier versions of Octave.
-
-  if (! ident_valid)
-    {
-      // fix the identifier, replacing invalid chars with underscores
-      vname = make_valid_identifier (vname);
-
-      // check again (in case vname was null, empty, or some such thing):
-      ident_valid = valid_identifier (vname);
-    }
-
-  H5Gget_objinfo (group_id, name, 1, &info);
-
-  if (info.type == H5G_GROUP && ident_valid)
-    {
-#if defined (HAVE_HDF5_18)
-      subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT);
-#else
-      subgroup_id = H5Gopen (group_id, name);
-#endif
-
-      if (subgroup_id < 0)
-        {
-          retval = subgroup_id;
-          goto done;
-        }
-
-      if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
-        {
-#if defined (HAVE_HDF5_18)
-          data_id = H5Dopen (subgroup_id, "type", octave_H5P_DEFAULT);
-#else
-          data_id = H5Dopen (subgroup_id, "type");
-#endif
-
-          if (data_id < 0)
-            {
-              retval = data_id;
-              goto done;
-            }
-
-          type_id = H5Dget_type (data_id);
-
-          type_class_id = H5Tget_class (type_id);
-
-          if (type_class_id != H5T_STRING)
-            goto done;
-
-          space_id = H5Dget_space (data_id);
-          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-          if (rank != 0)
-            goto done;
-
-          int slen = H5Tget_size (type_id);
-          if (slen < 0)
-            goto done;
-
-          OCTAVE_LOCAL_BUFFER (char, typ, slen);
-
-          // create datatype for (null-terminated) string to read into:
-          hid_t st_id = H5Tcopy (H5T_C_S1);
-          H5Tset_size (st_id, slen);
-
-          if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT,
-                       typ) < 0)
-            goto done;
-
-          H5Tclose (st_id);
-          H5Dclose (data_id);
-
-          d->tc = octave_value_typeinfo::lookup_type (typ);
-
-          retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
-
-          // check for OCTAVE_GLOBAL attribute:
-          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
-
-          H5Gclose (subgroup_id);
-        }
-      else
-        {
-          // an HDF5 group is treated as an octave structure by
-          // default (since that preserves name information), and an
-          // octave list otherwise.
-
-          if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
-            d->tc = octave_value_typeinfo::lookup_type ("list");
-          else
-            d->tc = octave_value_typeinfo::lookup_type ("struct");
-
-          // check for OCTAVE_GLOBAL attribute:
-          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
-
-          H5Gclose (subgroup_id);
-
-          retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
-        }
-
-    }
-  else if (info.type == H5G_DATASET && ident_valid)
-    {
-      // For backwards compatibility.
-#if defined (HAVE_HDF5_18)
-      data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT);
-#else
-      data_id = H5Dopen (group_id, name);
-#endif
-
-      if (data_id < 0)
-        {
-          retval = data_id;
-          goto done;
-        }
-
-      type_id = H5Dget_type (data_id);
-
-      type_class_id = H5Tget_class (type_id);
-
-      if (type_class_id == H5T_FLOAT)
-        {
-          space_id = H5Dget_space (data_id);
-
-          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-          if (rank == 0)
-            d->tc = octave_value_typeinfo::lookup_type ("scalar");
-          else
-            d->tc = octave_value_typeinfo::lookup_type ("matrix");
-
-          H5Sclose (space_id);
-        }
-      else if (type_class_id == H5T_INTEGER)
-        {
-          // What integer type do we really have..
-          std::string int_typ;
-#if defined (HAVE_H5T_GET_NATIVE_TYPE)
-          // FIXME: test this code and activated with an autoconf
-          // test!! It is also incorrect for 64-bit indexing!!
-
-          switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
-            {
-            case H5T_NATIVE_CHAR:
-              int_typ = "int8 ";
-              break;
-
-            case H5T_NATIVE_SHORT:
-              int_typ = "int16 ";
-              break;
-
-            case H5T_NATIVE_INT:
-            case H5T_NATIVE_LONG:
-              int_typ = "int32 ";
-              break;
-
-            case H5T_NATIVE_LLONG:
-              int_typ = "int64 ";
-              break;
-
-            case H5T_NATIVE_UCHAR:
-              int_typ = "uint8 ";
-              break;
-
-            case H5T_NATIVE_USHORT:
-              int_typ = "uint16 ";
-              break;
-
-            case H5T_NATIVE_UINT:
-            case H5T_NATIVE_ULONG:
-              int_typ = "uint32 ";
-              break;
-
-            case H5T_NATIVE_ULLONG:
-              int_typ = "uint64 ";
-              break;
-            }
-#else
-          hid_t int_sign = H5Tget_sign (type_id);
-
-          if (int_sign == H5T_SGN_ERROR)
-            warning ("load: can't read '%s' (unknown datatype)", name);
-          else
-            {
-              if (int_sign == H5T_SGN_NONE)
-                int_typ.append ("u");
-              int_typ.append ("int");
-
-              int slen = H5Tget_size (type_id);
-              if (slen < 0)
-                warning ("load: can't read '%s' (unknown datatype)", name);
-              else
-                {
-                  switch (slen)
-                    {
-                    case 1:
-                      int_typ.append ("8 ");
-                      break;
-
-                    case 2:
-                      int_typ.append ("16 ");
-                      break;
-
-                    case 4:
-                      int_typ.append ("32 ");
-                      break;
-
-                    case 8:
-                      int_typ.append ("64 ");
-                      break;
-
-                    default:
-                      warning ("load: can't read '%s' (unknown datatype)",
-                               name);
-                      int_typ = "";
-                      break;
-                    }
-                }
-            }
-#endif
-          if (int_typ == "")
-            warning ("load: can't read '%s' (unknown datatype)", name);
-          else
-            {
-              // Matrix or scalar?
-              space_id = H5Dget_space (data_id);
-
-              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-              if (rank == 0)
-                int_typ.append ("scalar");
-              else
-                int_typ.append ("matrix");
-
-              d->tc = octave_value_typeinfo::lookup_type (int_typ);
-              H5Sclose (space_id);
-            }
-        }
-      else if (type_class_id == H5T_STRING)
-        d->tc = octave_value_typeinfo::lookup_type ("string");
-      else if (type_class_id == H5T_COMPOUND)
-        {
-          hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
-
-          if (hdf5_types_compatible (type_id, complex_type))
-            {
-              // read complex matrix or scalar variable
-              space_id = H5Dget_space (data_id);
-              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
-
-              if (rank == 0)
-                d->tc = octave_value_typeinfo::lookup_type ("complex scalar");
-              else
-                d->tc = octave_value_typeinfo::lookup_type ("complex matrix");
-
-              H5Sclose (space_id);
-            }
-          else
-            // Assume that if its not complex its a range.
-            // If its not, it'll be rejected later in the range code.
-            d->tc = octave_value_typeinfo::lookup_type ("range");
-
-          H5Tclose (complex_type);
-        }
-      else
-        {
-          warning ("load: can't read '%s' (unknown datatype)", name);
-          retval = 0; // unknown datatype; skip
-          return retval;
-        }
-
-      // check for OCTAVE_GLOBAL attribute:
-      d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
-
-      H5Tclose (type_id);
-      H5Dclose (data_id);
-
-      retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
-    }
-
-  if (! ident_valid)
-    {
-      // should we attempt to handle invalid identifiers by converting
-      // bad characters to '_', say?
-      warning ("load: skipping invalid identifier '%s' in hdf5 file",
-               name);
-    }
-
-done:
-  if (retval < 0)
-    error ("load: error while reading hdf5 item %s", name);
-
-  if (retval > 0)
-    {
-      // get documentation string, if any:
-      int comment_length = H5Gget_comment (group_id, name, 0, 0);
-
-      if (comment_length > 1)
-        {
-          OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
-          H5Gget_comment (group_id, name, comment_length, tdoc);
-          d->doc = tdoc;
-        }
-      else if (vname != name)
-        {
-          // the name was changed; store the original name
-          // as the documentation string:
-          d->doc = name;
-        }
-
-      // copy name (actually, vname):
-      d->name = vname;
-    }
-
-  return retval;
-
-#else
-  err_disabled_feature ("hdf5_read_next_data", "HDF5");
-#endif
-}
-
 // Read the next Octave variable from the stream IS, which must really be
 // an hdf5_ifstream.  Return the variable value in tc, its doc string
 // in doc, and whether it is global in global.  The return value is
@@ -739,8 +368,8 @@
 
 
   if (hs.current_item < static_cast<int> (num_obj))
-    H5Giterate_retval = H5Giterate (hs.file_id, "/", &hs.current_item,
-                                    hdf5_read_next_data, &d);
+    H5Giterate_retval = octave_H5Giterate (hs.file_id, "/", &hs.current_item,
+                                           &d);
 
   if (H5Giterate_retval > 0)
     {
@@ -848,7 +477,7 @@
 #endif
 }
 
-// Save an empty matrix, if needed.  Returns
+// Save an empty matrix, if needed. Returns
 //    > 0  Saved empty matrix
 //    = 0  Not an empty matrix; did nothing
 //    < 0  Error condition
@@ -904,7 +533,7 @@
 #endif
 }
 
-// Load an empty matrix, if needed.  Returns
+// Load an empty matrix, if needed. Returns
 //    > 0  loaded empty matrix, dimensions returned
 //    = 0  Not an empty matrix; did nothing
 //    < 0  Error condition
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/ls-hdf5.h
--- a/libinterp/corefcn/ls-hdf5.h	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/corefcn/ls-hdf5.h	Thu May 26 18:03:18 2016 +0200
@@ -119,9 +119,6 @@
 extern OCTINTERP_API bool
 hdf5_types_compatible (octave_hdf5_id t1, octave_hdf5_id t2);
 
-extern OCTINTERP_API octave_hdf5_err
-hdf5_read_next_data (octave_hdf5_id group_id, const char *name, void *dv);
-
 extern OCTINTERP_API bool
 add_hdf5_data (octave_hdf5_id loc_id, const octave_value& tc,
                const std::string& name, const std::string& doc,
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/module.mk
--- a/libinterp/corefcn/module.mk	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/corefcn/module.mk	Thu May 26 18:03:18 2016 +0200
@@ -201,6 +201,7 @@
   libinterp/corefcn/nproc.cc \
   libinterp/corefcn/oct-fstrm.cc \
   libinterp/corefcn/oct-hdf5-types.cc \
+  libinterp/corefcn/oct-hdf5.cc \
   libinterp/corefcn/oct-hist.cc \
   libinterp/corefcn/oct-iostrm.cc \
   libinterp/corefcn/oct-lvalue.cc \
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/oct-hdf5-types.h
--- a/libinterp/corefcn/oct-hdf5-types.h	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/corefcn/oct-hdf5-types.h	Thu May 26 18:03:18 2016 +0200
@@ -32,7 +32,8 @@
 
 // Available for C and C++.
 
-typedef int octave_hdf5_id;
+// octave_hdf5_id is cast to int for versions of hdf5 older than 1.8
+typedef int64_t octave_hdf5_id;
 typedef int octave_hdf5_err;
 
 #if defined (__cplusplus)
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/oct-hdf5.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libinterp/corefcn/oct-hdf5.cc	Thu May 26 18:03:18 2016 +0200
@@ -0,0 +1,421 @@
+/*
+
+Copyright (C) 2009-2015 John W. Eaton
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#include "config.h"
+
+#include "oct-hdf5.h"
+#include "ov-cell.h"
+#include "utils.h"
+
+#include "ls-hdf5.h"
+
+
+#if defined (HAVE_HDF5)
+
+octave_hdf5_err
+hdf5_read_next_data (hid_t group_id, const char *name, void *dv);
+
+int
+octave_H5Giterate(octave_hdf5_id loc_id, const char* name, int *idx,
+                     void *operator_data)
+{
+  hid_t new_id = static_cast<hid_t> (loc_id);
+  return H5Giterate(new_id, name, idx, hdf5_read_next_data, operator_data);
+}
+
+static std::string
+make_valid_identifier (const std::string& nm)
+{
+  std::string retval;
+
+  size_t nm_len = nm.length ();
+
+  if (nm_len > 0)
+    {
+      if (! isalpha (nm[0]))
+        retval += '_';
+
+      for (size_t i = 0; i < nm_len; i++)
+        {
+          char c = nm[i];
+          retval += (isalnum (c) || c == '_') ? c : '_';
+        }
+    }
+
+  return retval;
+}
+
+// This function is designed to be passed to H5Giterate, which calls it
+// on each data item in an HDF5 file.  For the item whose name is NAME in
+// the group GROUP_ID, this function sets dv->tc to an Octave representation
+// of that item.  (dv must be a pointer to hdf5_callback_data.)  (It also
+// sets the other fields of dv).
+//
+// It returns 1 on success (in which case H5Giterate stops and returns),
+// -1 on error, and 0 to tell H5Giterate to continue on to the next item
+// (e.g. if NAME was a data type we don't recognize).
+//
+// Since we want octave to be agnostic of the hdf5 version installed,
+// and because this function needs a parameter of type hid_t, it was moved
+// here to be used in a wrapper function for H5Giterate
+
+octave_hdf5_err
+hdf5_read_next_data (hid_t group_id, const char *name, void *dv)
+{
+#if defined (HAVE_HDF5)
+
+  hdf5_callback_data *d = static_cast<hdf5_callback_data *> (dv);
+  hid_t type_id = -1;
+  hid_t type_class_id = -1;
+  hid_t data_id = -1;
+  hid_t subgroup_id = -1;
+  hid_t space_id = -1;;
+
+  H5G_stat_t info;
+  herr_t retval = 0;
+  bool ident_valid = valid_identifier (name);
+
+  std::string vname = name;
+
+  // Allow identifiers as all digits so we can load lists saved by
+  // earlier versions of Octave.
+
+  if (! ident_valid)
+    {
+      // fix the identifier, replacing invalid chars with underscores
+      vname = make_valid_identifier (vname);
+
+      // check again (in case vname was null, empty, or some such thing):
+      ident_valid = valid_identifier (vname);
+    }
+
+  H5Gget_objinfo (group_id, name, 1, &info);
+
+  if (info.type == H5G_GROUP && ident_valid)
+    {
+#if defined (HAVE_HDF5_18)
+      subgroup_id = H5Gopen (group_id, name, octave_H5P_DEFAULT);
+#else
+      subgroup_id = H5Gopen (group_id, name);
+#endif
+
+      if (subgroup_id < 0)
+        {
+          retval = subgroup_id;
+          goto done;
+        }
+
+      if (hdf5_check_attr (subgroup_id, "OCTAVE_NEW_FORMAT"))
+        {
+#if defined (HAVE_HDF5_18)
+          data_id = H5Dopen (subgroup_id, "type", octave_H5P_DEFAULT);
+#else
+          data_id = H5Dopen (subgroup_id, "type");
+#endif
+
+          if (data_id < 0)
+            {
+              retval = data_id;
+              goto done;
+            }
+
+          type_id = H5Dget_type (data_id);
+
+          type_class_id = H5Tget_class (type_id);
+
+          if (type_class_id != H5T_STRING)
+            goto done;
+
+          space_id = H5Dget_space (data_id);
+          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+          if (rank != 0)
+            goto done;
+
+          int slen = H5Tget_size (type_id);
+          if (slen < 0)
+            goto done;
+
+          OCTAVE_LOCAL_BUFFER (char, typ, slen);
+
+          // create datatype for (null-terminated) string to read into:
+          hid_t st_id = H5Tcopy (H5T_C_S1);
+          H5Tset_size (st_id, slen);
+
+          if (H5Dread (data_id, st_id, octave_H5S_ALL, octave_H5S_ALL, octave_H5P_DEFAULT,
+                       typ) < 0)
+            goto done;
+
+          H5Tclose (st_id);
+          H5Dclose (data_id);
+
+          d->tc = octave_value_typeinfo::lookup_type (typ);
+
+          retval = (d->tc.load_hdf5 (subgroup_id, "value") ? 1 : -1);
+
+          // check for OCTAVE_GLOBAL attribute:
+          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
+
+          H5Gclose (subgroup_id);
+        }
+      else
+        {
+          // an HDF5 group is treated as an octave structure by
+          // default (since that preserves name information), and an
+          // octave list otherwise.
+
+          if (hdf5_check_attr (subgroup_id, "OCTAVE_LIST"))
+            d->tc = octave_value_typeinfo::lookup_type ("list");
+          else
+            d->tc = octave_value_typeinfo::lookup_type ("struct");
+
+          // check for OCTAVE_GLOBAL attribute:
+          d->global = hdf5_check_attr (subgroup_id, "OCTAVE_GLOBAL");
+
+          H5Gclose (subgroup_id);
+
+          retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
+        }
+
+    }
+  else if (info.type == H5G_DATASET && ident_valid)
+    {
+      // For backwards compatibility.
+#if defined (HAVE_HDF5_18)
+      data_id = H5Dopen (group_id, name, octave_H5P_DEFAULT);
+#else
+      data_id = H5Dopen (group_id, name);
+#endif
+
+      if (data_id < 0)
+        {
+          retval = data_id;
+          goto done;
+        }
+
+      type_id = H5Dget_type (data_id);
+
+      type_class_id = H5Tget_class (type_id);
+
+      if (type_class_id == H5T_FLOAT)
+        {
+          space_id = H5Dget_space (data_id);
+
+          hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+          if (rank == 0)
+            d->tc = octave_value_typeinfo::lookup_type ("scalar");
+          else
+            d->tc = octave_value_typeinfo::lookup_type ("matrix");
+
+          H5Sclose (space_id);
+        }
+      else if (type_class_id == H5T_INTEGER)
+        {
+          // What integer type do we really have..
+          std::string int_typ;
+#ifdef HAVE_H5T_GET_NATIVE_TYPE
+          // FIXME: test this code and activated with an autoconf
+          // test!! It is also incorrect for 64-bit indexing!!
+
+          switch (H5Tget_native_type (type_id, H5T_DIR_ASCEND))
+            {
+            case H5T_NATIVE_CHAR:
+              int_typ = "int8 ";
+              break;
+
+            case H5T_NATIVE_SHORT:
+              int_typ = "int16 ";
+              break;
+
+            case H5T_NATIVE_INT:
+            case H5T_NATIVE_LONG:
+              int_typ = "int32 ";
+              break;
+
+            case H5T_NATIVE_LLONG:
+              int_typ = "int64 ";
+              break;
+
+            case H5T_NATIVE_UCHAR:
+              int_typ = "uint8 ";
+              break;
+
+            case H5T_NATIVE_USHORT:
+              int_typ = "uint16 ";
+              break;
+
+            case H5T_NATIVE_UINT:
+            case H5T_NATIVE_ULONG:
+              int_typ = "uint32 ";
+              break;
+
+            case H5T_NATIVE_ULLONG:
+              int_typ = "uint64 ";
+              break;
+            }
+#else
+          hid_t int_sign = H5Tget_sign (type_id);
+
+          if (int_sign == H5T_SGN_ERROR)
+            warning ("load: can't read '%s' (unknown datatype)", name);
+          else
+            {
+              if (int_sign == H5T_SGN_NONE)
+                int_typ.append ("u");
+              int_typ.append ("int");
+
+              int slen = H5Tget_size (type_id);
+              if (slen < 0)
+                warning ("load: can't read '%s' (unknown datatype)", name);
+              else
+                {
+                  switch (slen)
+                    {
+                    case 1:
+                      int_typ.append ("8 ");
+                      break;
+
+                    case 2:
+                      int_typ.append ("16 ");
+                      break;
+
+                    case 4:
+                      int_typ.append ("32 ");
+                      break;
+
+                    case 8:
+                      int_typ.append ("64 ");
+                      break;
+
+                    default:
+                      warning ("load: can't read '%s' (unknown datatype)",
+                               name);
+                      int_typ = "";
+                      break;
+                    }
+                }
+            }
+#endif
+          if (int_typ == "")
+            warning ("load: can't read '%s' (unknown datatype)", name);
+          else
+            {
+              // Matrix or scalar?
+              space_id = H5Dget_space (data_id);
+
+              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+              if (rank == 0)
+                int_typ.append ("scalar");
+              else
+                int_typ.append ("matrix");
+
+              d->tc = octave_value_typeinfo::lookup_type (int_typ);
+              H5Sclose (space_id);
+            }
+        }
+      else if (type_class_id == H5T_STRING)
+        d->tc = octave_value_typeinfo::lookup_type ("string");
+      else if (type_class_id == H5T_COMPOUND)
+        {
+          hid_t complex_type = hdf5_make_complex_type (H5T_NATIVE_DOUBLE);
+
+          if (hdf5_types_compatible (type_id, complex_type))
+            {
+              // read complex matrix or scalar variable
+              space_id = H5Dget_space (data_id);
+              hsize_t rank = H5Sget_simple_extent_ndims (space_id);
+
+              if (rank == 0)
+                d->tc = octave_value_typeinfo::lookup_type ("complex scalar");
+              else
+                d->tc = octave_value_typeinfo::lookup_type ("complex matrix");
+
+              H5Sclose (space_id);
+            }
+          else
+            // Assume that if its not complex its a range. If its not
+            // it'll be rejected later in the range code
+            d->tc = octave_value_typeinfo::lookup_type ("range");
+
+          H5Tclose (complex_type);
+        }
+      else
+        {
+          warning ("load: can't read '%s' (unknown datatype)", name);
+          retval = 0; // unknown datatype; skip
+          return retval;
+        }
+
+      // check for OCTAVE_GLOBAL attribute:
+      d->global = hdf5_check_attr (data_id, "OCTAVE_GLOBAL");
+
+      H5Tclose (type_id);
+      H5Dclose (data_id);
+
+      retval = (d->tc.load_hdf5 (group_id, name) ? 1 : -1);
+    }
+
+  if (! ident_valid)
+    {
+      // should we attempt to handle invalid identifiers by converting
+      // bad characters to '_', say?
+      warning ("load: skipping invalid identifier '%s' in hdf5 file",
+               name);
+    }
+
+done:
+  if (retval < 0)
+    error ("load: error while reading hdf5 item %s", name);
+
+  if (retval > 0)
+    {
+      // get documentation string, if any:
+      int comment_length = H5Gget_comment (group_id, name, 0, 0);
+
+      if (comment_length > 1)
+        {
+          OCTAVE_LOCAL_BUFFER (char, tdoc, comment_length);
+          H5Gget_comment (group_id, name, comment_length, tdoc);
+          d->doc = tdoc;
+        }
+      else if (vname != name)
+        {
+          // the name was changed; store the original name
+          // as the documentation string:
+          d->doc = name;
+        }
+
+      // copy name (actually, vname):
+      d->name = vname;
+    }
+
+  return retval;
+
+#else
+  err_disabled_feature ("hdf5_read_next_data", "HDF5");
+#endif
+}
+
+
+#endif /*HAVE_HDF5*/
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/corefcn/oct-hdf5.h
--- a/libinterp/corefcn/oct-hdf5.h	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/corefcn/oct-hdf5.h	Thu May 26 18:03:18 2016 +0200
@@ -33,6 +33,11 @@
 
 #  include "oct-hdf5-types.h"
 
+// This is a wrapper for H5Giterate which hides the hdf5_read_next_data function
+int
+octave_H5Giterate(octave_hdf5_id loc_id, const char* name, int *idx,
+		     void *operator_data);
+
 #  if defined (OCTAVE_ENABLE_64)
 #    define H5T_NATIVE_IDX H5T_NATIVE_INT64
 #  else
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/octave-value/ov-cell.cc
--- a/libinterp/octave-value/ov-cell.cc	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/octave-value/ov-cell.cc	Thu May 26 18:03:18 2016 +0200
@@ -1152,8 +1152,7 @@
       if (current_item >= static_cast<int> (num_obj))
         retval2 = -1;
       else
-        retval2 = H5Giterate (loc_id, name, &current_item,
-                              hdf5_read_next_data, &dsub);
+        retval2 = octave_H5Giterate (loc_id, name, &current_item,&dsub);
 
       if (retval2 <= 0)
         break;
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/octave-value/ov-class.cc
--- a/libinterp/octave-value/ov-class.cc	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/octave-value/ov-class.cc	Thu May 26 18:03:18 2016 +0200
@@ -1590,8 +1590,8 @@
   H5Gclose (subgroup_hid);
 
   while (current_item < static_cast<int> (num_obj)
-         && (retval2 = H5Giterate (group_hid, name, &current_item,
-                                   hdf5_read_next_data, &dsub)) > 0)
+         && (retval2 = octave_H5Giterate (group_hid, name, &current_item,
+                                          &dsub)) > 0)
     {
       octave_value t2 = dsub.tc;
 
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/octave-value/ov-fcn-handle.cc
--- a/libinterp/octave-value/ov-fcn-handle.cc	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/octave-value/ov-fcn-handle.cc	Thu May 26 18:03:18 2016 +0200
@@ -1146,8 +1146,8 @@
           int current_item = 0;
           for (octave_idx_type i = 0; i < len; i++)
             {
-              if (H5Giterate (group_hid, "symbol table", &current_item,
-                              hdf5_read_next_data, &dsub) <= 0)
+              if (octave_H5Giterate (group_hid, "symbol table", &current_item,
+                                     &dsub) <= 0)
                 error ("load: failed to load anonymous function handle");
 
               symbol_table::assign (dsub.name, dsub.tc, local_scope);
diff -r 895971cb50f0 -r f8df8fb30210 libinterp/octave-value/ov-struct.cc
--- a/libinterp/octave-value/ov-struct.cc	Wed May 25 16:59:05 2016 -0700
+++ b/libinterp/octave-value/ov-struct.cc	Thu May 26 18:03:18 2016 +0200
@@ -946,8 +946,8 @@
   // Why is that happening?
 
   while (current_item < static_cast<int> (num_obj)
-         && (retval2 = H5Giterate (loc_id, name, &current_item,
-                                   hdf5_read_next_data, &dsub)) > 0)
+         && (retval2 = octave_H5Giterate (loc_id, name, &current_item,
+                                          &dsub)) > 0)  
     {
       octave_value t2 = dsub.tc;
 
@@ -1551,8 +1551,8 @@
   // Why is that happening?
 
   while (current_item < static_cast<int> (num_obj)
-         && (retval2 = H5Giterate (loc_id, name, &current_item,
-                                   hdf5_read_next_data, &dsub)) > 0)
+         && (retval2 = octave_H5Giterate (loc_id, name, &current_item,
+                                          &dsub)) > 0)
     {
       octave_value t2 = dsub.tc;
 
