Example #1
0
int
main()
{
   printf("\n*** Checking HDF5 file c0.nc.\n");
   printf("*** Checking HDF5 objcts...");

   {
      hid_t fileid, grpid;
      hsize_t num_obj, i;
      char obj_name[MAX_NAME];

      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDONLY, H5P_DEFAULT)) < 0) ERR; 
      if ((grpid = H5Gopen(fileid, "/")) < 0) ERR;

      /* Find the variables. Read their metadata and attributes. */
      if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the class (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if (H5Gget_objtype_by_idx(grpid, i) < 0) ERR;
	 if (H5Gget_objname_by_idx(grpid, i, obj_name, MAX_NAME) < 0) ERR;
      }

      if (H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }
   SUMMARIZE_ERR;

   FINAL_RESULTS;
}
Example #2
0
//--------------------------------------------------------------------------
// Function:	CommonFG::getObjTypeByIdx
///\brief	Returns the type of an object in this group, given the
///		object's index.
///\param	idx - IN: Transient index of the object
///\return	Object type
///\exception	H5::FileIException or H5::GroupIException
// Programmer	Binh-Minh Ribler - January, 2003
//--------------------------------------------------------------------------
H5G_obj_t CommonFG::getObjTypeByIdx(hsize_t idx) const
{
   H5G_obj_t obj_type = H5Gget_objtype_by_idx(getLocId(), idx);
   if (obj_type == H5G_UNKNOWN)
   {
      throwException("getObjTypeByIdx", "H5Gget_objtype_by_idx failed");
   }
   return (obj_type);
}
Example #3
0
listOfPaths_t* listOfObjectsInGroup( hid_t group, H5G_obj_t filter)
{
	ERROR_SWITCH_INIT
	
	herr_t get_err;
	H5G_info_t groupInfo; 
	H5G_obj_t objType;
	hsize_t i, numberOfLinks;
	size_t size;
	char* name = NULL;
	listOfPaths_t* listOfPaths = NULL;
	
	// get number of links in group
	ERROR_SWITCH_OFF
	get_err = H5Gget_info(group, &groupInfo);
	ERROR_SWITCH_ON
	if (get_err < 0) return listOfPaths;
	numberOfLinks = groupInfo.nlinks;
	
	// loop on all links in group
	for (i=0; i<numberOfLinks; i++)
	{
		// get type of current link
		objType = H5Gget_objtype_by_idx(group, i);
		// only add requested type of objects to the list
		if ( objType == filter || filter == -1) 
		{
			// get length of object name
			ERROR_SWITCH_OFF
			size = H5Lget_name_by_idx(group, ".", H5_INDEX_NAME, H5_ITER_INC, i, NULL, -1, H5P_DEFAULT);
			ERROR_SWITCH_ON
			if (size < 0) return listOfPaths;
			
			// get object name
			// allocate with extra character for '\0'
			name = (char *) malloc((size+1)*sizeof(char));
			ERROR_SWITCH_OFF
			size = H5Lget_name_by_idx(group, ".", H5_INDEX_NAME, H5_ITER_INC, i, name, size+1, H5P_DEFAULT);
			ERROR_SWITCH_ON
			if (size < 0)
			{
				free(name);
				return listOfPaths;
			}
			
			// add it into the list
			listOfPaths = addCopyToList(listOfPaths, name);
			free(name); name = NULL;			
		}
	}
Example #4
0
//--------------------------------------------------------------------------
// Function:	CommonFG::getObjTypeByIdx
///\brief	This is an overloaded member function, provided for convenience.
///		It differs from the above function because it also provides
///		the returned object type in text (H5std_string&)
///\param	idx       - IN: Transient index of the object
///\param	type_name - IN: Object type in text
///\return	Object type
///\exception	H5::FileIException or H5::GroupIException
// Programmer	Binh-Minh Ribler - January, 2003
//--------------------------------------------------------------------------
H5G_obj_t CommonFG::getObjTypeByIdx(hsize_t idx, H5std_string& type_name) const
{
   H5G_obj_t obj_type = H5Gget_objtype_by_idx(getLocId(), idx);
   switch (obj_type)
   {
	case H5G_LINK: type_name = H5std_string("symbolic link"); break;
	case H5G_GROUP: type_name = H5std_string("group"); break;
	case H5G_DATASET: type_name = H5std_string("dataset"); break;
	case H5G_TYPE: type_name = H5std_string("datatype"); break;
	case H5G_UNKNOWN:
	default:
   	{
	   throwException("getObjTypeByIdx", "H5Gget_objtype_by_idx failed");
	}
   }
   return (obj_type);
}
int AMRreader::
getInfo( const char* filename )
{
  debug2 << "opening AMR file " << filename << "\n";

  filename_ = filename;

  hid_t file_id = H5Fopen( filename, H5F_ACC_RDONLY, H5P_DEFAULT );
  if( file_id<0 ) {
    debug1 << "Failed to open AMR file: " << filename << ".\n";
    return -1;
  }

  hsize_t nobjs;
  herr_t  err = H5Gget_num_objs( file_id, &nobjs );
  debug2 << "nobjs in " << filename << " is " << nobjs << "\n";
  for( hsize_t i=0; i<nobjs; i++ ) {
    int type = H5Gget_objtype_by_idx( file_id, i );
    if( type == H5G_GROUP ) {
      char name[1000];
      ssize_t l= H5Gget_objname_by_idx( file_id, i, name, 1000 );

      hid_t gid = H5Gopen1( file_id, name );

      if( strcmp( name, amr_grpname )==0 ) {
    if( getAMRinfo( gid )!=0 ) {
      debug1 << "Failed to retrieve AMR info in " << filename << "\n";
      H5Gclose(gid);
      return -2;
    }}
      else if( strcmp( name, intf_grp_name )==0 ) {
    if( getIntfInfo( gid ) != 0 ) {
      debug1 << "Failed to retrieve Interface info in " << filename << "\n";
      return -3;
    }}
      else {
    debug1 << "Find a unrecongnized group " << name << " in " << filename << "\n";
      }

      H5Gclose(gid);
    }
  }

  H5Fclose( file_id );
  return 0;
}
Example #6
0
std::vector<std::string> HdfGroup::objects( H5G_obj_t type ) const
{
  std::vector<std::string> lst;

  hsize_t nobj;
  H5Gget_num_objs( d->id, &nobj );
  for ( hsize_t i = 0; i < nobj; ++i )
  {
    if ( type == H5G_UNKNOWN || H5Gget_objtype_by_idx( d->id, i ) == type )
    {
      char name[HDF_MAX_NAME];
      H5Gget_objname_by_idx( d->id, i, name, ( size_t )HDF_MAX_NAME );
      lst.push_back( std::string( name ) );
    }
  }
  return lst;
}
//------------------------------------------------------------------------------
// Description:
// Finds the block index (blockIndx) within the HDF5 file associated with
// the given file index.
static bool FindBlockIndex(hid_t fileIndx, const int blockIdx, hid_t &rootIndx)
{
    // retrieve the contents of the root directory to look for a group
    // corresponding to the target block, if available, open that group
    hsize_t numbObjs;
    rootIndx = H5Gopen(fileIndx, "/");
    if (rootIndx < 0)
    {
        vtkGenericWarningMacro("Failed to open root node of particles file");
        return false;
    }

    bool found = false;
    H5Gget_num_objs(rootIndx, &numbObjs);
    for (int objIndex = 0; objIndex < static_cast < int >(numbObjs); objIndex++)
    {
        if (H5Gget_objtype_by_idx(rootIndx, objIndex) == H5G_GROUP)
        {
            int blckIndx;
            char blckName[65];
            H5Gget_objname_by_idx(rootIndx, objIndex, blckName, 64);

            // Is this the target block?
            if ((sscanf(blckName, "Grid%d", &blckIndx) == 1) &&
                (blckIndx == blockIdx))
            {
                // located the target block
                rootIndx = H5Gopen(rootIndx, blckName);
                if (rootIndx < 0)
                {
                    vtkGenericWarningMacro("Could not locate target block!\n");
                }
                found = true;
                break;
            }
        } // END if group
    } // END for all objects
    return (found);
}
Example #8
0
std::vector<std::string> hdf5file::subelements(const std::string& path, int desired_type)
{
	hid_t group_id = H5Gopen(_file_id, path.c_str(), H5P_DEFAULT);

	const size_t MAX_NAME = 256;
	char element_name[MAX_NAME];

	hsize_t object_count;
	H5Gget_num_objs(group_id, &object_count);

	std::vector<std::string> result;

	for(std::size_t i = 0; i < object_count; ++i)
	{

		int object_type = H5Gget_objtype_by_idx(group_id, i);
		H5Gget_objname_by_idx(group_id, i, element_name, MAX_NAME);

		if(object_type == desired_type)
			result.push_back(std::string(element_name));
	}

	return result;
}
Example #9
0
H5Object & H5LinksList::getObject(const int pos, const bool checkPos)
{
    if (checkPos)
    {
        unsigned int size = getSize();
        if (pos < 0 || pos >= size)
        {
            throw H5Exception(__LINE__, __FILE__, _("Invalid index %d: must be between 0 and %d."), pos, size);
        }
    }

    H5Object * obj = 0;
    hid_t parentId = getParent().getH5Id();
    ssize_t nameSize = H5Gget_objname_by_idx(parentId, (hsize_t)pos, 0, 0);
    char * name = (char *)MALLOC((nameSize + 1) * sizeof(char));
    H5Gget_objname_by_idx(parentId, (hsize_t)pos, name, nameSize + 1);
    int type = H5Gget_objtype_by_idx(parentId, (hsize_t)pos);

    switch (type)
    {
        case H5G_LINK:
            obj = &H5Link::getLink(getParent(), name);
            break;
        case H5G_GROUP:
            obj = new H5Group(getParent(), name);
            break;
        case H5G_DATASET:
            obj = new H5Dataset(getParent(), name);
            break;
        case H5G_TYPE:
            obj = new H5Type(getParent(), name);
            break;
    }

    return *obj;
}
Example #10
0
bool HBase::isChildData(hsize_t i)
{
	int otype = H5Gget_objtype_by_idx(fObjectId, (size_t)i);
	return otype == H5G_DATASET;
}
Example #11
0
bool HBase::isChildGroup(hsize_t i)
{
	int otype = H5Gget_objtype_by_idx(fObjectId, (size_t)i);
	return otype == H5G_GROUP;
}
void read_amuse_hdf5_data(char *filename,
                           int maxtypes,
                           int npartoftype[maxtypes],
                           int ncol,
                           int isrequired[ncol],
                           int *ierr)
   {
   hid_t     file_id;
   hid_t     group_id, group_id1, group_id2;
   herr_t    status;
   herr_t    HDF5_error = -1;
   char      groupname[12];
   char      datasetname[256];
   int i;

   if (debug) printf("DEBUG: re-opening %s \n",filename);
   file_id = H5Fopen(filename,H5F_ACC_RDONLY,H5P_DEFAULT);
   if (file_id == HDF5_error)
      { printf("ERROR re-opening %s \n",filename); *ierr = 1; return; }

   /* open main particles group */
   char *maingroup = "particles";
#if H5_VERSION_GE(1,8,0)
   group_id1 = H5Gopen2(file_id,maingroup,H5P_DEFAULT);
#else
   group_id1 = H5Gopen(file_id,maingroup);
#endif
   if (debug) printf("DEBUG: maxtypes = %i\n",maxtypes);
   
   /* read dataset for each particle type present in dump file */
   int itype,iobjtype;
   for (itype=0;itype<maxtypes;itype++) {
      if (debug) printf("DEBUG: type %i npartoftype = %i\n",itype,npartoftype[itype]);
      if (npartoftype[itype] > 0) {
         /* If npartoftype[N] > 0 in header, look for dataset of the form 000000000N */
         sprintf(groupname,"00000000%02i",itype+1);
         if (debug) printf("DEBUG: opening group %s\n",groupname);
#if H5_VERSION_GE(1,8,0)
         group_id = H5Gopen2(group_id1,groupname,H5P_DEFAULT);
#else
         group_id = H5Gopen(group_id1,groupname);
#endif
         if (group_id == HDF5_error)
            { printf("ERROR opening %s group \n",groupname); *ierr = 2; }
         else {

#if H5_VERSION_GE(1,8,0)
            group_id2 = H5Gopen2(group_id,"attributes",H5P_DEFAULT);
#else
            group_id2 = H5Gopen(group_id,"attributes");
#endif
            if (group_id2 == HDF5_error)
               { printf("ERROR opening attributes group \n"); *ierr = 2; }
            else {

               hsize_t ndatasets;
               status = H5Gget_num_objs(group_id2, &ndatasets);
               if (debug) printf("DEBUG: number of datasets = %i \n",(int)ndatasets);

               int j = 0;
               /* always read particle positions first */
               *ierr = read_amuse_hdf5_dataset(group_id2,"x",itype,maxtypes,npartoftype,ncol,isrequired,&j);
               j = 1;
               *ierr = read_amuse_hdf5_dataset(group_id2,"y",itype,maxtypes,npartoftype,ncol,isrequired,&j);
               j = 2;
               *ierr = read_amuse_hdf5_dataset(group_id2,"z",itype,maxtypes,npartoftype,ncol,isrequired,&j);

               /* read remaining datasets in the order they appear in the file */
               for(i=0; i < (int)ndatasets; i++) {
                   status       = H5Gget_objname_by_idx(group_id2, i, datasetname, 256);
                   iobjtype     = H5Gget_objtype_by_idx(group_id2, i);
                   if (strcmp(datasetname,"x")&&
                       strcmp(datasetname,"y")&&
                       strcmp(datasetname,"z")&& (iobjtype == H5G_DATASET)) {
                      *ierr = read_amuse_hdf5_dataset(group_id2,datasetname,itype,maxtypes,npartoftype,ncol,isrequired,&j);
                   }
               }

               /* close "attributes" group */
               H5Gclose(group_id2);

            }
            
            H5Gclose(group_id);
         }
      }
   }
   H5Gclose(group_id1);

   status = H5Fclose( file_id );
   if (status == HDF5_error) { printf("ERROR closing file \n"); *ierr = 7; }

   }
Example #13
0
void rdiff(const char *name, hid_t f1, hid_t f2) {
  hid_t g1 = H5Gopen(f1, name, H5P_DEFAULT);
  hid_t g2 = H5Gopen(f2, name, H5P_DEFAULT);
  if (g1 >= 0 && g2 >= 0) {
    int n1 = H5Aget_num_attrs(g1);
    for (int i = 0; i < n1; i++) {
      char aname[MAXNAME];
      hid_t a1 = H5Aopen_idx(g1, i);
      assert(H5Aget_name(a1, MAXNAME, aname) < MAXNAME);
      H5Aclose(a1);
      if (!H5LTfind_attribute(g2, aname)) {
	printf("Only in %s[%s%s]\n", file1, name, aname);
	continue;
      }
      int d1, d2;
      H5LTget_attribute_ndims(f1, name, aname, &d1);
      H5LTget_attribute_ndims(f2, name, aname, &d2);
      assert(d1 <= 1 && d2 <= 1);
      hsize_t dims1, dims2;
      H5T_class_t t1, t2;
      size_t ts1, ts2;
      H5LTget_attribute_info(f1, name, aname, &dims1, &t1, &ts1);
      H5LTget_attribute_info(f2, name, aname, &dims2, &t2, &ts2);
      assert(t1 == t2);
      assert(t1 == H5T_INTEGER || t1 == H5T_FLOAT || t1 == H5T_STRING);
      if (t1 == H5T_INTEGER) {
	assert(d1==0 || (dims1 == 1 && dims2 == 1));
	assert(ts1 == 4 && ts2 == 4);
	int v1, v2;
	H5LTget_attribute_int(f1, name, aname, &v1);
	H5LTget_attribute_int(f2, name, aname, &v2);
	if (v1 != v2) {
	  printf("%s[%s%s]=%d %s[%s%s]=%d\n", file1, name, aname, v1, file2, name, aname, v2);
	}
      }
      if (t1 == H5T_FLOAT) {
	assert(d1==0 || (dims1 == 1 && dims2 == 1));
	assert(ts1 == 4 && ts2 == 4);
	float v1, v2;
	H5LTget_attribute_float(f1, name, aname, &v1);
	H5LTget_attribute_float(f2, name, aname, &v2);
	if (v1 != v2) {
	  printf("%s[%s%s]=%g %s[%s%s]=%g\n", file1, name, aname, v1, file2, name, aname, v2);
	}
      }
      if (t1 == H5T_STRING) {
	assert(ts1 < 256 && ts2 < 256);
	char buf1[256];
	char buf2[256];
	H5LTget_attribute_string(f1, name, aname, buf1);
	H5LTget_attribute_string(f2, name, aname, buf2);
	if (strcmp(buf1, buf2)) {
	  printf("%s[%s%s]=%s %s[%s%s]=%s\n", file1, name, aname, buf1, file2, name, aname, buf2);
	}
      }
    }
    int n2 = H5Aget_num_attrs(g2);
    for (int i = 0; i < n2; i++) {
      char aname[MAXNAME];
      hid_t a2 = H5Aopen_idx(g2, i);
      assert(H5Aget_name(a2, MAXNAME, aname) < MAXNAME);
      H5Aclose(a2);
      if (!H5LTfind_attribute(g1, aname)) {
	printf("Only in %s[%s%s]\n", file2, name, aname);
	continue;
      }
    }

    hsize_t nobj;
    H5Gget_num_objs(g1, &nobj);
    for (int i = 0; i < nobj; i++) {
      char oname[MAXNAME];
      assert(H5Gget_objname_by_idx(g1, i, oname, MAXNAME) < MAXNAME);
      int otype = H5Gget_objtype_by_idx(g1, i);
      assert(otype == H5G_DATASET);
      if (!H5LTfind_dataset(g2, oname)) {
	printf("Only in %s[%s%s]\n", file1, name, oname);
	continue;
      }
      hsize_t dims1[2], dims2[2];
      H5T_class_t t1, t2;
      size_t ts1, ts2;
      H5LTget_dataset_info(g1, oname, dims1, &t1, &ts1);
      H5LTget_dataset_info(g2, oname, dims2, &t2, &ts2);
      if (dims1[0] != dims2[0] || dims1[1] != dims2[1]) {
	printf("%s[%s%s](%d,%d) != %s[%s%s](%d,%d)\n", 
	       file1, name, oname, dims1[1], dims1[0],
	       file2, name, oname, dims2[1], dims2[0]);
	continue;
      }
      float *data1 = malloc(dims1[0]*dims1[1]*sizeof(float));
      float *data2 = malloc(dims1[0]*dims1[1]*sizeof(float));
      H5LTread_dataset_float(g1, oname, data1);
      H5LTread_dataset_float(g2, oname, data2);
      float maxdiff = 0;
      for (int i = dims1[0]*dims1[1]-1; i >= 0; i--) {
	float d = data1[i] - data2[i];
	if (d < 0) d = -d;
	if (d > maxdiff) maxdiff = d;
      }
      printf("max |%s[%s%s] - %s[%s%s]| = %g\n",
	     file1, name, oname, file2, name, oname, maxdiff);
      free(data1); free(data2);
    }
    H5Gget_num_objs(g2, &nobj);
    for (int i = 0; i < nobj; i++) {
      char oname[MAXNAME];
      assert(H5Gget_objname_by_idx(g2, i, oname, MAXNAME) < MAXNAME);
      int otype = H5Gget_objtype_by_idx(g2, i);
      assert(otype == H5G_DATASET);
      if (!H5LTfind_dataset(g1, oname)) {
	printf("Only in %s[%s%s]\n", file2, name, oname);
	continue;
      }
    }
    H5Gclose(g1);
    H5Gclose(g2);
  } else if (g1 >= 0) {
    printf("Only in %s:%s\n", file1, name);
    H5Gclose(g1);
  } else if (g2 >= 0) {
    printf("Only in %s:%s\n", file2, name);
    H5Gclose(g2);
  } else {
    printf("Group %s does not exist in either file.\n", name);
  }
}
int
rec_scan_group(hid_t grpid)
{
   hid_t spaceid, datasetid = 0, child_grpid;
   hsize_t num_obj, i;
   int obj_class;
   char obj_name[STR_LEN + 1];
   htri_t is_scale;
   int num_scales;
   hsize_t dims[MAX_DIMS], max_dims[MAX_DIMS];
   int ndims, d;
   
   /* Loop through datasets to find variables. */
   if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
   for (i=0; i<num_obj; i++)
   {
      /* Get the type (i.e. group, dataset, etc.), and the name of
       * the object. */
      if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
      if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
      /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", 
	obj_class, obj_name);*/

      /* Deal with groups and datasets, ignore the rest. */
      switch(obj_class)
      {
	 case H5G_GROUP:
	    if ((child_grpid = H5Gopen(grpid, obj_name)) < 0) ERR;
	    if (rec_scan_group(child_grpid)) ERR;
	    break;
	 case H5G_DATASET:
	    /* Open the dataset. */
	    if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
	    /*printf("\nobj_name %s\n", obj_name);*/

	    /* Get the dimensions of this dataset. */
	    if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	    if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
	    if (ndims > MAX_DIMS) ERR;
	    if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;

	    /* Is this a dimscale? */
	    if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	    if (is_scale)
	    {
	       /*printf("dimension scale! Hoorah for the Pirate King!\n");*/
	    }
	    else
	    {
	       int visitor_data = 0;
		  
	       /* Here's how to get the number of scales attached
		* to the dataset's dimension 0. */
	       if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
	       if (num_scales != 1) ERR;

	       /* Go through all dimscales for this var and learn about them. */
	       for (d = 0; d < ndims; d++)
		  if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
					 &visitor_data) < 0) ERR;
	    }
	    if (H5Dclose(datasetid) < 0) ERR;
	    break;
	 case H5G_TYPE:
	    printf("found a type!\n");
	    break;
	 case H5G_LINK:
	    printf("found a link! Yikes!\n");
	    break;
	 default:
	    printf("Unknown object class %d!", obj_class);
      }
   }

   return 0;
}
int
main()
{
   printf("\n*** Checking HDF5 dimension scales.\n");
#define GRP_NAME "simple_scales"
#define DIMSCALE_NAME "dimscale"
#define NAME_ATTRIBUTE "Billy-Bob"
#define VAR1_NAME "var1"
#define VAR2_NAME "var2"
#define VAR3_NAME "var3"
#define DIM1_LEN 3
#define DIM2_LEN 2
#define FIFTIES_SONG "Mamma said they'll be days like this. They'll be days like this, my mamma said."

   printf("*** Creating simple dimension scales file...");
   {
      hid_t fileid, grpid, dimscaleid;
      hid_t dimscale_spaceid, var1_spaceid, var3_spaceid;
      hid_t var1_datasetid, var2_datasetid, var3_datasetid;
      hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
      hsize_t dimscale_dims[1] = {DIM1_LEN};

      /* Open file and create group. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, 
			      H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
      
      /* Create our dimension scale. Use the built-in NAME attribute
       * on the dimscale. */
      if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims, 
					       dimscale_dims)) < 0) ERR;
      if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT, 
				  dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;

      /* Create a 1D variable which uses the dimscale. Attach a label
       * to this scale. */
      if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      if ((var1_datasetid = H5Dcreate(grpid, VAR1_NAME, H5T_NATIVE_INT, 
				      var1_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSattach_scale(var1_datasetid, dimscaleid, 0) < 0) ERR;
      if (H5DSset_label(var1_datasetid, 0, FIFTIES_SONG) < 0) ERR;

      /* Create a 1D variabls that doesn't use the dimension scale. */
      if ((var2_datasetid = H5Dcreate(grpid, VAR2_NAME, H5T_NATIVE_INT, 
				      var1_spaceid, H5P_DEFAULT)) < 0) ERR;

      /* Create a 2D dataset which uses the scale for one of its
       * dimensions. */
      if ((var3_spaceid = H5Screate_simple(2, dims, dims)) < 0) ERR;
      if ((var3_datasetid = H5Dcreate(grpid, VAR3_NAME, H5T_NATIVE_INT, 
				      var3_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSattach_scale(var3_datasetid, dimscaleid, 0) < 0) ERR;

      /* Close up the shop. */
      if (H5Dclose(dimscaleid) < 0 ||
	  H5Dclose(var1_datasetid) < 0 ||
	  H5Dclose(var2_datasetid) < 0 ||
	  H5Dclose(var3_datasetid) < 0 ||
	  H5Sclose(var1_spaceid) < 0 ||
	  H5Sclose(var3_spaceid) < 0 ||
	  H5Sclose(dimscale_spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;

      /* HELP! If you are reading this in the future, and time
       * machines have been invented, please come back to July 10,
       * 2005, the Java Java coffee shop in Lafayette, 8:00 am MST +-
       * 20 minutes. Bring back some advanced weapons systems to
       * destroy the sound system here, which is playing 50's rock and
       * roll. Do-op, do-op, la-ma la-ma, ding dong. Save me!!! (Mind
       * you, James Brown is a different story!) */
   }
   SUMMARIZE_ERR;
   printf("*** Checking that simple dimscale file can be read...");
   {
      hid_t fileid, grpid, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[STR_LEN + 1];
      htri_t is_scale;
      int num_scales;

      /* Reopen the file and group. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
      
      /* Loop through datasets to find variables. */
      if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of the
	  * object. Confusingly, this is a different type than the type
	  * of a variable. This type might be better called "class" or
	  * "type of type"  */
	 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
	 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/

	 /* Deal with groups and datasets. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:

	       /*Close the last datasetid, if one is open. */
	       if (datasetid > 0)
	       {
		  H5Dclose(datasetid);
	       }
	       
	       if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
	       if (is_scale)
	       {
		  char nom_de_quincey[STR_LEN+1];

		  /* A dimscale comes with a NAME attribute, in
		   * addition to its real name. */
		  if (H5DSget_scale_name(datasetid, nom_de_quincey, 
					 STR_LEN) < 0) ERR;
		  if (strcmp(nom_de_quincey, NAME_ATTRIBUTE)) ERR;

		  /*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/

	       }
	       else
	       {
		  char label[STR_LEN+1];

		  /* Here's how to get the number of scales attached
		   * to the dataset. I would think that this would
		   * return 0 scales for a dataset that doesn't have
		   * scales, but instead it errors. So take an error
		   * to be the same as no dimension scales. */
		  num_scales = H5DSget_num_scales(datasetid, 0);
		  if (strcmp(obj_name, VAR1_NAME) == 0 && num_scales != 1) ERR;
		  if (strcmp(obj_name, VAR2_NAME) == 0 && num_scales > 0) ERR;
		  if (strcmp(obj_name, VAR3_NAME) == 0 && num_scales != 1) ERR;
		  
		  /* There's also a label for dimension 0 of var1. */
		  if (strcmp(obj_name, VAR1_NAME) == 0)
		  {
		     if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
		     if (strcmp(label, FIFTIES_SONG)) ERR;
		  }
	       }
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Dclose(datasetid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating simple dimension scales file with lots of datasets...");

#define NUM_DATASETS 500
   {
      hid_t fileid, grpid, dimscaleid;
      hid_t dimscale_spaceid, var1_spaceid;
      hid_t var1_datasetid[NUM_DATASETS];
      hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
      hsize_t dimscale_dims[1] = {DIM1_LEN};
      char var_name[STR_LEN + 1];
      int v;

      /* Open file and create group. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, 
			      H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;
      
      /* Create our dimension scale. Use the built-in NAME attribute
       * on the dimscale. */
      if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims, 
					       dimscale_dims)) < 0) ERR;
      if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT, 
				  dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;

      /* Create many 1D datasets which use the dimscale. */
      if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      for (v = 0; v < NUM_DATASETS; v++)
      {
	 sprintf(var_name, "var_%d", v);
	 if ((var1_datasetid[v] = H5Dcreate(grpid, var_name, H5T_NATIVE_INT, 
					    var1_spaceid, H5P_DEFAULT)) < 0) ERR;
	 if (H5DSattach_scale(var1_datasetid[v], dimscaleid, 0) < 0) ERR;
      }

      /* Close up the shop. */
      for (v = 0; v < NUM_DATASETS; v++)
	 if (H5Dclose(var1_datasetid[v]) < 0) ERR;
      if (H5Dclose(dimscaleid) < 0 ||
	  H5Sclose(var1_spaceid) < 0 ||
	  H5Sclose(dimscale_spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating a file with an unlimited dimension scale...");

   {
      hid_t fileid, grpid, spaceid, datasetid, dimscaleid, cparmsid;
      hsize_t dims[1] = {1}, maxdims[1] = {H5S_UNLIMITED};

      /* Create file and group. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT, 
			      H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;

      if ((spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;

      /* Modify dataset creation properties, i.e. enable chunking  */
      if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;

      /* Create our dimension scale, as an unlimited dataset. */
      if ((dimscaleid = H5Dcreate(grpid, DIMSCALE_NAME, H5T_NATIVE_INT, 
				  spaceid, cparmsid)) < 0) ERR;
      if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;

      /* Create a variable which uses it. */
      if ((datasetid = H5Dcreate(grpid, VAR1_NAME, H5T_NATIVE_INT, 
				 spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(datasetid, dimscaleid, 0) < 0) ERR;
      if (H5DSset_label(datasetid, 0, "dimension label") < 0) ERR;

      /* Close up the shop. */
      if (H5Dclose(dimscaleid) < 0 ||
	  H5Dclose(datasetid) < 0 ||
	  H5Sclose(spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
#ifdef EXTRA_TESTS
   printf("*** Checking that unlimited dimscale file can be read...");

   {
      hid_t fileid, grpid, spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[STR_LEN + 1];
      htri_t is_scale;
      int num_scales;
      hsize_t dims[1], maxdims[1];

      /* Reopen the file and group. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
      
      /* Loop through datasets to find variables. */
      if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
	 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/

	 /* Deal with groups and datasets. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:

	       /*Close the last datasetid, if one is open. */
	       if (datasetid > 0)
	       {
		  H5Dclose(datasetid);
		  datasetid = 0;
	       }
	       
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;

	       /* This should be an unlimited dataset. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if (maxdims[0] != H5S_UNLIMITED) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
	       if (is_scale)
	       {
		  char nom_de_quincey[STR_LEN+1];

		  /* A dimscale comes with a NAME attribute, in
		   * addition to its real name. */
		  if (H5DSget_scale_name(datasetid, nom_de_quincey, STR_LEN) < 0) ERR;
		  /*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/

	       }
	       else
	       {
		  char label[STR_LEN+1];
		  int visitor_data = 0;

		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor, 
					 &visitor_data) < 0) ERR;
		  
		  /* There's also a label for dimension 0. */
		  if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;

		  /*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/
	       }
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Dclose(datasetid) < 0 ||
	  H5Sclose(spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating some 3D datasets using shared dimscales...");

   {
#define NDIMS 3
#define TIME_DIM 0      
#define LAT_DIM 1
#define LON_DIM 2
#define LAT_LEN 2
#define LON_LEN 3
#define LAT_NAME "Lat"
#define LON_NAME "Lon"
#define TIME_NAME "Time"
#define PRES_NAME "Pressure"
#define TEMP_NAME "Temperature"

      hid_t fileid, grpid, lat_spaceid, lon_spaceid, time_spaceid, spaceid;
      hid_t lat_scaleid, lon_scaleid, time_scaleid;
      hid_t pres_dsid, temp_dsid, cparmsid;
      hsize_t dims[NDIMS], max_dims[NDIMS];

      /* Create file and group. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
			      H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gcreate(fileid, GRP_NAME, 0)) < 0) ERR;

      /* Create 3 1D spaces for the 3 dimension scale datasets. Time
       * starts out as size 0. It's an unlimited dimension scale. */
      dims[0] = 0;
      max_dims[0] = H5S_UNLIMITED;
      if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
      dims[0] = LAT_LEN;
      max_dims[0] = LAT_LEN;
      if ((lat_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
      dims[0] = LON_LEN;
      max_dims[0] = LON_LEN;
      if ((lon_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;

      /* Enable chunking for unlimited time scale.  */
      if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      dims[TIME_DIM] = 1;
      if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;

      /* Create our dimension scales. */
      if ((time_scaleid = H5Dcreate(grpid, TIME_NAME, H5T_NATIVE_INT,
				    time_spaceid, cparmsid)) < 0) ERR;
      if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
      if ((lat_scaleid = H5Dcreate(grpid, LAT_NAME, H5T_NATIVE_FLOAT,
				   lat_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lat_scaleid, LAT_NAME) < 0) ERR;
      if ((lon_scaleid = H5Dcreate(grpid, LON_NAME, H5T_NATIVE_FLOAT,
				   lon_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lon_scaleid, LON_NAME) < 0) ERR;

      /* Create a space coresponding to these three dimensions. */
      dims[TIME_DIM] = 0;
      dims[LAT_DIM] = LAT_LEN;
      dims[LON_DIM] = LON_LEN;
      max_dims[TIME_DIM] = H5S_UNLIMITED;
      max_dims[LAT_DIM] = LAT_LEN;
      max_dims[LON_DIM] = LON_LEN;
      if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;

      /* Create two variables which use them, and attach the dimension scales. */
      dims[TIME_DIM] = 1;
      if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
      if ((pres_dsid = H5Dcreate(grpid, PRES_NAME, H5T_NATIVE_FLOAT,
				 spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(pres_dsid, time_scaleid, 0) < 0) ERR;
      if (H5DSattach_scale(pres_dsid, lat_scaleid, 1) < 0) ERR;
      if (H5DSattach_scale(pres_dsid, lon_scaleid, 2) < 0) ERR;
      if (H5DSset_label(pres_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
      if (H5DSset_label(pres_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
      if (H5DSset_label(pres_dsid, LON_DIM, LON_NAME) < 0) ERR;
      if ((temp_dsid = H5Dcreate(grpid, TEMP_NAME, H5T_NATIVE_FLOAT,
				 spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(temp_dsid, time_scaleid, 0) < 0) ERR;
      if (H5DSattach_scale(temp_dsid, lat_scaleid, 1) < 0) ERR;
      if (H5DSattach_scale(temp_dsid, lon_scaleid, 2) < 0) ERR;
      if (H5DSset_label(temp_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
      if (H5DSset_label(temp_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
      if (H5DSset_label(temp_dsid, LON_DIM, LON_NAME) < 0) ERR;

      /* Close up the shop. */
      if (H5Dclose(pres_dsid) < 0 ||
	  H5Dclose(temp_dsid) < 0 ||
	  H5Dclose(lat_scaleid) < 0 ||
	  H5Dclose(lon_scaleid) < 0 ||
	  H5Dclose(time_scaleid) < 0 ||
	  H5Sclose(spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Checking 3D datasets created with shared dimscales...");

   {
      hid_t fileid, grpid, spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[STR_LEN + 1];
      htri_t is_scale;
      int num_scales;
      hsize_t dims[NDIMS], max_dims[NDIMS];
      int d;

      /* Reopen the file and group. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gopen(fileid, GRP_NAME)) < 0) ERR;
      
      /* Loop through datasets to find variables. */
      if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
	 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/

	 /* Deal with groups and datasets. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen(grpid, obj_name)) < 0) ERR;
	       /*printf("\nobj_name %s\n", obj_name);*/

	       /* Get the dimensions of this dataset. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale)
	       {
		  char nom_de_quincey[STR_LEN+1];

		  /* A dimscale comes with a NAME attribute, in
		   * addition to its real name. */
		  if (H5DSget_scale_name(datasetid, nom_de_quincey, 
					 STR_LEN) < 0) ERR;
		  /*printf("found scale %s, NAME %s id 0x%x\n", obj_name, 
		    nom_de_quincey, datasetid);*/

		  /* Check size depending on name. */
		  if ((!strcmp(obj_name, LAT_NAME) && dims[TIME_DIM] != LAT_LEN) ||
		      (!strcmp(obj_name, LON_NAME) && dims[TIME_DIM] != LON_LEN) ||
		      (!strcmp(obj_name, TIME_NAME) && 
		       max_dims[TIME_DIM] != H5S_UNLIMITED)) ERR;

	       }
	       else
	       {
		  char label[STR_LEN+1];
		  int visitor_data = 0;
		  
		  /* SHould have these dimensions... */
		  if (dims[TIME_DIM] != 0 || dims[LAT_DIM] != LAT_LEN || 
		      dims[LON_DIM] != LON_LEN) ERR;
		  if (max_dims[TIME_DIM] != H5S_UNLIMITED) ERR;

		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn
		   * about them. What I want is the dataset id of each
		   * dimscale. Then... */
		  for (d = 0; d < NDIMS; d++)
		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
					    &visitor_data) < 0) ERR;
		  /*printf("visitor_data: 0x%x\n", visitor_data);*/
		  
		  /* There's also a label for each dimension. */
		  if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
		  if (strcmp(label, TIME_NAME)) ERR;
		  if (H5DSget_label(datasetid, 1, label, STR_LEN) < 0) ERR;
		  if (strcmp(label, LAT_NAME)) ERR;
		  if (H5DSget_label(datasetid, 2, label, STR_LEN) < 0) ERR;
		  if (strcmp(label, LON_NAME)) ERR;
	       }
	       if (H5Dclose(datasetid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Sclose(spaceid) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating 3D datasets using shared dimscales in groups...");

   {
#define FATHER "Adam"
#define GOOD_CHILD "Able"
#define BAD_CHILD "Cain"
#define DISTANCE_LEN 3
#define SMELLINESS_NAME "Smelliness"
#define DISTANCE_NAME "Distance"
#define TIME_NAME "Time"
#define TIME_DIM 0      
#define SMELLINESS_DIM 1
#define DISTANCE_DIM 2
#define GOAT_NAME "Billy_goat_gruff"
#define CAMEL_NAME "Grumpy_the_camel"

      hid_t fileid, smelliness_spaceid, distance_spaceid, time_spaceid, spaceid;
      hid_t adam_grpid, able_grpid, cain_grpid;
      hid_t time_scaleid, smelliness_scaleid, distance_scaleid;
      hid_t goat_dsid, camel_dsid, cparmsid;
      hsize_t dims[NDIMS], max_dims[NDIMS];

      /* Create file and group. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
			      H5P_DEFAULT)) < 0) ERR;
      if ((adam_grpid = H5Gcreate(fileid, FATHER, 0)) < 0) ERR;
      if ((able_grpid = H5Gcreate(adam_grpid, GOOD_CHILD, 0)) < 0) ERR;
      if ((cain_grpid = H5Gcreate(adam_grpid, BAD_CHILD, 0)) < 0) ERR;

      /* Create 3 1D spaces for the 3 dimension scale datasets. Time
       * and smelliness starts out as 0. They are unlimited dimension
       * scales. */
      dims[0] = 0;
      max_dims[0] = H5S_UNLIMITED;
      if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
      dims[0] = 0;
      max_dims[0] = H5S_UNLIMITED;
      if ((smelliness_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
      dims[0] = DISTANCE_LEN;
      max_dims[0] = DISTANCE_LEN;
      if ((distance_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;

      /* Enable chunking for unlimited time and smelliness scale. */
      if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      dims[0] = 1;
      if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;

      /* Create our dimension scales. */
      if ((time_scaleid = H5Dcreate(adam_grpid, TIME_NAME, H5T_NATIVE_INT,
				    time_spaceid, cparmsid)) < 0) ERR;
      if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
      if ((smelliness_scaleid = H5Dcreate(adam_grpid, SMELLINESS_NAME, H5T_NATIVE_FLOAT,
					  smelliness_spaceid, cparmsid)) < 0) ERR;
      if (H5DSset_scale(smelliness_scaleid, SMELLINESS_NAME) < 0) ERR;
      if ((distance_scaleid = H5Dcreate(adam_grpid, DISTANCE_NAME, H5T_NATIVE_FLOAT,
					distance_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(distance_scaleid, DISTANCE_NAME) < 0) ERR;

      /* Create a space coresponding to these three dimensions. */
      dims[TIME_DIM] = 0;
      dims[SMELLINESS_DIM] = 0;
      dims[DISTANCE_DIM] = DISTANCE_LEN;
      max_dims[TIME_DIM] = H5S_UNLIMITED;
      max_dims[SMELLINESS_DIM] = H5S_UNLIMITED;
      max_dims[DISTANCE_DIM] = DISTANCE_LEN;
      if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;

      /* Set up chunking for our 3D vars. */
      dims[TIME_DIM] = 1;
      dims[SMELLINESS_DIM] = 1;
      if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;

      /* Create two variables which use them, and attach the dimension scales. */
      if ((goat_dsid = H5Dcreate(able_grpid, GOAT_NAME, H5T_NATIVE_FLOAT,
				 spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(goat_dsid, time_scaleid, 0) < 0) ERR;
      if (H5DSattach_scale(goat_dsid, smelliness_scaleid, 1) < 0) ERR;
      if (H5DSattach_scale(goat_dsid, distance_scaleid, 2) < 0) ERR;
      if ((camel_dsid = H5Dcreate(cain_grpid, CAMEL_NAME, H5T_NATIVE_FLOAT,
				  spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(camel_dsid, time_scaleid, 0) < 0) ERR;
      if (H5DSattach_scale(camel_dsid, smelliness_scaleid, 1) < 0) ERR;
      if (H5DSattach_scale(camel_dsid, distance_scaleid, 2) < 0) ERR;

      /* Close up the shop. */
      if (H5Dclose(goat_dsid) < 0 ||
	  H5Dclose(camel_dsid) < 0 ||
	  H5Dclose(smelliness_scaleid) < 0 ||
	  H5Dclose(distance_scaleid) < 0 ||
	  H5Dclose(time_scaleid) < 0 ||
	  H5Sclose(spaceid) < 0 ||
	  H5Gclose(cain_grpid) < 0 ||
	  H5Gclose(able_grpid) < 0 ||
	  H5Gclose(adam_grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Checking 3D datasets in groups created with shared dimscales...");

   {
      hid_t fileid, grpid;

      /* Reopen the file and group. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gopen(fileid, FATHER)) < 0) ERR;

      /* If we can't scan the group, crash into a flaming heap of
       * smoking, smoldering rubbish. */
      if (rec_scan_group(grpid)) ERR;
      
      /* Close up the shop. */
      if (H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
#endif
   FINAL_RESULTS;
}
int
main()
{
   printf("\n*** Checking HDF5 dimscales some more.\n");
   printf("*** Creating a file with one var with one dimension scale...");
   
   {
      hid_t fileid, spaceid, datasetid, dimscaleid, cparmsid;
      hsize_t dims[NDIMS] = {DIM1_LEN}, maxdims[NDIMS] = {H5S_UNLIMITED};

      /* Create file. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
			      H5P_DEFAULT)) < 0) ERR;

      /* Create the space that will be used both for the dimscale and
       * the 1D dataset that will attach it. */
      if ((spaceid = H5Screate_simple(NDIMS, dims, maxdims)) < 0) ERR;

      /* Modify dataset creation properties, i.e. enable chunking. */
      dims[0] = 1;
      if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;

      /* Create our dimension scale, as an unlimited dataset. */
      if ((dimscaleid = H5Dcreate(fileid, DIMSCALE_NAME, H5T_NATIVE_INT,
				  spaceid, cparmsid)) < 0) ERR;
      if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;

      /* Create a variable which uses it. */
      if ((datasetid = H5Dcreate(fileid, VAR1_NAME, H5T_NATIVE_INT,
				 spaceid, cparmsid)) < 0) ERR;
      if (H5DSattach_scale(datasetid, dimscaleid, 0) < 0) ERR;
      if (H5DSset_label(datasetid, 0, DIMSCALE_LABEL) < 0) ERR;

      /* Fold up our tents. */
      if (H5Dclose(dimscaleid) < 0 ||
	  H5Dclose(datasetid) < 0 ||
	  H5Sclose(spaceid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Checking that one var, one dimscale file can be read...");

   {
      hid_t fileid, spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[NC_MAX_NAME + 1];
      char dimscale_name[NC_MAX_NAME+1];
      htri_t is_scale;
      char label[NC_MAX_NAME+1];
      int num_scales;
      hsize_t dims[1], maxdims[1];
      H5G_stat_t statbuf;
      HDF5_OBJID_T dimscale_obj, vars_dimscale_obj;

      /* Open the file. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      
      /* Loop through objects in the root group. */
      if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(fileid, i, obj_name, NC_MAX_NAME) < 0) ERR;

	 /*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n",
	   obj_class, obj_name);*/

	 /* Deal with object based on its obj_class. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;

	       /* This should be an unlimited dataset. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if (maxdims[0] != H5S_UNLIMITED) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
	       if (is_scale)
	       {
		  /* A dimscale comes with a NAME attribute, in
		   * addition to its real name. */
		  if (H5DSget_scale_name(datasetid, dimscale_name, NC_MAX_NAME) < 0) ERR;
		  if (strcmp(dimscale_name, NAME_ATTRIBUTE)) ERR;

		  /* fileno and objno uniquely identify an object and a
		   * HDF5 file. */
		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
		  dimscale_obj.fileno[0] = statbuf.fileno[0];
		  dimscale_obj.objno[0] = statbuf.objno[0];
		  dimscale_obj.fileno[1] = statbuf.fileno[1];
		  dimscale_obj.objno[1] = statbuf.objno[1];
		  /*printf("statbuf.fileno = %d statbuf.objno = %d\n",
		    statbuf.fileno, statbuf.objno);*/

	       }
	       else
	       {
		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor,
					 &vars_dimscale_obj) < 0) ERR;
		  /*printf("vars_dimscale_obj.fileno = %d vars_dimscale_obj.objno = %d\n",
		    vars_dimscale_obj.fileno, vars_dimscale_obj.objno);*/
		  if (vars_dimscale_obj.fileno[0] != dimscale_obj.fileno[0] ||
		      vars_dimscale_obj.objno[0] != dimscale_obj.objno[0] ||
		      vars_dimscale_obj.fileno[1] != dimscale_obj.fileno[1] ||
		      vars_dimscale_obj.objno[1] != dimscale_obj.objno[1]) ERR;
		  
		  /* There's also a label for dimension 0. */
		  if (H5DSget_label(datasetid, 0, label, NC_MAX_NAME) < 0) ERR;

		  /*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/
	       }
	       if (H5Dclose(datasetid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Sclose(spaceid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Creating a file with one var with two dimension scales...");
   
   {
#define LAT_LEN 3
#define LON_LEN 2
#define DIMS_2 2
#define LAT_NAME "lat"
#define LON_NAME "lon"
#define PRES_NAME "pres"
      
      hid_t fileid, lat_spaceid, lon_spaceid, pres_spaceid;
      hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid;
      hsize_t dims[DIMS_2];

      /* Create file. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
			      H5P_DEFAULT)) < 0) ERR;

      /* Create the spaces that will be used for the dimscales. */
      dims[0] = LAT_LEN;
      if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = LON_LEN;
      if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;

      /* Create the space for the dataset. */
      dims[0] = LAT_LEN;
      dims[1] = LON_LEN;
      if ((pres_spaceid = H5Screate_simple(DIMS_2, dims, dims)) < 0) ERR;

      /* Create our dimension scales. */
      if ((lat_dimscaleid = H5Dcreate(fileid, LAT_NAME, H5T_NATIVE_INT,
				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
      if ((lon_dimscaleid = H5Dcreate(fileid, LON_NAME, H5T_NATIVE_INT,
				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;

      /* Create a variable which uses these two dimscales. */
      if ((pres_datasetid = H5Dcreate(fileid, PRES_NAME, H5T_NATIVE_FLOAT,
				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;

      /* Fold up our tents. */
      if (H5Dclose(lat_dimscaleid) < 0 ||
	  H5Dclose(lon_dimscaleid) < 0 ||
	  H5Dclose(pres_datasetid) < 0 ||
	  H5Sclose(lat_spaceid) < 0 ||
	  H5Sclose(lon_spaceid) < 0 ||
	  H5Sclose(pres_spaceid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Checking that one var, two dimscales file can be read...");

   {
#define NDIMS2 2
      hid_t fileid, spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[NC_MAX_NAME + 1];
      htri_t is_scale;
      int num_scales;
      hsize_t dims[NDIMS2], maxdims[NDIMS2];
      H5G_stat_t statbuf;
      HDF5_OBJID_T dimscale_obj[2], vars_dimscale_obj[2];
      int dimscale_cnt = 0;
      int d, ndims;

      /* Open the file. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      
      /* Loop through objects in the root group. */
      if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(fileid, i, obj_name, NC_MAX_NAME) < 0) ERR;

/* 	 printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", */
/* 		obj_class, obj_name); */

	 /* Deal with object based on its obj_class. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;

	       /* Get space info. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
	       if (ndims > NDIMS2) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale)
	       {
		  /* fileno and objno uniquely identify an object and a
		   * HDF5 file. */
		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
/* 		  printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */
/* 			 dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt,  */
/* 			 dimscale_obj[dimscale_cnt].objno); */
		  dimscale_cnt++;
	       }
	       else
	       {
		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0 and 1. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;
		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  for (d = 0; d < ndims; d++)
		  {
		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
		     &(vars_dimscale_obj[d])) < 0) ERR;

		     /* Verify that the object ids passed from the
		      * alien_visitor2 function match the ones we found
		      * for the lat and lon datasets. */
		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
		  }
	       }
	       if (H5Dclose(datasetid) < 0) ERR;
	       if (H5Sclose(spaceid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Fclose(fileid) < 0) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** Creating a file with one var with two unlimited dimension scales...");
   {
#define U1_LEN 3
#define U2_LEN 2
#define DIMS2 2
#define U1_NAME "u1"
#define U2_NAME "u2"
#define VNAME "v1"
      
      hid_t fapl_id, fcpl_id, grpid, plistid, plistid2;
      hid_t fileid, lat_spaceid, lon_spaceid, pres_spaceid;
      hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid;
      hsize_t dims[DIMS2], maxdims[DIMS2], chunksize[DIMS2] = {10, 10};
      hid_t spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[NC_MAX_NAME + 1];
      htri_t is_scale;
      int num_scales;
      H5G_stat_t statbuf;
      HDF5_OBJID_T dimscale_obj[2], vars_dimscale_obj[2];
      int dimscale_cnt = 0;
      int d, ndims;

      /* Create file access and create property lists. */
      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
      if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
      
      /* Set latest_format in access propertly list. This ensures that
       * the latest, greatest, HDF5 versions are used in the file. */
      if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;

      /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
       * turns on HDF5 creation ordering in the file. */
      if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
      if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;

      /* Create file. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;

      /* Open the root group. */
      if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;

      /* Create the spaces that will be used for the dimscales. */
      dims[0] = 0;
      maxdims[0] = H5S_UNLIMITED;
      if ((lat_spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;
      if ((lon_spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;

      /* Create the space for the dataset. */
      dims[0] = 0;
      dims[1] = 0;
      maxdims[0] = H5S_UNLIMITED;
      maxdims[1] = H5S_UNLIMITED;
      if ((pres_spaceid = H5Screate_simple(DIMS2, dims, maxdims)) < 0) ERR;

      /* Set up the dataset creation property list for the two dimensions. */
      if ((plistid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      if (H5Pset_chunk(plistid, 1, chunksize) < 0) ERR;
      if (H5Pset_attr_creation_order(plistid, H5P_CRT_ORDER_TRACKED|
				     H5P_CRT_ORDER_INDEXED) < 0) ERR;

      /* Create our dimension scales. */
      if ((lat_dimscaleid = H5Dcreate(grpid, U1_NAME, H5T_NATIVE_INT,
				      lat_spaceid, plistid)) < 0) ERR;
      if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
      if ((lon_dimscaleid = H5Dcreate(grpid, U2_NAME, H5T_NATIVE_INT,
				      lon_spaceid, plistid)) < 0) ERR;
      if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;

      /* Set up the dataset creation property list for the variable. */
      if ((plistid2 = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
      if (H5Pset_chunk(plistid2, DIMS2, chunksize) < 0) ERR;
      if (H5Pset_attr_creation_order(plistid2, H5P_CRT_ORDER_TRACKED|
				     H5P_CRT_ORDER_INDEXED) < 0) ERR;

      /* Create a variable which uses these two dimscales. */
      if ((pres_datasetid = H5Dcreate(grpid, VNAME, H5T_NATIVE_DOUBLE, pres_spaceid,
				      plistid2)) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;

      /* Close down the show. */
      if (H5Pclose(fapl_id) < 0 ||
	  H5Pclose(fcpl_id) < 0 ||
	  H5Dclose(lat_dimscaleid) < 0 ||
	  H5Dclose(lon_dimscaleid) < 0 ||
	  H5Dclose(pres_datasetid) < 0 ||
	  H5Sclose(lat_spaceid) < 0 ||
	  H5Sclose(lon_spaceid) < 0 ||
	  H5Sclose(pres_spaceid) < 0 ||
	  H5Pclose(plistid) < 0 ||
	  H5Pclose(plistid2) < 0 ||
	  H5Gclose(grpid) < 0 ||
	  H5Fclose(fileid) < 0) ERR;

      /* Open the file. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      if ((grpid = H5Gopen2(fileid, "/", H5P_DEFAULT)) < 0) ERR;
      
      /* Loop through objects in the root group. */
      if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;

      for (i = 0; i < num_obj; i++)
      {
	 /*Get the type (i.e. group, dataset, etc.), and the name of
	   the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(grpid, i, obj_name, NC_MAX_NAME) < 0) ERR;

	 /* Deal with object based on its obj_class. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;

	       /* Get space info. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale)
	       {
		  /* fileno and objno uniquely identify an object and a
		   * HDF5 file. */
		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
		  dimscale_cnt++;
	       }
	       else
	       {
		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0 and 1. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;
		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  for (d = 0; d < ndims; d++)
		  {
		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
					    &(vars_dimscale_obj[d])) < 0) ERR;

		     /* Verify that the object ids passed from the
		      * alien_visitor2 function match the ones we found
		      * for the lat and lon datasets. */
		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
			 vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
			 vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
		  }

	       }

	       if (H5Dclose(datasetid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
     }

      /* Check the dimension lengths. */
      {
	 hid_t spaceid1;
	 hsize_t h5dimlen[DIMS2], h5dimlenmax[DIMS2];
	 int dataset_ndims;

	 /* Check U1. */
	 if ((datasetid = H5Dopen1(grpid, U1_NAME)) < 0) ERR;
	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 1 || h5dimlen[0] != 0 || h5dimlenmax[0] != H5S_UNLIMITED) ERR;
	 if (H5Dclose(datasetid) ||
	     H5Sclose(spaceid1)) ERR;

	 /* Check U2. */
	 if ((datasetid = H5Dopen1(grpid, U2_NAME)) < 0) ERR;
	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 1 || h5dimlen[0] != 0 || h5dimlenmax[0] != H5S_UNLIMITED) ERR;
	 if (H5Dclose(datasetid) ||
	     H5Sclose(spaceid1)) ERR;
	 
	 /* Check V1. */
	 if ((datasetid = H5Dopen1(grpid, VNAME)) < 0) ERR;
	 if ((spaceid1 = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(spaceid1, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 2 || h5dimlen[0] != 0 || h5dimlen[1] != 0 ||
	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;

	 /* All done. */
	 if (H5Dclose(datasetid) ||
	     H5Sclose(spaceid1)) ERR;
      }

      /* Write two hyperslabs. */
      {
#define NUM_VALS 3
	 hid_t file_spaceid, mem_spaceid;
	 hsize_t h5dimlen[DIMS2], h5dimlenmax[DIMS2], xtend_size[DIMS2] = {1, NUM_VALS};
	 hsize_t start[DIMS2] = {0, 0};
	 hsize_t count[DIMS2] = {1, NUM_VALS};
	 double value[NUM_VALS];
	 int dataset_ndims;
	 int i;

	 /* Set up phony data. */
	 for (i = 0; i < NUM_VALS; i++)
	    value[i] = (float)i;

	 /* Open the dataset, check its dimlens. */
	 if ((datasetid = H5Dopen1(grpid, VNAME)) < 0) ERR;
	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 2 || h5dimlen[0] != 0 || h5dimlen[1] != 0 ||
	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;

	 /* Extend the size of the dataset. */
	 if (H5Dextend(datasetid, xtend_size) < 0) ERR;
	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;

	 /* Check the size. */
	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 2 || h5dimlen[0] != 1 || h5dimlen[1] != NUM_VALS ||
	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;

	 /* Set up the file and memory spaces. */
	 if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
				 start, NULL, count, NULL) < 0) ERR;
	 if ((mem_spaceid = H5Screate_simple(DIMS2, count, NULL)) < 0) ERR;

	 /* Write a slice of data. */
	 if (H5Dwrite(datasetid, H5T_NATIVE_DOUBLE, mem_spaceid, file_spaceid,
		      H5P_DEFAULT, value) < 0)

	 /* Check the size. */
	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 2 || h5dimlen[0] != 1 || h5dimlen[1] != NUM_VALS ||
	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;

	 /* Extend the size of the dataset for the second slice. */
	 xtend_size[0]++;
	 if (H5Dextend(datasetid, xtend_size) < 0) ERR;
	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;

	 /* Set up the file and memory spaces for a second slice. */
	 start[0]++;
	 if (H5Sselect_hyperslab(file_spaceid, H5S_SELECT_SET,
				 start, NULL, count, NULL) < 0) ERR;
	 if ((mem_spaceid = H5Screate_simple(DIMS2, count, NULL)) < 0) ERR;

	 /* Write a second slice of data. */
	 if (H5Dwrite(datasetid, H5T_NATIVE_DOUBLE, mem_spaceid, file_spaceid,
		      H5P_DEFAULT, value) < 0)

	 /* Check the size again. */
	 if ((file_spaceid = H5Dget_space(datasetid)) < 0) ERR;
	 if ((dataset_ndims = H5Sget_simple_extent_dims(file_spaceid, h5dimlen,
							h5dimlenmax)) < 0) ERR;
	 if (dataset_ndims != 2 || h5dimlen[0] != 2 || h5dimlen[1] != NUM_VALS ||
	     h5dimlenmax[0] != H5S_UNLIMITED || h5dimlenmax[1] != H5S_UNLIMITED) ERR;

	 /* All done. */
	 if (H5Dclose(datasetid) ||
	     H5Sclose(mem_spaceid) ||
	     H5Sclose(file_spaceid)) ERR;
      }

      /* Close up the shop. */
      if (H5Sclose(spaceid)) ERR;
      if (H5Gclose(grpid) < 0 ||
      H5Fclose(fileid) < 0) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** Checking dimension scales with attached dimension scales...");
   
   {
#define LAT_LEN 3
#define LON_LEN 2
#define TIME_LEN 5
#define LEN_LEN 10
#define DIMS_3 3
#define NUM_DIMSCALES1 4
#define LAT_NAME "lat"
#define LON_NAME "lon"
#define PRES_NAME1 "z_pres"
#define TIME_NAME "time"
#define LEN_NAME "u_len"
      
      hid_t fileid, lat_spaceid, lon_spaceid, time_spaceid, pres_spaceid, len_spaceid;
      hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid, time_dimscaleid, len_dimscaleid;
      hid_t fapl_id, fcpl_id;
      hsize_t dims[DIMS_3];
      hid_t spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[NC_MAX_NAME + 1];
      htri_t is_scale;
      int num_scales;
      hsize_t maxdims[DIMS_3];
      H5G_stat_t statbuf;
      HDF5_OBJID_T dimscale_obj[NUM_DIMSCALES1], vars_dimscale_obj[NUM_DIMSCALES1];
      int dimscale_cnt = 0;
      int d, ndims;

      /* Create file access and create property lists. */
      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
      if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
      
      /* Set latest_format in access propertly list. This ensures that
       * the latest, greatest, HDF5 versions are used in the file. */
      if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;

      /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
       * turns on HDF5 creation ordering in the file. */
      if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
      if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;

      /* Create file. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;

      /* Create the spaces that will be used for the dimscales. */
      dims[0] = LAT_LEN;
      if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = LON_LEN;
      if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = TIME_LEN;
      if ((time_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = LEN_LEN;
      if ((len_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;

      /* Create the space for the dataset. */
      dims[0] = LAT_LEN;
      dims[1] = LON_LEN;
      dims[2] = TIME_LEN;
      if ((pres_spaceid = H5Screate_simple(DIMS_3, dims, dims)) < 0) ERR;

      /* Create our dimension scales. */
      if ((lat_dimscaleid = H5Dcreate1(fileid, LAT_NAME, H5T_NATIVE_INT,
				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
      if ((lon_dimscaleid = H5Dcreate1(fileid, LON_NAME, H5T_NATIVE_INT,
				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
      if ((time_dimscaleid = H5Dcreate1(fileid, TIME_NAME, H5T_NATIVE_INT,
				      time_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(time_dimscaleid, NULL) < 0) ERR;
      if ((len_dimscaleid = H5Dcreate1(fileid, LEN_NAME, H5T_NATIVE_INT,
				      len_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(len_dimscaleid, NULL) < 0) ERR;

      /* Create a variable which uses these three dimscales. */
      if ((pres_datasetid = H5Dcreate1(fileid, PRES_NAME1, H5T_NATIVE_FLOAT,
				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, time_dimscaleid, 2) < 0) ERR;

      /* Attach a dimscale to a dimscale. Unfortunately, HDF5 does not
       * allow this. Woe is me. */
      /*if (H5DSattach_scale(time_dimscaleid, len_dimscaleid, 0) < 0) ERR;*/

      /* Fold up our tents. */
      if (H5Dclose(lat_dimscaleid) < 0 ||
	  H5Dclose(lon_dimscaleid) < 0 ||
	  H5Dclose(time_dimscaleid) < 0 ||
	  H5Dclose(len_dimscaleid) < 0 ||
	  H5Dclose(pres_datasetid) < 0 ||
	  H5Sclose(lat_spaceid) < 0 ||
	  H5Sclose(lon_spaceid) < 0 ||
	  H5Sclose(time_spaceid) < 0 ||
	  H5Sclose(pres_spaceid) < 0 ||
	  H5Sclose(len_spaceid) < 0 ||
	  H5Pclose(fapl_id) < 0 ||
	  H5Pclose(fcpl_id) < 0 ||
	  H5Fclose(fileid) < 0) ERR;

      /* Open the file. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      
      /* Loop through objects in the root group. */
      if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(fileid, i, obj_name, NC_MAX_NAME) < 0) ERR;

 	 /* printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n",  */
/*  		obj_class, obj_name);  */

	 /* Deal with object based on its obj_class. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;

	       /* Get space info. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale)
	       {
		  /* fileno and objno uniquely identify an object and a
		   * HDF5 file. */
		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
		  /* printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */
/* 			 dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt, */
/* 			 dimscale_obj[dimscale_cnt].objno); */
		  dimscale_cnt++;
	       }
	       else
	       {
		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0 and 1. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;
		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  for (d = 0; d < ndims; d++)
		  {
		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
		     &(vars_dimscale_obj[d])) < 0) ERR;

		     /* Verify that the object ids passed from the
		      * alien_visitor2 function match the ones we found
		      * for the lat and lon datasets. */
		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
		  }
	       }
	       if (H5Dclose(datasetid) < 0) ERR;
	       if (H5Sclose(spaceid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** Checking cration ordering of datasets which are also dimension scales...");
   
   {
#define LAT_LEN 3
#define LON_LEN 2
#define TIME_LEN 5
#define LEN_LEN 10
#define DIMS_3 3
#define NUM_DIMSCALES2 4
#define LAT_NAME "lat"
#define LON_NAME "lon"
#define PRES_NAME1 "z_pres"
#define TIME_NAME "time"
#define LEN_NAME "u_len"
      
      hid_t fileid, lat_spaceid, lon_spaceid, time_spaceid, pres_spaceid, len_spaceid;
      hid_t pres_datasetid, lat_dimscaleid, lon_dimscaleid, time_dimscaleid, len_dimscaleid;
      hid_t fapl_id, fcpl_id;
      hsize_t dims[DIMS_3];
      hid_t spaceid = 0, datasetid = 0;
      hsize_t num_obj, i;
      int obj_class;
      char obj_name[NC_MAX_NAME + 1];
      htri_t is_scale;
      int num_scales;
      hsize_t maxdims[DIMS_3];
      H5G_stat_t statbuf;
      HDF5_OBJID_T dimscale_obj[NUM_DIMSCALES2], vars_dimscale_obj[NUM_DIMSCALES2];
      int dimscale_cnt = 0;
      int d, ndims;

      /* Create file access and create property lists. */
      if ((fapl_id = H5Pcreate(H5P_FILE_ACCESS)) < 0) ERR;
      if ((fcpl_id = H5Pcreate(H5P_FILE_CREATE)) < 0) ERR;
      
      /* Set latest_format in access propertly list. This ensures that
       * the latest, greatest, HDF5 versions are used in the file. */
      if (H5Pset_libver_bounds(fapl_id, H5F_LIBVER_LATEST, H5F_LIBVER_LATEST) < 0) ERR;

      /* Set H5P_CRT_ORDER_TRACKED in the creation property list. This
       * turns on HDF5 creation ordering in the file. */
      if (H5Pset_link_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;
      if (H5Pset_attr_creation_order(fcpl_id, (H5P_CRT_ORDER_TRACKED |
					       H5P_CRT_ORDER_INDEXED)) < 0) ERR;

      /* Create file. */
      if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, fcpl_id, fapl_id)) < 0) ERR;

      /* Create the spaces that will be used for the dimscales. */
      dims[0] = LAT_LEN;
      if ((lat_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = LON_LEN;
      if ((lon_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = TIME_LEN;
      if ((time_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
      dims[0] = LEN_LEN;
      if ((len_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;

      /* Create the space for the dataset. */
      dims[0] = LAT_LEN;
      dims[1] = LON_LEN;
      dims[2] = TIME_LEN;
      if ((pres_spaceid = H5Screate_simple(DIMS_3, dims, dims)) < 0) ERR;

      /* Create our dimension scales. */
      if ((lat_dimscaleid = H5Dcreate1(fileid, LAT_NAME, H5T_NATIVE_INT,
				      lat_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lat_dimscaleid, NULL) < 0) ERR;
      if ((lon_dimscaleid = H5Dcreate1(fileid, LON_NAME, H5T_NATIVE_INT,
				      lon_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(lon_dimscaleid, NULL) < 0) ERR;
      if ((time_dimscaleid = H5Dcreate1(fileid, TIME_NAME, H5T_NATIVE_INT,
				      time_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(time_dimscaleid, NULL) < 0) ERR;
      if ((len_dimscaleid = H5Dcreate1(fileid, LEN_NAME, H5T_NATIVE_INT,
				      len_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSset_scale(len_dimscaleid, NULL) < 0) ERR;

      /* Create a variable which uses these three dimscales. */
      if ((pres_datasetid = H5Dcreate1(fileid, PRES_NAME1, H5T_NATIVE_FLOAT,
				      pres_spaceid, H5P_DEFAULT)) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lat_dimscaleid, 0) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, lon_dimscaleid, 1) < 0) ERR;
      if (H5DSattach_scale(pres_datasetid, time_dimscaleid, 2) < 0) ERR;

      /* Attach a dimscale to a dimscale. Unfortunately, HDF5 does not
       * allow this. Woe is me. */
      /*if (H5DSattach_scale(time_dimscaleid, len_dimscaleid, 0) < 0) ERR;*/

      /* Fold up our tents. */
      if (H5Dclose(lat_dimscaleid) < 0 ||
	  H5Dclose(lon_dimscaleid) < 0 ||
	  H5Dclose(time_dimscaleid) < 0 ||
	  H5Dclose(len_dimscaleid) < 0 ||
	  H5Dclose(pres_datasetid) < 0 ||
	  H5Sclose(lat_spaceid) < 0 ||
	  H5Sclose(lon_spaceid) < 0 ||
	  H5Sclose(time_spaceid) < 0 ||
	  H5Sclose(pres_spaceid) < 0 ||
	  H5Sclose(len_spaceid) < 0 ||
	  H5Pclose(fapl_id) < 0 ||
	  H5Pclose(fcpl_id) < 0 ||
	  H5Fclose(fileid) < 0) ERR;

      /* Open the file. */
      if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
      
      /* Loop through objects in the root group. */
      if (H5Gget_num_objs(fileid, &num_obj) < 0) ERR;
      for (i=0; i<num_obj; i++)
      {
	 /* Get the type (i.e. group, dataset, etc.), and the name of
	  * the object. */
	 if ((obj_class = H5Gget_objtype_by_idx(fileid, i)) < 0) ERR;
	 if (H5Gget_objname_by_idx(fileid, i, obj_name, NC_MAX_NAME) < 0) ERR;

 	 /* printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n",  */
/*  		obj_class, obj_name);  */

	 /* Deal with object based on its obj_class. */
	 switch(obj_class)
	 {
	    case H5G_GROUP:
	       break;
	    case H5G_DATASET:
	       /* Open the dataset. */
	       if ((datasetid = H5Dopen1(fileid, obj_name)) < 0) ERR;

	       /* Get space info. */
	       if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
	       if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
	       if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;

	       /* Is this a dimscale? */
	       if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
	       if (is_scale)
	       {
		  /* fileno and objno uniquely identify an object and a
		   * HDF5 file. */
		  if (H5Gget_objinfo(datasetid, ".", 1, &statbuf) < 0) ERR;
		  dimscale_obj[dimscale_cnt].fileno[0] = statbuf.fileno[0];
		  dimscale_obj[dimscale_cnt].objno[0] = statbuf.objno[0];
		  dimscale_obj[dimscale_cnt].fileno[1] = statbuf.fileno[1];
		  dimscale_obj[dimscale_cnt].objno[1] = statbuf.objno[1];
		  /* printf("dimscale_obj[%d].fileno = %d dimscale_obj[%d].objno = %d\n", */
/* 			 dimscale_cnt, dimscale_obj[dimscale_cnt].fileno, dimscale_cnt, */
/* 			 dimscale_obj[dimscale_cnt].objno); */
		  dimscale_cnt++;
	       }
	       else
	       {
		  /* Here's how to get the number of scales attached
		   * to the dataset's dimension 0 and 1. */
		  if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
		  if (num_scales != 1) ERR;
		  if ((num_scales = H5DSget_num_scales(datasetid, 1)) < 0) ERR;
		  if (num_scales != 1) ERR;

		  /* Go through all dimscales for this var and learn about them. */
		  for (d = 0; d < ndims; d++)
		  {
		     if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor2,
		     &(vars_dimscale_obj[d])) < 0) ERR;

		     /* Verify that the object ids passed from the
		      * alien_visitor2 function match the ones we found
		      * for the lat and lon datasets. */
		     if (vars_dimscale_obj[d].fileno[0] != dimscale_obj[d].fileno[0] ||
		     vars_dimscale_obj[d].objno[0] != dimscale_obj[d].objno[0]) ERR;
		     if (vars_dimscale_obj[d].fileno[1] != dimscale_obj[d].fileno[1] ||
		     vars_dimscale_obj[d].objno[1] != dimscale_obj[d].objno[1]) ERR;
		  }
	       }
	       if (H5Dclose(datasetid) < 0) ERR;
	       if (H5Sclose(spaceid) < 0) ERR;
	       break;
	    case H5G_TYPE:
	       break;
	    case H5G_LINK:
	       break;
	    default:
	       printf("Unknown object class %d!", obj_class);
	 }
      }

      /* Close up the shop. */
      if (H5Fclose(fileid) < 0) ERR;
   }

   SUMMARIZE_ERR;
   FINAL_RESULTS;
}