From 4322bfe90ab7de7245ff770155867fa5da78147c Mon Sep 17 00:00:00 2001
From: Albert Cheng <acheng@hdfgroup.org>
Date: Wed, 19 Aug 1998 16:46:55 -0500
Subject: [svn-r605] Added in h5dump tools created by Ruey-Hsia. Renamed what
 was called h5dump.c to h5tools.c. Changed Makefile.in to reflect all the
 changes. (Make dependence is to be processed later.)

Tested in Solaris 2.5
---
 tools/Makefile.in  |   9 +-
 tools/h5dump.c     | 660 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/h5dump.h     | 160 +++++++++++++
 tools/h5dumputil.c | 523 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 1349 insertions(+), 3 deletions(-)
 create mode 100644 tools/h5dump.c
 create mode 100644 tools/h5dump.h
 create mode 100644 tools/h5dumputil.c

diff --git a/tools/Makefile.in b/tools/Makefile.in
index 2ab717a..e2c14c9 100644
--- a/tools/Makefile.in
+++ b/tools/Makefile.in
@@ -10,16 +10,16 @@
 CPPFLAGS=-I../src -I. @CPPFLAGS@
 
 # These are our main targets:
-PROGS=h5debug h5import h5ls h5repart
+PROGS=h5debug h5import h5ls h5repart h5dump
 LIB=libh5tools.a
 LIBS=../src/libhdf5.a libh5tools.a @LIBS@
 
 # Source and object files for the library.
-LIB_SRC=h5dump.c
+LIB_SRC=h5tools.c
 LIB_OBJ=$(LIB_SRC:.c=.o)
 
 # Source and object files for programs...
-PROG_SRC=h5debug.c h5import.c h5ls.c h5repart.c
+PROG_SRC=h5debug.c h5import.c h5ls.c h5repart.c h5dump.c h5dumputil.c
 PROG_OBJ=$(PROG_SRC:.c=.o)
 PRIVATE_HDR=h5tools.h
 
@@ -36,4 +36,7 @@ h5ls: h5ls.o $(LIB) ../src/libhdf5.a
 h5repart: h5repart.o $(LIB) ../src/libhdf5.a
 	$(CC) $(CFLAGS) -o $@ h5repart.o $(LIBS)
 
+h5dump: h5dump.o h5dumputil.o $(LIB) ../src/libhdf5.a
+	$(CC) $(CFLAGS) -o $@ h5dump.o h5dumputil.o $(LIBS)
+
 @CONCLUDE@
diff --git a/tools/h5dump.c b/tools/h5dump.c
new file mode 100644
index 0000000..a8a0a81
--- /dev/null
+++ b/tools/h5dump.c
@@ -0,0 +1,660 @@
+#include <h5dump.h>
+
+static int indent = 0;
+
+/*-------------------------------------------------------------------------
+ * Function:    usage
+ *
+ * Purpose:     Print the usage message about dumper
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+usage()
+{
+
+printf("Usage: dumper <filename>\n");
+
+/*
+    printf(" Usage: h5dumper [OPTIONS] <file>\n");
+    printf(" OPTIONS\n");
+    printf("  -H         Print a usage message \n");
+    printf("  -nobb      No boot block\n");
+    printf("  -nodata    No data\n");
+    printf("  -g <name>  Dump everything in the group with name <name>\n");
+    printf("  -d <name>  Dump everything in the dataset with name <name>\n");
+    printf("  -l <name>  Dump the target of the link with name <link>\n");
+*/
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    indentation
+ *
+ * Purpose:     Print spaces for indentation
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void indentation(int x) {
+
+  while (x>0) {
+         printf(" "); 
+         x--;
+  }
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    datatype_name
+ *
+ * Purpose:     Returns the name of data type. 
+ *
+ * Return:      Returns a pointer to a string. 
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static char*
+datatype_name(hid_t type) {
+
+    switch (H5Tget_class(type)) {
+
+    case H5T_INTEGER:
+
+        if (H5Tequal(type, H5T_NATIVE_CHAR)) 
+            return "H5T_NATIVE_CHAR";
+        else if (H5Tequal(type, H5T_NATIVE_UCHAR))
+            return "H5T_NATIVE_UCHAR";
+        else if (H5Tequal(type, H5T_NATIVE_SHORT))
+            return "H5T_NATIVE_SHORT";
+        else if (H5Tequal(type, H5T_NATIVE_USHORT))
+            return "H5T_NATIVE_USHORT";
+        else if (H5Tequal(type, H5T_NATIVE_INT))
+            return "H5T_NATIVE_INT";
+        else if (H5Tequal(type, H5T_NATIVE_UINT))
+            return "H5T_NATIVE_UINT";
+        else if (H5Tequal(type, H5T_NATIVE_LONG))
+            return "H5T_NATIVE_LONG";
+        else if (H5Tequal(type, H5T_NATIVE_ULONG))
+            return "H5T_NATIVE_ULONG";
+        else if (H5Tequal(type, H5T_NATIVE_LLONG))
+            return "H5T_NATIVE_LLONG";
+        else if (H5Tequal(type, H5T_NATIVE_ULLONG))
+            return "H5T_NATIVE_ULLONG";
+        else if (H5Tequal(type, H5T_STD_I8BE))
+            return "H5T_STD_I8BE";
+        else if (H5Tequal(type, H5T_STD_I8LE))
+            return "H5T_STD_I8LE";
+        else if (H5Tequal(type, H5T_STD_I16BE))
+            return "H5T_STD_I16BE";
+        else if (H5Tequal(type, H5T_STD_I16LE))
+            return "H5T_STD_I16LE";
+        else if (H5Tequal(type, H5T_STD_I32BE))
+            return "H5T_STD_I32BE";
+        else if (H5Tequal(type, H5T_STD_I32LE))
+            return "H5T_STD_I32LE";
+        else if (H5Tequal(type, H5T_STD_I64BE))
+            return "H5T_STD_I64BE";
+        else if (H5Tequal(type, H5T_STD_I64LE))
+            return "H5T_STD_I64LE";
+        else if (H5Tequal(type, H5T_STD_U8BE))
+            return "H5T_STD_U8BE";
+        else if (H5Tequal(type, H5T_STD_U8LE))
+            return "H5T_STD_U8LE";
+        else if (H5Tequal(type, H5T_STD_U16BE))
+            return "H5T_STD_U16BE";
+        else if (H5Tequal(type, H5T_STD_U16LE))
+            return "H5T_STD_U16LE";
+        else if (H5Tequal(type, H5T_STD_U32BE))
+            return "H5T_STD_U32BE";
+        else if (H5Tequal(type, H5T_STD_U32LE))
+            return "H5T_STD_U32LE";
+        else if (H5Tequal(type, H5T_STD_U64BE))
+            return "H5T_STD_U64BE";
+        else if (H5Tequal(type, H5T_STD_U64LE))
+            return "H5T_STD_U64LE";
+        else return "unknown integer";
+
+    case H5T_FLOAT: 
+
+        if (H5Tequal(type, H5T_NATIVE_FLOAT))
+            return "H5T_NATIVE_FLOAT";
+        else if (H5Tequal(type, H5T_NATIVE_DOUBLE))
+            return "H5T_NATIVE_DOUBLE";
+        else if (H5Tequal(type, H5T_NATIVE_LDOUBLE))
+            return "H5T_NATIVE_LDOUBLE";
+        else if (H5Tequal(type, H5T_IEEE_F32BE))
+            return "H5T_IEEE_F32BE";
+        else if (H5Tequal(type, H5T_IEEE_F32LE))
+            return "H5T_IEEE_F32LE";
+        else if (H5Tequal(type, H5T_IEEE_F64BE))
+            return "H5T_IEEE_F64BE";
+        else if (H5Tequal(type, H5T_IEEE_F64LE))
+            return "H5T_IEEE_F64LE";
+        else return "unknown float";
+
+    case H5T_TIME: return "time: not yet implemented";
+
+    case H5T_STRING: 
+
+        if (H5Tequal(type,H5T_C_S1))
+            return "H5T_C_S1";
+        else if (H5Tequal(type,H5T_FORTRAN_S1))
+            return "H5T_FORTRAN_S1";
+        else return "unknown string";
+
+    case H5T_BITFIELD: 
+
+        if (H5Tequal(type, H5T_STD_B8BE))
+            return "H5T_STD_B8BE";
+        else if (H5Tequal(type, H5T_STD_B8LE))
+            return "H5T_STD_B8LE";
+        else if (H5Tequal(type, H5T_STD_B16BE))
+            return "H5T_STD_B16BE";
+        else if (H5Tequal(type, H5T_STD_B16LE))
+            return "H5T_STD_B16LE";
+        else if (H5Tequal(type, H5T_STD_B32BE))
+            return "H5T_STD_B32BE";
+        else if (H5Tequal(type, H5T_STD_B32LE))
+            return "H5T_STD_B32LE";
+        else if (H5Tequal(type, H5T_STD_B64BE))
+            return "H5T_STD_B64BE";
+        else if (H5Tequal(type, H5T_STD_B64LE))
+            return "H5T_STD_B64LE";
+        else return "unknown bitfield";
+
+    case H5T_OPAQUE: return "opaque: not yet implemented";
+
+    case H5T_COMPOUND: 
+
+         return "compound: not yet implemented";
+
+    default:
+            return "unknown data type";
+    }
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_bb
+ *
+ * Purpose:     Dump the boot block
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_bb() {
+
+    printf ("%s %s %s\n", BOOT_BLOCK, BEGIN, END);
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_datatype
+ *
+ * Purpose:     Dump the data type. Data type can be HDF5 predefined
+ *              atomic data type, named data type or compound data type. 
+ *
+ * Return:      void 
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_datatype (hid_t type) {
+char *pt;
+char *fname ;
+hid_t nmembers, mtype;
+int i, ndims, perm[512]; 
+size_t dims[512];
+
+    indent += col;
+    indentation (indent);
+    pt = datatype_name(type);
+    printf ("%s %s \"%s\" %s\n", DATATYPE, BEGIN, pt, END);
+    indent -= col;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_dataspace
+ *
+ * Purpose:     Dump the data space. Data space can be named data space,
+ *              array, or others.
+ *
+ * Return:      void    
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_dataspace (hid_t dataset_id, hid_t space) {
+hsize_t size[64];
+hsize_t maxsize[64];  /* check max dims size */
+int ndims = H5Sextent_dims(space, size, maxsize);
+int i;
+
+    indent += col;
+
+    indentation (indent);
+
+    printf("%s ", DATASPACE);
+
+    if (H5Sis_simple(space)) {
+
+        HDfprintf (stdout, "%s %s ( %Hu",BEGIN, ARRAY, size[0]);
+        for (i = 1; i < ndims; i++) 
+             HDfprintf (stdout, ", %Hu", size[i]);
+        printf(" ) ");
+           
+        if (maxsize[0]==H5S_UNLIMITED)
+            HDfprintf (stdout, "( %s", "H5S_UNLIMITED");
+        else
+            HDfprintf (stdout, "( %Hu", maxsize[0]);
+
+        for (i = 1; i < ndims; i++) 
+             if (maxsize[i]==H5S_UNLIMITED)
+                 HDfprintf (stdout, ", %s", "H5S_UNLIMITED");
+             else
+                 HDfprintf (stdout, ", %Hu", maxsize[i]);
+
+        printf(" ) %s\n", END);
+
+    } else
+
+        printf("%s not yet implemented %s\n", BEGIN, END);
+
+    indent -= col;
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_attr
+ *
+ * Purpose:     dump the attribute
+ *
+ * Return:      Success:        SUCCEED
+ *
+ *              Failure:        FAIL
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static herr_t
+dump_attr (hid_t attr, const char *attr_name, void __unused__ *op_data)
+{
+hid_t  attr_id, type, space;
+
+    indentation(indent);
+    begin_obj (ATTRIBUTE, attr_name); 
+
+    if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) {
+
+        type = H5Aget_type(attr_id);
+        space = H5Aget_space(attr_id);
+        dump_datatype(type);
+        dump_dataspace(attr_id, space);
+        dump_data(attr_id, ATTRIBUTE_DATA);
+        H5Tclose(type);
+        H5Sclose(space);
+	H5Aclose (attr_id);
+
+    } else {
+        indent += col;
+        indentation (indent);
+        printf("Unable to open attribute.\n", attr_name);
+        indent -= col;
+        return FAIL;
+    }
+
+    indentation (indent);
+    end_obj();
+
+    return SUCCEED;
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump all
+ *
+ * Purpose:     Dump everything in the specified object
+ *
+ * Return:      Success:        SUCCEED
+ *
+ *              Failure:        FAIL
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static herr_t
+dump_all (hid_t group, const char *name, void __unused__ *op_data)
+{
+hid_t obj;
+hid_t (*func)(void*);
+void *edata;
+char buf[512]; /* Is 512 large enough? */
+
+    /* Disable error reporting */
+    H5Eget_auto (&func, &edata);
+    H5Eset_auto (NULL, NULL);
+
+
+    if (H5Gget_linkval (group, name, sizeof(buf), buf)>=0) {  
+
+        indentation (indent);
+        begin_obj(SOFTLINK, name);
+        indent += col;
+        indentation (indent);
+        printf ("linktarget \"%s\"\n", buf);
+        indent -= col;
+        indentation (indent);
+        end_obj();
+
+    } else if ((obj=H5Dopen (group, name))>=0) {              
+
+        dump_dataset (obj, name);
+        H5Dclose (obj);
+
+    } else if ((obj=H5Gopen (group, name))>=0) {
+
+           dump_group (obj, name);
+           H5Gclose (obj);
+
+    } else if ((obj=H5Topen(group, name))>=0) {
+    
+           dump_named_datatype (obj, name);
+           H5Tclose(obj);
+
+    } else {
+
+        printf ("Unknown Object %s\n", name);
+        H5Eset_auto (func, edata);
+        return FAIL;
+
+    }
+
+    /* Restore error reporting */
+    H5Eset_auto (func, edata);
+
+    return SUCCEED;
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_named_datatype
+ *
+ * Purpose:     Dump named data type
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_named_datatype (hid_t type_id, const char *name) {
+char *fname ;
+hid_t nmembers, mtype;
+int i, ndims, perm[512]; /* dimensionality */
+size_t dims[512];
+
+    indentation (indent);
+    begin_obj(DATATYPE, name);
+
+    indent += col;
+    indentation(indent);
+    printf("named data type: not yet implemented.\n");
+    indent -= col;
+
+    indentation (indent);
+    end_obj();
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_group
+ *
+ * Purpose:     Dump everything within the specified group
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_group (hid_t gid, const char *name) {
+
+    indentation (indent);
+    begin_obj(GROUP, name);
+    indent += col;
+    H5Aiterate (gid, NULL, dump_attr, NULL);
+    H5Giterate (gid, ".", NULL, dump_all, NULL);
+    indent -= col;
+    indentation (indent);
+    end_obj();
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_dataset
+ *
+ * Purpose:     Dump the specified data set
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_dataset (hid_t did, const char *name) {
+hid_t  type, space;
+
+    indentation (indent);
+    begin_obj(DATASET, name);
+    indent += col;
+    H5Aiterate (did, NULL, dump_attr, NULL);
+    indent -= col;
+    type = H5Dget_type (did);
+    space = H5Dget_space (did);
+    dump_datatype(type);
+    dump_dataspace(did, space);
+
+    switch (H5Tget_class(type)) {
+    case H5T_INTEGER:
+         dump_data(did, DATASET_DATA);
+         break;
+    case H5T_FLOAT:
+         dump_data(did, DATASET_DATA);
+         break;
+    case H5T_TIME:
+         indent += col;
+         indentation (indent);
+         indent -= col;
+         printf("DATA{ not yet implemented.}\n");
+         break;
+    case H5T_STRING:
+         indent += col;
+         indentation (indent);
+         indent -= col;
+         printf("DATA{ not yet implemented.}\n");
+         break;
+    case H5T_BITFIELD:
+         indent += col;
+         indentation (indent);
+         indent -= col;
+         printf("DATA{ not yet implemented.}\n");
+         break;
+    case H5T_OPAQUE:
+         indent += col;
+         indentation (indent);
+         indent -= col;
+         printf("DATA{ not yet implemented.}\n");
+         break;
+    case H5T_COMPOUND:
+         indent += col;
+         indentation (indent);
+         indent -= col;
+         printf("DATA{ not yet implemented.}\n");
+         break;
+    default: break;
+    }
+
+    H5Tclose(type);
+    H5Sclose(space);
+    indentation (indent);
+    end_obj();
+    
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    dump_data
+ *
+ * Purpose:     Dump attribute or dataset data
+ *
+ * Return:      void
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+static void
+dump_data (hid_t obj_id, int obj_data) {
+
+    hid_t               f_type ;
+    size_t              size ;
+    h5dump_t            info;
+
+    indent += col;
+    indentation (indent);
+    printf("%s %s", DATA, BEGIN);
+
+    if (obj_data == DATASET_DATA)
+        f_type = H5Dget_type(obj_id);
+    else
+        f_type = H5Aget_type(obj_id);
+
+    size = H5Tget_size(f_type);
+
+    /* Set to all default values and then override */
+    memset(&info, 0, sizeof info);
+    info.idx_fmt = "        (%s) ";
+    info.line_ncols = 80;
+
+    /*
+     * If the dataset is a 1-byte integer type then format it as an ASCI
+     * character string instead of integers.
+     */
+    if (1==size && H5T_INTEGER==H5Tget_class(f_type)) {
+        info.elmt_suf1 = "";
+        info.elmt_suf2 = "";
+        info.idx_fmt = "        (%s) \"";
+        info.line_suf = "\"";
+        printf("\"");
+    }
+
+   
+    /*
+     * Print all the values.
+     */
+
+    if (h5dump1(stdout, &info, obj_id, -1, obj_data)<0) {
+        printf("Unable to print data.");
+    }
+
+    if (1==size && H5T_INTEGER==H5Tget_class(f_type)) 
+        printf("\"");
+
+    printf("%s\n", END);
+    indent -= col;
+
+    H5Tclose(f_type);
+
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:    main
+ *
+ * Purpose:     HDF5 dumper
+ *
+ * Return:      Success:	0
+ *              Failure:	1
+ *
+ * Programmer:  Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-----------------------------------------------------------------------*/
+int
+main(int argc, char *argv[]) {
+hid_t fid, gid;
+hid_t plist=H5P_DEFAULT;
+const char *fname = NULL;
+
+    if (argc > 2 || argc <= 1) {
+        usage();
+        exit(1);
+    }
+
+    /* arguments */
+    fname = argv[1];
+
+    /* open file */
+    if ((fid = H5Fopen (fname, H5F_ACC_RDONLY, plist))<0) exit(1);
+   
+    begin_obj("HDF5", fname);
+
+    gid = H5Gopen (fid, "/");
+
+    dump_group(gid, "/");
+
+    end_obj();
+    
+    if (H5Gclose (gid) < 0) exit(1);
+
+    if (H5Fclose (fid) < 0) exit(1);
+    
+
+    return 0;
+
+}
diff --git a/tools/h5dump.h b/tools/h5dump.h
new file mode 100644
index 0000000..d537390
--- /dev/null
+++ b/tools/h5dump.h
@@ -0,0 +1,160 @@
+#ifndef _DUMPER_H
+#define _DUMPER_H
+
+#include <hdf5.h>
+#include <H5private.h>
+#include <h5tools.h>
+
+#define BOOT_BLOCK	"BOOT_BLOCK"
+#define GROUP		"GROUP"
+#define DATASET		"DATASET"
+#define ATTRIBUTE	"ATTRIBUTE"
+#define	DATATYPE	"DATATYPE"
+#define DATASPACE	"DATASPACE"
+#define DATA		"DATA"
+#define ARRAY		"ARRAY"
+#define OTHER		"OTHER"
+#define STORAGELAYOUT	"STORAGELAYOUT"
+#define COMPRESSION	"COMPRESSION"
+#define EXTERNAL	"EXTERNAL"
+#define HARDLINK	"HARDLINK"
+#define SOFTLINK	"SOFTLINK"
+
+#define BEGIN		"{"
+#define END		"}"
+
+#define ATTRIBUTE_DATA	0
+#define DATASET_DATA	1
+
+
+#define begin_obj(x,y)	printf("%s \"%s\" %s\n", x, y, BEGIN)
+#define end_obj()	printf("%s\n", END);
+
+#define col 3;
+
+static void dump_group (hid_t , const char* );
+static void dump_dataset (hid_t, const  char* );
+static void dump_data (hid_t, int);
+static void dump_named_datatype (hid_t , const char *);
+
+#endif
+
+
+/*
+ * Copyright � 1998 NCSA
+ *                  All rights reserved.
+ *
+ * Programmer:  Robb Matzke <matzke@llnl.gov>
+ *              Thursday, July 23, 1998
+ *
+ * Purpose:	Support functions for the various tools.
+ */
+#ifndef _H5TOOLS_H
+#define _H5TOOLS_H
+
+#include <stdio.h>
+
+/*
+ * Information about how to format output.
+ */
+typedef struct h5dump_t {
+    /*
+     * Fields associated with compound array members.
+     *
+     *	 pre:	    A string to print at the beginning of each array. The
+     *		    default value is the left square bracket `['.
+     *
+     *	 sep:	    A string to print between array values.  The default
+     *		    value is a comma.
+     *
+     *	 suf:	    A strint to print at the end of each array.  The default
+     *		    value is a right square bracket `]'.
+     */
+    const char	*arr_pre;
+    const char	*arr_sep;
+    const char	*arr_suf;
+    
+    /*
+     * Fields associated with compound data types.
+     *
+     *	 name:      How the name of the struct member is printed in the
+     *		    values. By default the name is not printed, but a
+     *		    reasonable setting might be "%s=" which prints the name
+     *		    followed by an equal sign and then the value.
+     *
+     *	 sep:	    A string that separates one member from another.  The
+     *		    default is a comma.
+     *
+     *	 pre:	    A string to print at the beginning of a compound type.
+     *		    The default is a left curly brace.
+     *
+     *	 suf:       A string to print at the end of each compound type.  The
+     *		    default is a right curly brace.
+     */
+    const char	*cmpd_name;
+    const char	*cmpd_sep;
+    const char	*cmpd_pre;
+    const char	*cmpd_suf;
+
+    /*
+     * Fields associated with the individual elements.
+     *
+     *	 fmt:       A printf(3c) format to use to print the value string
+     *		    after it has been rendered.  The default is "%s".
+     *
+     *	 suf1:	    This string is appended to elements which are followed by
+     *		    another element whether the following element is on the
+     *		    same line or the next line.  The default is a comma.
+     *
+     *	 suf2:	    This string is appended (after `suf1') to elements which
+     *		    are followed on the same line by another element.  The
+     *		    default is a single space.
+     */
+    const char	*elmt_fmt;
+    const char	*elmt_suf1;
+    const char	*elmt_suf2;
+    
+    /*
+     * Fields associated with the index values printed at the left edge of
+     * each line of output.
+     *
+     *	 n_fmt:	    Each index value is printed according to this printf(3c)
+     *		    format string which should include a format for a long
+     *		    integer.  The default is "%lu".
+     *
+     *	 sep:	    Each integer in the index list will be separated from the
+     *		    others by this string, which defaults to a comma.
+     *
+     *	 fmt:	    After the index values are formated individually and
+     *		    separated from one another by some string, the entire
+     *		    resulting string will be formated according to this
+     *		    printf(3c) format which should include a format for a
+     *		    character string.  The default is "%s".
+     */
+    const char	*idx_n_fmt;		/*index number format		*/
+    const char	*idx_sep;		/*separator between numbers	*/
+    const char	*idx_fmt;		/*entire index format		*/
+    
+    /*
+     * Fields associated with entire lines.
+     *
+     *   ncols:	    Number of columns per line defaults to 80.
+     *
+     *	 suf:	    This character string will be appended to each line of
+     *		    output.  It should not contain line feeds.  The default
+     *		    is the empty string.
+     *	 
+     *	 sep:	    A character string to be printed after every line feed
+     *		    defaulting to the empty string.  It should end with a
+     *		    line feed.
+     */
+    int		line_ncols;		/*columns of output		*/
+    const char	*line_suf;		/*string to append to each line	*/
+    const char	*line_sep;		/*separates lines		*/
+    
+} h5dump_t;
+
+
+int h5dump1(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type, int);
+
+#endif
diff --git a/tools/h5dumputil.c b/tools/h5dumputil.c
new file mode 100644
index 0000000..d0b3847
--- /dev/null
+++ b/tools/h5dumputil.c
@@ -0,0 +1,523 @@
+/*
+ *  Note: this program is a modification of h5dump.c by Robb Matzke.
+ */
+#include <assert.h>
+#include <ctype.h>
+#include <h5dump.h>
+#include <hdf5.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The output functions need a temporary buffer to hold a piece of the
+ * dataset while it's being printed.  This constant sets the limit on the
+ * size of that temporary buffer in bytes.  For efficiency's sake, choose the
+ * largest value suitable for your machine (for testing use a small value).
+ */
+#define H5DUMP_BUFSIZE	1024
+
+#define OPT(X,S)	((X)?(X):(S))
+#define MIN(X,Y)	((X)<(Y)?(X):(Y))
+#define NELMTS(X)	(sizeof(X)/sizeof(*X))
+#define ALIGN(A,Z)	((((A)+(Z)-1)/(Z))*(Z))
+
+#define DATASET_DATA 	1
+
+/*-------------------------------------------------------------------------
+ * Function:	h5dump_prefix
+ *
+ * Purpose:	Prints the prefix to show up at the begining of the line.
+ *
+ * Return:	void
+ *
+ * Programmer:	Robb Matzke
+ *              Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_prefix(char *s/*out*/, const h5dump_t *info, hsize_t elmtno, int ndims,
+	      hsize_t min_idx[], hsize_t max_idx[])
+{
+    hsize_t	p_prod[8], p_idx[8];
+    hsize_t	n, i;
+    char	temp[1024];
+
+    /*
+     * Calculate the number of elements represented by a unit change in a
+     * certain index position.
+     */
+    for (i=ndims-1, p_prod[ndims-1]=1; i>0; --i) {
+	p_prod[i-1] = (max_idx[i]-min_idx[i]) * p_prod[i];
+    }
+
+    /*
+     * Calculate the index values from the element number.
+     */
+    for (i=0, n=elmtno; i<(hsize_t)ndims; i++) {
+	p_idx[i] = n / p_prod[i] + min_idx[i];
+	n %= p_prod[i];
+    }
+
+    /*
+     * Print the index values.
+     */
+    *temp = '\0';
+    for (i=0; i<(hsize_t)ndims; i++) {
+	if (i) strcat(temp, OPT(info->idx_sep, ","));
+	sprintf(temp+strlen(temp), OPT(info->idx_n_fmt, "%lu"),
+		(unsigned long)p_idx[i]);
+    }
+
+    /*
+     * Add prefix and suffix to the index.
+     */
+    sprintf(s, OPT(info->idx_fmt, "%s: "), temp);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:	h5dump_sprint
+ *
+ * Purpose:	Prints the value pointed to by VP into the string S assuming
+ *		the data type of VP is TYPE.
+ *
+ * Return:	void
+ *
+ * Programmer:	Robb Matzke
+ *              Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_sprint(char *s/*out*/, const h5dump_t *info, hid_t type, void *vp)
+{
+    size_t	i, n, offset;
+    char	temp[1024], *name;
+    hid_t	memb;
+    int		nmembs, j;
+    
+    if (H5Tequal(type, H5T_NATIVE_DOUBLE)) {
+	sprintf(temp, "%g", *((double*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) {
+	sprintf(temp, "%g", *((float*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_CHAR) ||
+	       H5Tequal(type, H5T_NATIVE_UCHAR)) {
+	switch (*((char*)vp)) {
+	case '\\':
+	    strcpy(temp, "\\\\");
+	    break;
+	case '\b':
+	    strcpy(temp, "\\b");
+	    break;
+	case '\f':
+	    strcpy(temp, "\\f");
+	    break;
+	case '\n':
+	    strcpy(temp, "\\n");
+	    break;
+	case '\r':
+	    strcpy(temp, "\\r");
+	    break;
+	case '\t':
+	    strcpy(temp, "\\t");
+	    break;
+	default:
+	    if (isprint(*((char*)vp))) sprintf(temp, "%c", *((char*)vp));
+	    else sprintf(temp, "\\%03o", *((unsigned char*)vp));
+	    break;
+	}
+    } else if (H5Tequal(type, H5T_NATIVE_SHORT)) {
+	sprintf(temp, "%d", *((short*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_USHORT)) {
+	sprintf(temp, "%u", *((unsigned short*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_INT)) {
+	sprintf(temp, "%d", *((int*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_UINT)) {
+	sprintf(temp, "%u", *((unsigned*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_LONG)) {
+	sprintf(temp, "%ld", *((long*)vp));
+    } else if (H5Tequal(type, H5T_NATIVE_ULONG)) {
+	sprintf(temp, "%lu", *((unsigned long*)vp));
+    } else if (H5T_COMPOUND==H5Tget_class(type)) {
+	nmembs = H5Tget_nmembers(type);
+	strcpy(temp, OPT(info->cmpd_pre, "{"));
+	for (j=0; j<nmembs; j++) {
+	    if (j) strcat(temp, OPT(info->cmpd_sep, ","));
+
+	    /* The name */
+	    name = H5Tget_member_name(type, j);
+	    sprintf(temp+strlen(temp), OPT(info->cmpd_name, ""), name);
+	    free(name);
+
+	    /* The value */
+	    offset = H5Tget_member_offset(type, j);
+	    memb = H5Tget_member_type(type, j);
+	    h5dump_sprint(temp+strlen(temp), info, memb, (char*)vp+offset);
+	    H5Tclose(memb);
+	}
+	strcat(temp, OPT(info->cmpd_suf, "}"));
+    } else {
+	strcpy(temp, "0x");
+	n = H5Tget_size(type);
+	for (i=0; i<n; i++) {
+	    sprintf(temp+strlen(temp), "%02x", ((unsigned char*)vp)[i]);
+	}
+    }
+
+    sprintf(s, OPT(info->elmt_fmt, "%s"), temp);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:	h5dump_simple
+ *
+ * Purpose:	Print some values from a dataset with a simple data space.
+ *		This is a special case of h5dump().
+ *
+ * Return:	Success:	0
+ *
+ *		Failure:	-1
+ *
+ * Programmer:	Robb Matzke
+ *              Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+h5dump_simple(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_type, int obj_data)
+{
+    hid_t		f_space;		/*file data space	*/
+    int			ndims;			/*dimensionality	*/
+    hsize_t		elmtno, i;		/*counters		*/
+    int			carry;			/*counter carry value	*/
+    hssize_t		zero[8];		/*vector of zeros	*/
+    int			need_prefix=1;		/*indices need printing	*/
+
+    /* Print info */
+    hsize_t		p_min_idx[8];		/*min selected index	*/
+    hsize_t		p_max_idx[8];		/*max selected index	*/
+    size_t		p_type_nbytes;		/*size of memory type	*/
+    hsize_t		p_nelmts;		/*total selected elmts	*/
+    char		p_buf[256];		/*output string		*/
+    size_t		p_column=0;		/*output column		*/
+    size_t		p_ncolumns=80;		/*default num columns	*/
+    char 		p_prefix[1024];		/*line prefix string	*/
+
+    /* Stripmine info */
+    hsize_t		sm_size[8];		/*stripmine size	*/
+    hsize_t		sm_nbytes;		/*bytes per stripmine	*/
+    hsize_t		sm_nelmts;		/*elements per stripmine*/
+    unsigned char	*sm_buf;		/*buffer for raw data	*/
+    hid_t		sm_space;		/*stripmine data space	*/
+
+    /* Hyperslab info */
+    hssize_t		hs_offset[8];		/*starting offset	*/
+    hsize_t		hs_size[8];		/*size this pass	*/
+    hsize_t		hs_nelmts;		/*elements in request	*/
+
+    /*
+     * Check that everything looks okay.  The dimensionality must not be too
+     * great and the dimensionality of the items selected for printing must
+     * match the dimensionality of the dataset.
+     */
+    if (obj_data == DATASET_DATA)
+         f_space = H5Dget_space(dset);
+    else
+         f_space = H5Aget_space(dset);
+   
+    ndims = H5Sextent_ndims(f_space);
+    if ((size_t)ndims>NELMTS(sm_size)) return -1;
+
+    /* Assume entire data space to be printed */
+    for (i=0; i<(hsize_t)ndims; i++) p_min_idx[i] = 0;
+    H5Sextent_dims(f_space, p_max_idx, NULL); 
+    for (i=0, p_nelmts=1; i<(hsize_t)ndims; i++) {
+	p_nelmts *= p_max_idx[i]-p_min_idx[i];
+    }
+
+    /*
+     * Determine the strip mine size and allocate a buffer.  The strip mine is
+     * a hyperslab whose size is manageable.
+     */
+    p_type_nbytes = H5Tget_size(p_type);
+    for (i=ndims, sm_nbytes=p_type_nbytes; i>0; --i) {
+	sm_size[i-1] = MIN (p_max_idx[i-1]-p_min_idx[i-1],
+			    H5DUMP_BUFSIZE/sm_nbytes);
+	sm_nbytes *= sm_size[i-1];
+	assert(sm_nbytes>0);
+    }
+    sm_buf = malloc(sm_nbytes);
+    sm_nelmts = sm_nbytes/p_type_nbytes;
+    sm_space = H5Screate_simple(1, &sm_nelmts, NULL);
+
+    /* Local things */
+    if (info->line_ncols>0) p_ncolumns = info->line_ncols;
+
+    /* The stripmine loop */
+    memset(hs_offset, 0, sizeof hs_offset);
+    memset(zero, 0, sizeof zero);
+    for (elmtno=0; elmtno<p_nelmts; elmtno+=hs_nelmts) {
+
+	/* Calculate the hyperslab size */
+	for (i=0, hs_nelmts=1; i<(hsize_t)ndims; i++) {
+	    hs_size[i] = MIN(sm_size[i], p_max_idx[i]-hs_offset[i]);
+	    hs_nelmts *= hs_size[i];
+	}
+	
+	/* Read the data */
+	H5Sselect_hyperslab(f_space, H5S_SELECT_SET, hs_offset, NULL,
+			    hs_size, NULL);
+	H5Sselect_hyperslab(sm_space, H5S_SELECT_SET, zero, NULL,
+			    &hs_nelmts, NULL);
+
+
+	if (obj_data == DATASET_DATA)
+            H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf);
+        else
+            H5Aread(dset, p_type, sm_buf);
+
+	/* Print the data */
+	for (i=0; i<hs_nelmts; i++) {
+	    /* Render the element */
+	    h5dump_sprint(p_buf, info, p_type, sm_buf+i*p_type_nbytes);
+	    if (elmtno+i+1<p_nelmts) {
+		strcat(p_buf, OPT(info->elmt_suf1, ","));
+	    }
+
+	    /* Print the prefix */
+/* 
+	    if ((p_column +
+		 strlen(p_buf) +
+		 strlen(OPT(info->elmt_suf2, " ")) +
+		 strlen(OPT(info->line_suf, ""))) > p_ncolumns) {
+		need_prefix = 1;
+	    }
+
+	    if (need_prefix) {
+		h5dump_prefix(p_prefix, info, elmtno+i, ndims,
+			      p_min_idx, p_max_idx);
+		if (p_column) {
+		    fputs(OPT(info->line_suf, ""), stream);
+		    putc('\n', stream);
+		    fputs(OPT(info->line_sep, ""), stream);
+		}
+		fputs(p_prefix, stream);
+		p_column = strlen(p_prefix);
+		need_prefix = 0;
+	    } else {
+		fputs(OPT(info->elmt_suf2, " "), stream);
+		p_column += strlen(OPT(info->elmt_suf2, " "));
+
+	    }
+	    
+ */
+
+	    fputs(p_buf, stream);
+/* 
+	    p_column += strlen(p_buf);
+ */
+	}
+	
+	/* Calculate the next hyperslab offset */
+	for (i=ndims, carry=1; i>0 && carry; --i) {
+	    hs_offset[i-1] += hs_size[i-1];
+	    if (hs_offset[i-1]==(hssize_t)p_max_idx[i-1]) {
+		hs_offset[i-1] = p_min_idx[i-1];
+	    } else {
+		carry = 0;
+	    }
+	}
+    }
+/* 
+
+    if (p_column) {
+	fputs(OPT(info->line_suf, ""), stream);
+	putc('\n', stream);
+	fputs(OPT(info->line_sep, ""), stream);
+    }
+ */
+    H5Sclose(sm_space);
+    H5Sclose(f_space);
+    return 0;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:	h5dump_fixtype
+ *
+ * Purpose:	Given a file data type choose a memory data type which is
+ *		appropriate for printing the data.
+ *
+ * Return:	Success:	Memory data type
+ *
+ *		Failure:	FAIL
+ *
+ * Programmer:	Robb Matzke
+ *              Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hid_t
+h5dump_fixtype(hid_t f_type)
+{
+    hid_t	m_type=-1, f_memb;
+    hid_t	*memb=NULL;
+    char	**name=NULL;
+    int		nmembs, i;
+    size_t	size;
+
+    size = H5Tget_size(f_type);
+    switch (H5Tget_class(f_type)) {
+
+    case H5T_INTEGER:
+	/*
+	 * Use the smallest native integer type of the same sign as the file
+	 * such that the memory type is at least as large as the file type.
+	 * If there is no memory type large enough then use the largest
+	 * memory type available.
+	 */
+	if (size<=sizeof(char)) {
+	    m_type = H5Tcopy(H5T_NATIVE_CHAR);
+	} else if (size<=sizeof(short)) {
+	    m_type = H5Tcopy(H5T_NATIVE_SHORT);
+	} else if (size<=sizeof(int)) {
+	    m_type = H5Tcopy(H5T_NATIVE_INT);
+	} else if (size<=sizeof(long)) {
+	    m_type = H5Tcopy(H5T_NATIVE_LONG);
+	} else {
+	    m_type = H5Tcopy(H5T_NATIVE_LLONG);
+	}
+	H5Tset_sign(m_type, H5Tget_size(f_type));
+	break;
+	
+    case H5T_FLOAT:
+	/*
+	 * Use the smallest native floating point type available such that
+	 * its size is at least as large as the file type.  If there is not
+	 * native type large enough then use the largest native type.
+	 */
+	if (size<=sizeof(float)) {
+	    m_type = H5Tcopy(H5T_NATIVE_FLOAT);
+	} else if (size<=sizeof(double)) {
+	    m_type = H5Tcopy(H5T_NATIVE_DOUBLE);
+	} else {
+	    m_type = H5Tcopy(H5T_NATIVE_LDOUBLE);
+	}
+	break;
+
+    case H5T_COMPOUND:
+	nmembs = H5Tget_nmembers(f_type);
+	memb = calloc(nmembs, sizeof(hid_t));
+	name = calloc(nmembs, sizeof(char*));
+	
+	for (i=0, size=0; i<nmembs; i++) {
+	    f_memb = H5Tget_member_type(f_type, i);
+	    memb[i] = h5dump_fixtype(f_memb);
+	    size = ALIGN(size, H5Tget_size(memb[i])) + H5Tget_size(memb[i]);
+	    H5Tclose(f_memb);
+	    name[i] = H5Tget_member_name(f_type, i);
+	    if (memb[i]<0 || NULL==name[i]) goto done;
+	}
+
+	m_type = H5Tcreate(H5T_COMPOUND, size);
+	for (i=0, size=0; i<nmembs; i++) {
+	    H5Tinsert(m_type, name[i], size, memb[i]);
+	    size = ALIGN(size, H5Tget_size(memb[i])) + H5Tget_size(memb[i]);
+	}
+	break;
+
+    case H5T_TIME:
+    case H5T_STRING:
+    case H5T_BITFIELD:
+    case H5T_OPAQUE:
+	/*
+	 * These type classes are not implemented yet.
+	 */
+	break;
+
+    default:
+	/* What the heck? */
+	break;
+    }
+
+ done:
+    /* Clean up temp buffers */
+    if (memb && name) {
+	for (i=0; i<nmembs; i++) {
+	    if (memb[i]>=0) H5Tclose(memb[i]);
+	    if (name[i]) free(name[i]);
+	}
+	free(memb);
+	free(name);
+    }
+    
+    return m_type;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function:	h5dump
+ *
+ * Purpose:	Print some values from a dataset.  The values to print are
+ *		determined by the P_SPACE argument and the format to use to
+ *		print them is determined by the P_TYPE argument.
+ *
+ * Return:	Success:	0
+ *
+ *		Failure:	-1
+ *
+ * Programmer:	Robb Matzke
+ *              Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+h5dump1(FILE *stream, const h5dump_t *info, hid_t dset, hid_t _p_type, int obj_data)
+{
+    hid_t	f_space;
+    hid_t	p_type = _p_type;
+    hid_t	f_type;
+    int		status;
+
+    /* Check the data space */
+    if (obj_data == DATASET_DATA) 
+        f_space = H5Dget_space(dset);
+    else
+        f_space = H5Aget_space(dset);
+
+    if (H5Sis_simple(f_space)<=0) return -1;
+    H5Sclose(f_space);
+
+    /*
+     * Check the data type.  If the caller didn't supply a data type then
+     * use an appropriate native data type.
+     */
+
+     if (obj_data == DATASET_DATA) 
+         f_type = H5Dget_type(dset);
+     else
+         f_type = H5Aget_type(dset);
+
+    if (p_type<0) {
+	p_type = h5dump_fixtype(f_type);
+	H5Tclose(f_type);
+	if (p_type<0) return -1;
+    }
+
+    /* Print the data */
+    status = h5dump_simple(stream, info, dset, p_type, obj_data);
+    if (p_type!=_p_type) H5Tclose(p_type);
+    return status;
+}
-- 
cgit v0.12