summaryrefslogtreecommitdiffstats
path: root/tools/lib
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib')
-rw-r--r--tools/lib/Dependencies0
-rw-r--r--tools/lib/Makefile.in43
-rw-r--r--tools/lib/h5tools.c2448
-rw-r--r--tools/lib/h5tools.h517
-rw-r--r--tools/lib/h5tools_str.c289
-rw-r--r--tools/lib/h5tools_str.h27
6 files changed, 3324 insertions, 0 deletions
diff --git a/tools/lib/Dependencies b/tools/lib/Dependencies
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/lib/Dependencies
diff --git a/tools/lib/Makefile.in b/tools/lib/Makefile.in
new file mode 100644
index 0000000..5e61afd
--- /dev/null
+++ b/tools/lib/Makefile.in
@@ -0,0 +1,43 @@
+## HDF5 Library Makefile(.in)
+##
+## Copyright (C) 2001 National Center for Supercomputing Applications.
+## All rights reserved.
+##
+##
+top_srcdir=@top_srcdir@
+top_builddir=../..
+srcdir=@srcdir@
+SUBDIRS=
+@COMMENCE@
+
+## Add include directory to the C preprocessor flags, add -lh5tools and
+## -lhdf5 to the list of libraries.
+##
+CPPFLAGS=-I. -I$(srcdir) -I$(top_builddir)/src -I$(top_srcdir)/src \
+ -I$(top_srcdir)/tools/lib @CPPFLAGS@
+
+## Test programs and scripts.
+##
+TEST_PROGS=
+TEST_SCRIPTS=
+
+## These are our main targets: library and tools. We link this library
+## statically because some systems can only link executables to a single
+## shared library and libhdf5 is much bigger than libh5tools.
+##
+LT_LINK_LIB=$(LT) --mode=link $(CC) -static -rpath $(libdir)
+LIB=libh5tools.la
+
+## Source and object files for the library; do not install
+##
+LIB_SRC=h5tools.c h5tools_str.c
+LIB_OBJ=$(LIB_SRC:.c=.lo)
+PUB_LIB=
+
+PRIVATE_HDR=h5tools.h h5tools_str.h
+
+## Programs have to be built before they can be tested!
+##
+check test _test: $(PROGS)
+
+@CONCLUDE@
diff --git a/tools/lib/h5tools.c b/tools/lib/h5tools.c
new file mode 100644
index 0000000..8ac51ef
--- /dev/null
+++ b/tools/lib/h5tools.c
@@ -0,0 +1,2448 @@
+/*
+ * Copyright (c) 1998-2001 National Center for Supercomputing Applications
+ * All rights reserved.
+ *
+ * Programmer: Robb Matzke <matzke@llnl.gov>
+ * Thursday, July 23, 1998
+ *
+ * Purpose: A library for displaying the values of a dataset in a human
+ * readable format.
+ */
+
+/*
+ * Portions of this work are derived from _Obfuscated C and Other Mysteries_,
+ * by Don Libes, copyright (c) 1993 by John Wiley & Sons, Inc.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "h5tools.h"
+#include "h5tools_str.h"
+#include "hdf5.h"
+#include "H5private.h"
+
+/* taken from h5dumputil.c */
+
+/*
+ * If REPEAT_VERBOSE is defined then character strings will be printed so
+ * that repeated character sequences like "AAAAAAAAAA" are displayed as
+ *
+ * 'A' repeates 9 times
+ *
+ * Otherwise the format is more Perl-like
+ *
+ * 'A'*10
+ *
+ */
+#define REPEAT_VERBOSE
+
+/*
+ * 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).
+ */
+#if 1
+#define H5DUMP_BUFSIZE (1024 * 1024)
+#else
+#define H5DUMP_BUFSIZE (1024)
+#endif
+
+#define ALIGN(A,Z) ((((A) + (Z) - 1) / (Z)) * (Z))
+
+#define START_OF_DATA 0x0001
+#define END_OF_DATA 0x0002
+
+/* Special strings embedded in the output */
+#define OPTIONAL_LINE_BREAK "\001"
+
+/* module-scoped variables */
+static int h5tools_init_g; /* if h5tools lib has been initialized */
+
+int indent;
+int compound_data;
+int nCols = 80;
+FILE *rawdatastream; /* should initialize to stdout but gcc moans about it */
+
+/* ``get_option'' variables */
+int opt_err = 1; /*get_option prints errors if this is on */
+int opt_ind = 1; /*token pointer */
+const char *opt_arg; /*flag argument (or value) */
+
+/* Output variables */
+typedef struct h5tools_context_t {
+ size_t cur_column; /*current column for output */
+ size_t cur_elmt; /*current element/output line */
+ int need_prefix; /*is line prefix needed? */
+ int ndims; /*dimensionality */
+ hsize_t p_min_idx[H5S_MAX_RANK]; /*min selected index */
+ hsize_t p_max_idx[H5S_MAX_RANK]; /*max selected index */
+ int prev_multiline; /*was prev datum multiline? */
+ size_t prev_prefix_len;/*length of previous prefix */
+ int continuation; /*continuation of previous data?*/
+ int size_last_dim; /*the size of the last dimension,
+ *needed so we can break after each
+ *row */
+ int indent_level; /*the number of times we need some
+ *extra indentation */
+ int default_indent_level; /*this is used when the indent
+ *level gets changed */
+} h5tools_context_t;
+
+typedef herr_t (*H5G_operator_t)(hid_t, const char*, void*);
+
+extern void free_table(table_t **table);
+extern void dump_table(char *name, table_t* table);
+extern int get_table_idx(table_t *table, unsigned long *);
+extern int get_tableflag(table_t*, int);
+extern int set_tableflag(table_t*, int);
+extern char *get_objectname(table_t*, int);
+
+
+/*-------------------------------------------------------------------------
+ * Function: error_msg
+ *
+ * Purpose: Print a nicely formatted error message to stderr flushing the
+ * stdout stream first.
+ *
+ * Return: Nothing
+ *
+ * Programmer: Bill Wendling
+ * Tuesday, 20. February 2001
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+error_msg(const char *progname, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fflush(stdout);
+ fprintf(stderr, "%s error: ", progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: warn_msg
+ *
+ * Purpose: Print a nicely formatted warning message to stderr flushing
+ * the stdout stream first.
+ *
+ * Return: Nothing
+ *
+ * Programmer: Bill Wendling
+ * Tuesday, 20. February 2001
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+warn_msg(const char *progname, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fflush(stdout);
+ fprintf(stderr, "%s warning: ", progname);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: get_option
+ *
+ * Purpose: Determine the command-line options a user specified. We can
+ * accept both short and long type command-lines.
+ *
+ * Return: Success: The short valued "name" of the command line
+ * parameter or EOF if there are no more
+ * parameters to process.
+ *
+ * Failure: A question mark.
+ *
+ * Programmer: Bill Wendling
+ * Friday, 5. January 2001
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+get_option(int argc, const char **argv, const char *opts, const struct long_options *l_opts)
+{
+ static int sp = 1; /* character index in current token */
+ int opt_opt = '?'; /* option character passed back to user */
+
+ if (sp == 1) {
+ /* check for more flag-like tokens */
+ if (opt_ind >= argc || argv[opt_ind][0] != '-' || argv[opt_ind][1] == '\0') {
+ return EOF;
+ } else if (strcmp(argv[opt_ind], "--") == 0) {
+ opt_ind++;
+ return EOF;
+ }
+ }
+
+ if (sp == 1 && argv[opt_ind][0] == '-' && argv[opt_ind][1] == '-') {
+ /* long command line option */
+ const char *arg = &argv[opt_ind][2];
+ register int i;
+
+ for (i = 0; l_opts && l_opts[i].name; i++) {
+ size_t len = strlen(l_opts[i].name);
+
+ if (strncmp(arg, l_opts[i].name, len) == 0) {
+ /* we've found a matching long command line flag */
+ opt_opt = l_opts[i].shortval;
+
+ if (l_opts[i].has_arg != no_arg) {
+ if (arg[len] == '=') {
+ opt_arg = &arg[len + 1];
+ } else if (opt_ind < (argc - 1) && argv[opt_ind + 1][0] != '-') {
+ opt_arg = argv[++opt_ind];
+ } else if (l_opts[i].has_arg == require_arg) {
+ if (opt_err)
+ fprintf(stderr,
+ "%s: option required for \"--%s\" flag\n",
+ argv[0], arg);
+
+ opt_opt = '?';
+ }
+ } else {
+ if (arg[len] == '=') {
+ if (opt_err)
+ fprintf(stderr,
+ "%s: no option required for \"%s\" flag\n",
+ argv[0], arg);
+
+ opt_opt = '?';
+ }
+
+ opt_arg = NULL;
+ }
+
+ break;
+ }
+ }
+
+ if (l_opts[i].name == NULL) {
+ /* exhausted all of the l_opts we have and still didn't match */
+ if (opt_err)
+ fprintf(stderr, "%s: unknown option \"%s\"\n", argv[0], arg);
+
+ opt_opt = '?';
+ }
+
+ opt_ind++;
+ sp = 1;
+ } else {
+ register char *cp; /* pointer into current token */
+
+ /* short command line option */
+ opt_opt = argv[opt_ind][sp];
+
+ if (opt_opt == ':' || (cp = strchr(opts, opt_opt)) == 0) {
+ if (opt_err)
+ fprintf(stderr, "%s: unknown option \"%c\"\n",
+ argv[0], opt_opt);
+
+ /* if no chars left in this token, move to next token */
+ if (argv[opt_ind][++sp] == '\0') {
+ opt_ind++;
+ sp = 1;
+ }
+
+ return '?';
+ }
+
+ if (*++cp == ':') {
+ /* if a value is expected, get it */
+ if (argv[opt_ind][sp + 1] != '\0') {
+ /* flag value is rest of current token */
+ opt_arg = &argv[opt_ind++][sp + 1];
+ } else if (++opt_ind >= argc) {
+ if (opt_err)
+ fprintf(stderr,
+ "%s: value expected for option \"%c\"\n",
+ argv[0], opt_opt);
+
+ opt_opt = '?';
+ } else {
+ /* flag value is next token */
+ opt_arg = argv[opt_ind++];
+ }
+
+ sp = 1;
+ } else {
+ /* set up to look at next char in token, next time */
+ if (argv[opt_ind][++sp] == '\0') {
+ /* no more in current token, so setup next token */
+ opt_ind++;
+ sp = 1;
+ }
+
+ opt_arg = NULL;
+ }
+ }
+
+ /* return the current flag character found */
+ return opt_opt;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_init
+ *
+ * Purpose: Initialize the H5 Tools library.
+ * This should be called before any other h5tools function is
+ * called. Effect of any h5tools function called before this
+ * has been called is undetermined.
+ *
+ * Return: None
+ *
+ * Programmer: Albert Cheng, 2000-10-31
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+void
+h5tools_init(void)
+{
+ if (!h5tools_init_g) {
+ if (!rawdatastream)
+ rawdatastream = stdout;
+
+ h5tools_init_g++;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_close
+ *
+ * Purpose: Close the H5 Tools library by closing or releasing resources
+ * such as files opened by the library.
+ * This should be called after all other h5tools functions have
+ * been called. Effect of any h5tools function called after this
+ * has been called is undetermined.
+ *
+ * Return: None
+ *
+ * Programmer: Albert Cheng, 2000-10-31
+ *
+ * Modifications:
+ *-------------------------------------------------------------------------
+ */
+void
+h5tools_close(void)
+{
+ if (h5tools_init_g) {
+ if (rawdatastream && rawdatastream != stdout) {
+ if (fclose(rawdatastream))
+ perror("closing rawdatastream");
+ else
+ rawdatastream = NULL;
+ }
+
+ h5tools_init_g = 0;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_escape
+ *
+ * Purpose: Changes all "funny" characters in S into standard C escape
+ * sequences. If ESCAPE_SPACES is non-zero then spaces are
+ * escaped by prepending a backslash.
+ *
+ * Return: Success: S
+ *
+ * Failure: NULL if the buffer would overflow. The
+ * buffer has as many left-to-right escapes as
+ * possible before overflow would have happened.
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5tools_escape(char *s/*in,out*/, size_t size, int escape_spaces)
+{
+ register size_t i;
+ size_t n = strlen(s);
+ const char *escape;
+ char octal[8];
+
+ for (i = 0; i < n; i++) {
+ switch (s[i]) {
+ case '"':
+ escape = "\\\"";
+ break;
+ case '\\':
+ escape = "\\\\";
+ break;
+ case '\b':
+ escape = "\\b";
+ break;
+ case '\f':
+ escape = "\\f";
+ break;
+ case '\n':
+ escape = "\\n";
+ break;
+ case '\r':
+ escape = "\\r";
+ break;
+ case '\t':
+ escape = "\\t";
+ break;
+ case ' ':
+ escape = escape_spaces ? "\\ " : NULL;
+ break;
+ default:
+ if (!isprint((int)*s)) {
+ sprintf(octal, "\\%03o", (unsigned char)s[i]);
+ escape = octal;
+ } else {
+ escape = NULL;
+ }
+
+ break;
+ }
+
+ if (escape) {
+ size_t esc_size = strlen(escape);
+
+ if (n + esc_size + 1 > size)
+ /*would overflow*/
+ return NULL;
+
+ memmove(s + i + esc_size, s + i, (n - i) + 1); /*make room*/
+ memcpy(s + i, escape, esc_size); /*insert*/
+ n += esc_size;
+ i += esc_size - 1;
+ }
+ }
+
+ return s;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_is_zero
+ *
+ * Purpose: Determines if memory is initialized to all zero bytes.
+ *
+ * Return: TRUE if all bytes are zero; FALSE otherwise
+ *
+ * Programmer: Robb Matzke
+ * Monday, June 7, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static hbool_t
+h5tools_is_zero(const void *_mem, size_t size)
+{
+ const unsigned char *mem = (const unsigned char *)_mem;
+
+ while (size-- > 0)
+ if (mem[size])
+ return FALSE;
+
+ return TRUE;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_region
+ *
+ * Purpose: Prints information about a dataspace region by appending
+ * the information to the specified string.
+ *
+ * Return: Success: 0
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, June 7, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+h5dump_region(hid_t region, h5tools_str_t *str/*in,out*/, const h5dump_t *info)
+{
+ hssize_t nblocks, npoints;
+ hsize_t alloc_size;
+ hsize_t *ptdata;
+ int ndims = H5Sget_simple_extent_ndims(region);
+
+ /*
+ * These two functions fail if the region does not have blocks or points,
+ * respectively. They do not currently know how to translate from one to
+ * the other.
+ */
+ H5E_BEGIN_TRY {
+ nblocks = H5Sget_select_hyper_nblocks(region);
+ npoints = H5Sget_select_elem_npoints(region);
+ } H5E_END_TRY;
+
+ h5tools_str_append(str, "{");
+
+ /* Print block information */
+ if (nblocks > 0) {
+ int i;
+
+ alloc_size = nblocks * ndims * 2 * sizeof(ptdata[0]);
+ assert(alloc_size == (hsize_t)((size_t)alloc_size)); /*check for overflow*/
+ ptdata = malloc((size_t)alloc_size);
+ H5_CHECK_OVERFLOW(nblocks, hssize_t, hsize_t);
+ H5Sget_select_hyper_blocklist(region, (hsize_t)0, (hsize_t)nblocks, ptdata);
+
+ for (i = 0; i < nblocks; i++) {
+ int j;
+
+ h5tools_str_append(str, info->dset_blockformat_pre,
+ i ? "," OPTIONAL_LINE_BREAK " " : "",
+ (unsigned long)i);
+
+ /* Start coordinates and opposite corner */
+ for (j = 0; j < ndims; j++)
+ h5tools_str_append(str, "%s%lu", j ? "," : "(",
+ (unsigned long)ptdata[i * 2 * ndims + j]);
+
+ for (j = 0; j < ndims; j++)
+ h5tools_str_append(str, "%s%lu", j ? "," : ")-(",
+ (unsigned long)ptdata[i * 2 * ndims + j + ndims]);
+
+ h5tools_str_append(str, ")");
+ }
+
+ free(ptdata);
+ }
+
+ /* Print point information */
+ if (npoints > 0) {
+ int i;
+
+ alloc_size = npoints * ndims * sizeof(ptdata[0]);
+ assert(alloc_size == (hsize_t)((size_t)alloc_size)); /*check for overflow*/
+ ptdata = malloc((size_t)alloc_size);
+ H5_CHECK_OVERFLOW(npoints,hssize_t,hsize_t);
+ H5Sget_select_elem_pointlist(region, (hsize_t)0, (hsize_t)npoints, ptdata);
+
+ for (i = 0; i < npoints; i++) {
+ int j;
+
+ h5tools_str_append(str, info->dset_ptformat_pre ,
+ i ? "," OPTIONAL_LINE_BREAK " " : "",
+ (unsigned long)i);
+
+ for (j = 0; j < ndims; j++)
+ h5tools_str_append(str, "%s%lu", j ? "," : "(",
+ (unsigned long)(ptdata[i * ndims + j]));
+
+ h5tools_str_append(str, ")");
+ }
+
+ free(ptdata);
+ }
+
+ h5tools_str_append(str, "}");
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_print_char
+ *
+ * Purpose: Shove a character into the STR.
+ *
+ * Return: Nothing
+ *
+ * Programmer: Bill Wendling
+ * Tuesday, 20. February 2001
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5tools_print_char(h5tools_str_t *str, const h5dump_t *info, unsigned char ch)
+{
+ if (info->str_locale == ESCAPE_HTML) {
+ if (ch <= ' ' || ch > '~')
+ h5tools_str_append(str, "%%%02x", ch);
+ else
+ h5tools_str_append(str, "%c", (char)ch);
+ } else {
+ switch (ch) {
+ case '"':
+ h5tools_str_append(str, "\\\"");
+ break;
+ case '\\':
+ h5tools_str_append(str, "\\\\");
+ break;
+ case '\b':
+ h5tools_str_append(str, "\\b");
+ break;
+ case '\f':
+ h5tools_str_append(str, "\\f");
+ break;
+ case '\n':
+ h5tools_str_append(str, "\\n");
+ break;
+ case '\r':
+ h5tools_str_append(str, "\\r");
+ break;
+ case '\t':
+ h5tools_str_append(str, "\\t");
+ break;
+ default:
+ if (isprint(ch))
+ h5tools_str_append(str, "%c", (char)ch);
+ else
+ h5tools_str_append(str, "\\%03o", ch);
+
+ break;
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_sprint
+ *
+ * Purpose: Renders the value pointed to by VP of type TYPE into variable
+ * length string STR.
+ *
+ * Return: A pointer to memory containing the result or NULL on error.
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ * Robb Matzke, 1999-04-26
+ * Made this function safe from overflow problems by allowing it
+ * to reallocate the output string.
+ *
+ * Robb Matzke, 1999-06-04
+ * Added support for object references. The new `container'
+ * argument is the dataset where the reference came from.
+ *
+ * Robb Matzke, 1999-06-07
+ * Added support for printing raw data. If info->raw is non-zero
+ * then data is printed in hexadecimal format.
+ *
+ *-------------------------------------------------------------------------
+ */
+static char *
+h5tools_sprint(h5tools_str_t *str/*in,out*/, const h5dump_t *info,
+ hid_t container, hid_t type, void *vp, h5tools_context_t *ctx)
+{
+ size_t n, offset, size, nelmts, start;
+ char *name, quote = '\0';
+ unsigned char *ucp_vp = (unsigned char *)vp;
+ char *cp_vp = (char *)vp;
+ hid_t memb, obj, region;
+ int nmembs, otype;
+ static char fmt_llong[8], fmt_ullong[8];
+ H5T_str_t pad;
+ H5G_stat_t sb;
+
+ /*
+ * some tempvars to store the value before we append it to the string to
+ * get rid of the memory alignment problem
+ */
+ double tempdouble;
+ float tempfloat;
+ unsigned long_long tempullong;
+ long_long templlong;
+ unsigned long tempulong;
+ long templong;
+ unsigned int tempuint;
+ int tempint;
+ unsigned short tempushort;
+ short tempshort;
+
+ /* Build default formats for long long types */
+ if (!fmt_llong[0]) {
+ sprintf(fmt_llong, "%%%sd", PRINTF_LL_WIDTH);
+ sprintf(fmt_ullong, "%%%su", PRINTF_LL_WIDTH);
+ }
+
+ /* Append value depending on data type */
+ start = h5tools_str_len(str);
+
+ if (info->raw) {
+ size_t i;
+
+ h5tools_str_append(str, "0x");
+ n = H5Tget_size(type);
+
+ for (i = 0; i < n; i++)
+ h5tools_str_append(str, OPT(info->fmt_raw, "%02x"), ucp_vp[i]);
+ } else if (H5Tequal(type, H5T_NATIVE_FLOAT)) {
+ memcpy(&tempfloat, vp, sizeof(float));
+ h5tools_str_append(str, OPT(info->fmt_float, "%g"), tempfloat);
+ } else if (H5Tequal(type, H5T_NATIVE_DOUBLE)) {
+ memcpy(&tempdouble, vp, sizeof(double));
+ h5tools_str_append(str, OPT(info->fmt_double, "%g"), tempdouble);
+ } else if (info->ascii && (H5Tequal(type, H5T_NATIVE_SCHAR) ||
+ H5Tequal(type, H5T_NATIVE_UCHAR))) {
+ h5tools_print_char(str, info, *ucp_vp);
+ } else if (H5T_STRING == H5Tget_class(type)) {
+ unsigned int i;
+
+ quote = '\0';
+ size = H5Tget_size(type);
+ pad = H5Tget_strpad(type);
+
+ for (i = 0; i < size && (cp_vp[i] != '\0' || pad != H5T_STR_NULLTERM); i++) {
+ int j = 1;
+
+ /*
+ * Count how many times the next character repeats. If the
+ * threshold is zero then that means it can repeat any number
+ * of times.
+ */
+ if (info->str_repeat > 0)
+ while (i + j < size && cp_vp[i] == cp_vp[i + j])
+ j++;
+
+ /*
+ * Print the opening quote. If the repeat count is high enough to
+ * warrant printing the number of repeats instead of enumerating
+ * the characters, then make sure the character to be repeated is
+ * in it's own quote.
+ */
+ if (info->str_repeat > 0 && j > info->str_repeat) {
+ if (quote)
+ h5tools_str_append(str, "%c", quote);
+
+ quote = '\'';
+ h5tools_str_append(str, "%s%c", i ? " " : "", quote);
+ } else if (!quote) {
+ quote = '"';
+ h5tools_str_append(str, "%s%c", i ? " " : "", quote);
+ }
+
+ /* Print the character */
+ h5tools_print_char(str, info, ucp_vp[i]);
+
+ /* Print the repeat count */
+ if (info->str_repeat && j > info->str_repeat) {
+#ifdef REPEAT_VERBOSE
+ h5tools_str_append(str, "%c repeats %d times", quote, j - 1);
+#else
+ h5tools_str_append(str, "%c*%d", quote, j - 1);
+#endif
+ quote = '\0';
+ i += j - 1;
+ }
+
+ }
+
+ if (quote)
+ h5tools_str_append(str, "%c", quote);
+
+ if (i == 0)
+ /*empty string*/
+ h5tools_str_append(str, "\"\"");
+ } else if (H5Tequal(type, H5T_NATIVE_INT)) {
+ memcpy(&tempint, vp, sizeof(int));
+ h5tools_str_append(str, OPT(info->fmt_int, "%d"), tempint);
+ } else if (H5Tequal(type, H5T_NATIVE_UINT)) {
+ memcpy(&tempuint, vp, sizeof(unsigned int));
+ h5tools_str_append(str, OPT(info->fmt_uint, "%u"), tempuint);
+ } else if (H5Tequal(type, H5T_NATIVE_SCHAR)) {
+ h5tools_str_append(str, OPT(info->fmt_schar, "%d"), *cp_vp);
+ } else if (H5Tequal(type, H5T_NATIVE_UCHAR)) {
+ h5tools_str_append(str, OPT(info->fmt_uchar, "%u"), *ucp_vp);
+ } else if (H5Tequal(type, H5T_NATIVE_SHORT)) {
+ memcpy(&tempshort, vp, sizeof(short));
+ h5tools_str_append(str, OPT(info->fmt_short, "%d"), tempshort);
+ } else if (H5Tequal(type, H5T_NATIVE_USHORT)) {
+ memcpy(&tempushort, vp, sizeof(unsigned short));
+ h5tools_str_append(str, OPT(info->fmt_ushort, "%u"), tempushort);
+ } else if (H5Tequal(type, H5T_NATIVE_LONG)) {
+ memcpy(&templong, vp, sizeof(long));
+ h5tools_str_append(str, OPT(info->fmt_long, "%ld"), templong);
+ } else if (H5Tequal(type, H5T_NATIVE_ULONG)) {
+ memcpy(&tempulong, vp, sizeof(unsigned long));
+ h5tools_str_append(str, OPT(info->fmt_ulong, "%lu"), tempulong);
+ } else if (H5Tequal(type, H5T_NATIVE_LLONG)) {
+ memcpy(&templlong, vp, sizeof(long_long));
+ h5tools_str_append(str, OPT(info->fmt_llong, fmt_llong), templlong);
+ } else if (H5Tequal(type, H5T_NATIVE_ULLONG)) {
+ memcpy(&tempullong, vp, sizeof(unsigned long_long));
+ h5tools_str_append(str, OPT(info->fmt_ullong, fmt_ullong), tempullong);
+ } else if (H5Tequal(type, H5T_NATIVE_HSSIZE)) {
+ if (sizeof(hssize_t) == sizeof(int)) {
+ memcpy(&tempint, vp, sizeof(int));
+ h5tools_str_append(str, OPT(info->fmt_int, "%d"), tempint);
+ } else if (sizeof(hssize_t) == sizeof(long)) {
+ memcpy(&templong, vp, sizeof(long));
+ h5tools_str_append(str, OPT(info->fmt_long, "%ld"), templong);
+ } else {
+ memcpy(&templlong, vp, sizeof(long_long));
+ h5tools_str_append(str, OPT(info->fmt_llong, fmt_llong), templlong);
+ }
+ } else if (H5Tequal(type, H5T_NATIVE_HSIZE)) {
+ if (sizeof(hsize_t) == sizeof(int)) {
+ memcpy(&tempuint, vp, sizeof(unsigned int));
+ h5tools_str_append(str, OPT(info->fmt_uint, "%u"), tempuint);
+ } else if (sizeof(hsize_t) == sizeof(long)) {
+ memcpy(&tempulong, vp, sizeof(long));
+ h5tools_str_append(str, OPT(info->fmt_ulong, "%lu"), tempulong);
+ } else {
+ memcpy(&tempullong, vp, sizeof(unsigned long_long));
+ h5tools_str_append(str, OPT(info->fmt_ullong, fmt_ullong), tempullong);
+ }
+ } else if (H5Tget_class(type) == H5T_COMPOUND) {
+ int j;
+
+ nmembs = H5Tget_nmembers(type);
+ h5tools_str_append(str, "%s", OPT(info->cmpd_pre, "{"));
+
+ for (j = 0; j < nmembs; j++) {
+ if (j)
+ h5tools_str_append(str, "%s", OPT(info->cmpd_sep, ", " OPTIONAL_LINE_BREAK));
+
+ /* RPM 2000-10-31
+ * If the previous character is a line-feed (which is true when
+ * h5dump is running) then insert some white space for
+ * indentation. Be warned that column number calculations will be
+ * incorrect and that object indices at the beginning of the line
+ * will be missing (h5dump doesn't display them anyway). */
+ if (ctx->indent_level >= 0 && str->len && str->s[str->len - 1] == '\n') {
+ int x;
+
+ h5tools_str_append(str, OPT(info->line_pre, ""), "");
+
+ for (x = 0; x < ctx->indent_level + 1; x++)
+ h5tools_str_append(str, "%s", OPT(info->line_indent, ""));
+ }
+
+ /* The name */
+ name = H5Tget_member_name(type, j);
+ h5tools_str_append(str, OPT(info->cmpd_name, ""), name);
+ free(name);
+
+ /* The value */
+ offset = H5Tget_member_offset(type, j);
+ memb = H5Tget_member_type(type, j);
+
+ ctx->indent_level++;
+ h5tools_sprint(str, info, container, memb, cp_vp + offset , ctx);
+ ctx->indent_level--;
+
+ H5Tclose(memb);
+ }
+
+ /* RPM 2000-10-31
+ * If the previous character is a line feed (which is true when
+ * h5dump is running) then insert some white space for indentation.
+ * Be warned that column number calculations will be incorrect and
+ * that object indices at the beginning of the line will be missing
+ * (h5dump doesn't display them anyway). */
+ h5tools_str_append(str, "%s", OPT(info->cmpd_end, ""));
+
+ if (ctx->indent_level >= 0 && str->len && str->s[str->len - 1] == '\n') {
+ int x;
+
+ h5tools_str_append(str, OPT(info->line_pre, ""), "");
+
+ for (x = 0; x < ctx->indent_level; x++)
+ h5tools_str_append(str, "%s", OPT(info->line_indent, ""));
+ }
+
+ h5tools_str_append(str, "%s", OPT(info->cmpd_suf, "}"));
+ } else if (H5Tget_class(type) == H5T_ENUM) {
+ char enum_name[1024];
+
+ if (H5Tenum_nameof(type, vp, enum_name, sizeof enum_name) >= 0) {
+ h5tools_str_append(str, h5tools_escape(enum_name, sizeof(enum_name), TRUE));
+ } else {
+ size_t i;
+
+ h5tools_str_append(str, "0x");
+ n = H5Tget_size(type);
+
+ for (i = 0; i < n; i++)
+ h5tools_str_append(str, "%02x", ucp_vp[i]);
+ }
+ } else if (H5Tequal(type, H5T_STD_REF_DSETREG)) {
+ /*
+ * Dataset region reference -- show the type and OID of the referenced
+ * object, but we are unable to show the region yet because there
+ * isn't enough support in the data space layer. - rpm 19990604
+ */
+ if (h5tools_is_zero(vp, H5Tget_size(type))) {
+ h5tools_str_append(str, "NULL");
+ } else {
+ obj = H5Rdereference(container, H5R_DATASET_REGION, vp);
+ region = H5Rget_region(container, H5R_DATASET_REGION, vp);
+ H5Gget_objinfo(obj, ".", FALSE, &sb);
+
+ if (info->dset_hidefileno)
+ h5tools_str_append(str, info->dset_format, sb.objno[1], sb.objno[0]);
+ else
+ h5tools_str_append(str, info->dset_format,
+ sb.fileno[1], sb.fileno[0], sb.objno[1], sb.objno[0]);
+
+ h5dump_region(region, str, info);
+ H5Sclose(region);
+ H5Dclose(obj);
+ }
+ } else if (H5Tequal(type, H5T_STD_REF_OBJ)) {
+ /*
+ * Object references -- show the type and OID of the referenced
+ * object.
+ */
+ if (h5tools_is_zero(vp, H5Tget_size(type))) {
+ h5tools_str_append(str, "NULL");
+ } else {
+ otype = H5Rget_object_type(container, vp);
+ obj = H5Rdereference(container, H5R_OBJECT, vp);
+ H5Gget_objinfo(obj, ".", FALSE, &sb);
+
+ /* Print object type and close object */
+ switch (otype) {
+ case H5G_GROUP:
+ h5tools_str_append(str, GROUPNAME);
+ H5Gclose(obj);
+ break;
+ case H5G_DATASET:
+ h5tools_str_append(str, DATASET);
+ H5Dclose(obj);
+ break;
+ case H5G_TYPE:
+ h5tools_str_append(str, DATATYPE);
+ H5Tclose(obj);
+ break;
+ default:
+ h5tools_str_append(str, "%u-", otype);
+ break;
+ }
+
+ /* Print OID */
+ if (info->obj_hidefileno) {
+ h5tools_str_append(str, info->obj_format, sb.objno[1], sb.objno[0]);
+ } else {
+ h5tools_str_append(str, info->obj_format,
+ sb.fileno[1], sb.fileno[0], sb.objno[1], sb.objno[0]);
+ }
+ }
+ } else if (H5Tget_class(type) == H5T_ARRAY) {
+ int k, ndims;
+ hsize_t i, dims[H5S_MAX_RANK];
+
+ /* Get the array's base datatype for each element */
+ memb = H5Tget_super(type);
+ size = H5Tget_size(memb);
+ ndims = H5Tget_array_ndims(type);
+ H5Tget_array_dims(type, dims, NULL);
+ assert(ndims >= 1 && ndims <= H5S_MAX_RANK);
+
+ /* Calculate the number of array elements */
+ for (k = 0, nelmts = 1; k < ndims; k++)
+ nelmts *= dims[k];
+
+ /* Print the opening bracket */
+ h5tools_str_append(str, "%s", OPT(info->arr_pre, "["));
+
+ for (i = 0; i < nelmts; i++) {
+ if (i)
+ h5tools_str_append(str, "%s",
+ OPT(info->arr_sep, "," OPTIONAL_LINE_BREAK));
+
+ if (info->arr_linebreak && i && i % dims[ndims - 1] == 0) {
+ int x;
+
+ h5tools_str_append(str, "%s", "\n");
+
+ /*need to indent some more here*/
+ if (ctx->indent_level >= 0)
+ h5tools_str_append(str, "%s", OPT(info->line_pre, ""));
+
+ for (x = 0; x < ctx->indent_level + 1; x++)
+ h5tools_str_append(str,"%s",OPT(info->line_indent,""));
+ } /* end if */
+
+ ctx->indent_level++;
+
+ /* Dump the array element */
+ h5tools_sprint(str, info, container, memb, cp_vp + i * size, ctx);
+
+ ctx->indent_level--;
+ } /* end for */
+
+ /* Print the closing bracket */
+ h5tools_str_append(str, "%s", OPT(info->arr_suf, "]"));
+ H5Tclose(memb);
+ } else if (H5Tget_class(type) == H5T_VLEN) {
+ unsigned int i;
+
+ /* Get the VL sequences's base datatype for each element */
+ memb = H5Tget_super(type);
+ size = H5Tget_size(memb);
+
+ /* Print the opening bracket */
+ h5tools_str_append(str, "%s", OPT(info->vlen_pre, "("));
+
+ /* Get the number of sequence elements */
+ nelmts = ((hvl_t *)cp_vp)->len;
+
+ for (i = 0; i < nelmts; i++) {
+ if (i)
+ h5tools_str_append(str, "%s",
+ OPT(info->arr_sep, "," OPTIONAL_LINE_BREAK));
+
+#ifdef LATER
+/* Need to fix so VL data breaks at correct location on end of line -QAK */
+ if (info->arr_linebreak && h5tools_str_len(str)>=info->line_ncols) {
+ int x;
+
+ h5tools_str_append(str, "%s", "\n");
+
+ /* need to indent some more here */
+ if (ctx->indent_level >= 0)
+ h5tools_str_append(str, "%s", OPT(info->line_pre, ""));
+
+ for (x = 0; x < ctx->indent_level + 1; x++)
+ h5tools_str_append(str,"%s",OPT(info->line_indent,""));
+ } /* end if */
+#endif /* LATER */
+
+ ctx->indent_level++;
+
+ /* Dump the array element */
+ h5tools_sprint(str, info, container, memb,
+ ((char *)(((hvl_t *)cp_vp)->p)) + i * size, ctx);
+
+ ctx->indent_level--;
+ } /* end for */
+
+ h5tools_str_append(str, "%s", OPT(info->vlen_suf, ")"));
+ H5Tclose(memb);
+ } else {
+ /* All other types get printed as hexadecimal */
+ size_t i;
+
+ h5tools_str_append(str, "0x");
+ n = H5Tget_size(type);
+
+ for (i = 0; i < n; i++)
+ h5tools_str_append(str, "%02x", ucp_vp[i]);
+ }
+
+ return h5tools_str_fmt(str, start, OPT(info->elmt_fmt, "%s"));
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_ncols
+ *
+ * Purpose: Count the number of columns in a string. This is the number
+ * of characters in the string not counting line-control
+ * characters.
+ *
+ * Return: Success: Width of string.
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Tuesday, April 27, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static size_t
+h5tools_ncols(const char *s)
+{
+ register size_t i;
+
+ for (i = 0; *s; s++)
+ if (*s >= ' ')
+ i++;
+
+ return i;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_prefix
+ *
+ * Purpose: If ctx->need_prefix is set then terminate the current line
+ * (if applicable), calculate the prefix string, and display it
+ * at the start of a line.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ * Robb Matzke, 1999-09-29
+ * If a new prefix is printed then the current element number is
+ * set back to zero.
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_simple_prefix(FILE *stream, const h5dump_t *info,
+ h5tools_context_t *ctx, hsize_t elmtno, int secnum)
+{
+ h5tools_str_t prefix;
+ size_t templength = 0;
+ int i, indentlevel = 0;
+
+ memset(&prefix, 0, sizeof(h5tools_str_t));
+
+ if (!ctx->need_prefix)
+ return;
+
+ /* Terminate previous line, if any */
+ if (ctx->cur_column) {
+ fputs(OPT(info->line_suf, ""), stream);
+#if 0 /*why?*/
+ if (info->line_ncols != ctx->cur_column) {
+ putc('\n', stream);
+ }
+#endif
+ putc('\n', stream);
+ fputs(OPT(info->line_sep, ""), stream);
+ }
+
+ /* Calculate new prefix */
+ h5tools_str_prefix(&prefix, info, elmtno, ctx->ndims, ctx->p_min_idx,
+ ctx->p_max_idx);
+
+ /* Write new prefix to output */
+ if (ctx->indent_level >= 0) {
+ indentlevel = ctx->indent_level;
+ } else {
+ /* this is because sometimes we dont print out all the header
+ * info for the data(like the tattr-2.ddl example. if that happens
+ * the ctx->indent_level a negative so we need to skip the above
+ * and just print out the default indent levels. */
+ indentlevel = ctx->default_indent_level;
+ }
+
+ if (elmtno == 0 && secnum == 0 && info->line_1st)
+ fputs(h5tools_str_fmt(&prefix, 0, info->line_1st), stream);
+ else if (secnum && info->line_cont)
+ fputs(h5tools_str_fmt(&prefix, 0, info->line_cont), stream);
+ else
+ fputs(h5tools_str_fmt(&prefix, 0, info->line_pre), stream);
+
+ templength = h5tools_str_len(&prefix);
+
+ for (i = 0; i < indentlevel; i++){
+ fputs(h5tools_str_fmt(&prefix, 0, info->line_indent), stream);
+ templength += h5tools_str_len(&prefix);
+ }
+
+ ctx->cur_column = ctx->prev_prefix_len = templength;
+ ctx->cur_elmt = 0;
+ ctx->need_prefix = 0;
+
+ /* Free string */
+ h5tools_str_close(&prefix);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_data
+ *
+ * Purpose: Prints some (NELMTS) data elements to output STREAM. The
+ * elements are stored in _MEM as type TYPE and are printed
+ * according to the format described in INFO. The CTX struct
+ * contains context information shared between calls to this
+ * function. The FLAGS is a bit field that indicates whether
+ * the data supplied in this call falls at the beginning or end
+ * of the total data to be printed (START_OF_DATA and
+ * END_OF_DATA).
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ * Robb Matzke, 1999-06-04
+ * The `container' argument is the optional dataset for
+ * reference types.
+ *
+ * Robb Matzke, 1999-09-29
+ * Understands the `per_line' property which indicates that
+ * every Nth element should begin a new line.
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+h5dump_simple_data(FILE *stream, const h5dump_t *info, hid_t container,
+ h5tools_context_t *ctx/*in,out*/, unsigned flags,
+ hsize_t nelmts, hid_t type, void *_mem)
+{
+ unsigned char *mem = (unsigned char*)_mem;
+ hsize_t i; /*element counter */
+ char *s, *section; /*a section of output */
+ int secnum; /*section sequence number */
+ size_t size; /*size of each datum */
+ size_t ncols=80; /*available output width */
+ h5tools_str_t buffer; /*string into which to render */
+ int multiline; /*datum was multiline */
+ int elmt_counter=0; /*counts the # elements printed.
+ * I (ptl?) needed something that
+ * isnt going to get reset when a new
+ * line is formed. I'm going to use
+ * this var to count elements and
+ * break after we see a number equal
+ * to the ctx->size_last_dim. */
+
+ /* Setup */
+ memset(&buffer, 0, sizeof(h5tools_str_t));
+ size = H5Tget_size(type);
+
+ if (info->line_ncols > 0)
+ ncols = info->line_ncols;
+
+ h5dump_simple_prefix(stream, info, ctx, (hsize_t)0, 0);
+
+ for (i = 0; i < nelmts; i++, ctx->cur_elmt++, elmt_counter++) {
+ /* Render the element */
+ h5tools_str_reset(&buffer);
+ h5tools_sprint(&buffer, info, container, type, mem + i * size, ctx);
+
+ if (i + 1 < nelmts || 0 == (flags & END_OF_DATA))
+ h5tools_str_append(&buffer, "%s", OPT(info->elmt_suf1, ","));
+
+ s = h5tools_str_fmt(&buffer, 0, "%s");
+
+ /*
+ * If the element would split on multiple lines if printed at our
+ * current location...
+ */
+ if (info->line_multi_new == 1 &&
+ (ctx->cur_column + h5tools_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols) {
+ if (ctx->prev_multiline) {
+ /*
+ * ... and the previous element also occupied more than one
+ * line, then start this element at the beginning of a line.
+ */
+ ctx->need_prefix = TRUE;
+ } else if ((ctx->prev_prefix_len + h5tools_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) <= ncols) {
+ /*
+ * ...but *could* fit on one line otherwise, then we
+ * should end the current line and start this element on its
+ * own line.
+ */
+ ctx->need_prefix = TRUE;
+ }
+ }
+
+ /*
+ * We need to break after each row of a dimension---> we should
+ * break at the end of the each last dimension well that is the
+ * way the dumper did it before
+ */
+ if (info->arr_linebreak && ctx->cur_elmt) {
+ if (ctx->size_last_dim && (ctx->cur_elmt % ctx->size_last_dim) == 0)
+ ctx->need_prefix = TRUE;
+
+ if (elmt_counter == ctx->size_last_dim) {
+ ctx->need_prefix = TRUE;
+ elmt_counter = 0;
+ }
+ }
+
+ /*
+ * If the previous element occupied multiple lines and this element
+ * is too long to fit on a line then start this element at the
+ * beginning of the line.
+ */
+ if (info->line_multi_new == 1 && ctx->prev_multiline &&
+ (ctx->cur_column + h5tools_ncols(s) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols)
+ ctx->need_prefix = TRUE;
+
+ /*
+ * If too many elements have already been printed then we need to
+ * start a new line.
+ */
+ if (info->line_per_line > 0 && ctx->cur_elmt >= info->line_per_line)
+ ctx->need_prefix = TRUE;
+
+ /*
+ * Each OPTIONAL_LINE_BREAK embedded in the rendered string can cause
+ * the data to split across multiple lines. We display the sections
+ * one-at a time.
+ */
+ for (secnum = 0, multiline = 0;
+ (section = strtok(secnum ? NULL : s, OPTIONAL_LINE_BREAK));
+ secnum++) {
+ /*
+ * If the current section plus possible suffix and end-of-line
+ * information would cause the output to wrap then we need to
+ * start a new line.
+ */
+
+ /*
+ * Added the info->skip_first because the dumper does not want
+ * this check to happen for the first line
+ */
+ if ((!info->skip_first || i) &&
+ (ctx->cur_column + strlen(section) +
+ strlen(OPT(info->elmt_suf2, " ")) +
+ strlen(OPT(info->line_suf, ""))) > ncols)
+ ctx->need_prefix = 1;
+
+ /*
+ * Print the prefix or separate the beginning of this element
+ * from the previous element.
+ */
+ if (ctx->need_prefix) {
+ if (secnum)
+ multiline++;
+
+ h5dump_simple_prefix(stream, info, ctx, i, secnum);
+ } else if ((i || ctx->continuation) && secnum == 0) {
+ fputs(OPT(info->elmt_suf2, " "), stream);
+ ctx->cur_column += strlen(OPT(info->elmt_suf2, " "));
+ }
+
+ /* Print the section */
+ fputs(section, stream);
+ ctx->cur_column += strlen(section);
+ }
+
+ ctx->prev_multiline = multiline;
+ }
+
+ h5tools_str_close(&buffer);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_dset
+ *
+ * Purpose: Print some values from a dataset with a simple data space.
+ * This is a special case of h5dump_dset(). This function only
+ * intended for dumping datasets -- it does strip mining and
+ * some other things which are unnecessary for smaller objects
+ * such as attributes (to print small objects like attributes
+ * simply read the attribute and call h5dump_simple_mem()).
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+h5dump_simple_dset(FILE *stream, const h5dump_t *info, hid_t dset,
+ hid_t p_type, int indentlevel)
+{
+ hid_t f_space; /*file data space */
+ hsize_t elmtno, i; /*counters */
+ int carry; /*counter carry value */
+ hssize_t zero[8]; /*vector of zeros */
+ unsigned flags; /*buffer extent flags */
+ hsize_t total_size[H5S_MAX_RANK];/*total size of dataset*/
+
+ /* Print info */
+ h5tools_context_t ctx; /*print context */
+ size_t p_type_nbytes; /*size of memory type */
+ hsize_t p_nelmts; /*total selected elmts */
+
+ /* Stripmine info */
+ hsize_t sm_size[H5S_MAX_RANK]; /*stripmine size */
+ hsize_t sm_nbytes; /*bytes per stripmine */
+ hsize_t sm_nelmts; /*elements per stripmine*/
+ unsigned char *sm_buf=NULL; /*buffer for raw data */
+ hid_t sm_space; /*stripmine data space */
+
+ /* Hyperslab info */
+ hssize_t hs_offset[H5S_MAX_RANK];/*starting offset */
+ hsize_t hs_size[H5S_MAX_RANK]; /*size this pass */
+ hsize_t hs_nelmts; /*elements in request */
+
+ /* VL data special information */
+ unsigned vl_data=0; /* Whether the dataset contains VL datatypes */
+
+#if 0
+ hsize_t dim_n_size;
+#endif
+
+ /*
+ * 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.
+ */
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.indent_level = indentlevel;
+ ctx.need_prefix = 1;
+ f_space = H5Dget_space(dset);
+ ctx.ndims = H5Sget_simple_extent_ndims(f_space);
+
+ if ((size_t)ctx.ndims > NELMTS(sm_size))
+ return -1;
+
+ /* Assume entire data space to be printed */
+ if (ctx.ndims > 0)
+ for (i = 0; i < (hsize_t)ctx.ndims; i++)
+ ctx.p_min_idx[i] = 0;
+
+ H5Sget_simple_extent_dims(f_space, total_size, NULL);
+
+ if (ctx.ndims > 0) {
+ for (i = 0, p_nelmts = 1; i < (hsize_t)ctx.ndims; i++)
+ p_nelmts *= total_size[i];
+ } else {
+ p_nelmts = 1;
+ }
+
+ if (p_nelmts == 0) {
+ H5Sclose(f_space);
+ return 0; /*nothing to print*/
+ }
+
+ ctx.size_last_dim = total_size[ctx.ndims - 1];
+
+ /* Check if we have VL data in the dataset's datatype */
+ if(H5Tdetect_class(p_type,H5T_VLEN)==TRUE)
+ vl_data=TRUE;
+
+ /*
+ * 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);
+
+ if (ctx.ndims > 0) {
+ for (i = ctx.ndims, sm_nbytes = p_type_nbytes; i > 0; --i) {
+ sm_size[i - 1] = MIN(total_size[i - 1], H5DUMP_BUFSIZE / sm_nbytes);
+ sm_nbytes *= sm_size[i - 1];
+ assert(sm_nbytes > 0);
+ }
+ } else {
+ sm_nbytes = p_type_nbytes;
+ }
+
+ assert(sm_nbytes == (hsize_t)((size_t)sm_nbytes)); /*check for overflow*/
+ sm_buf = malloc((size_t)sm_nbytes);
+ sm_nelmts = sm_nbytes / p_type_nbytes;
+ sm_space = H5Screate_simple(1, &sm_nelmts, NULL);
+
+ /* 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 */
+ if (ctx.ndims > 0) {
+ for (i = 0, hs_nelmts = 1; i < (hsize_t)ctx.ndims; i++) {
+ hs_size[i] = MIN(total_size[i] - hs_offset[i], sm_size[i]);
+ ctx.p_max_idx[i] = ctx.p_min_idx[i] + hs_size[i];
+ hs_nelmts *= hs_size[i];
+ }
+
+ 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);
+ } else {
+ H5Sselect_all(f_space);
+ H5Sselect_all(sm_space);
+ hs_nelmts = 1;
+ }
+
+ /* Read the data */
+ if (H5Dread(dset, p_type, sm_space, f_space, H5P_DEFAULT, sm_buf) < 0) {
+ H5Sclose(f_space);
+ H5Sclose(sm_space);
+ free(sm_buf);
+ return -1;
+ }
+
+ /* Print the data */
+ flags = (elmtno == 0) ? START_OF_DATA : 0;
+ flags |= ((elmtno + hs_nelmts) >= p_nelmts) ? END_OF_DATA : 0;
+ h5dump_simple_data(stream, info, dset, &ctx, flags, hs_nelmts,
+ p_type, sm_buf);
+
+ /* Reclaim any VL memory, if necessary */
+ if(vl_data)
+ H5Dvlen_reclaim(p_type,sm_space,H5P_DEFAULT,sm_buf);
+
+ /* Calculate the next hyperslab offset */
+ for (i = ctx.ndims, carry = 1; i > 0 && carry; --i) {
+ ctx.p_min_idx[i - 1] = ctx.p_max_idx[i - 1];
+ hs_offset[i - 1] += hs_size[i - 1];
+
+ if (hs_offset[i - 1] == (hssize_t)total_size[i - 1])
+ hs_offset[i-1] = 0;
+ else
+ carry = 0;
+ }
+
+ ctx.continuation++;
+ }
+
+ /* Terminate the output */
+ if (ctx.cur_column) {
+ fputs(OPT(info->line_suf, ""), stream);
+ putc('\n', stream);
+ fputs(OPT(info->line_sep, ""), stream);
+ }
+
+ H5Sclose(sm_space);
+ H5Sclose(f_space);
+ free(sm_buf);
+ return 0;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_simple_mem
+ *
+ * Purpose: Print some values from memory with a simple data space.
+ * This is a special case of h5dump_mem().
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static int
+h5dump_simple_mem(FILE *stream, const h5dump_t *info, hid_t obj_id, hid_t type,
+ hid_t space, void *mem, int indentlevel)
+{
+ hsize_t i; /*counters */
+ hsize_t nelmts; /*total selected elmts */
+ h5tools_context_t ctx; /*printing context */
+
+ /*
+ * 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.
+ */
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.ndims = H5Sget_simple_extent_ndims(space);
+
+ if ((size_t)ctx.ndims > NELMTS(ctx.p_min_idx))
+ return -1;
+
+ ctx.indent_level = indentlevel;
+ ctx.need_prefix = 1;
+
+ /* Assume entire data space to be printed */
+ for (i = 0; i < (hsize_t)ctx.ndims; i++)
+ ctx.p_min_idx[i] = 0;
+
+ H5Sget_simple_extent_dims(space, ctx.p_max_idx, NULL);
+
+ for (i = 0, nelmts = 1; ctx.ndims != 0 && i < (hsize_t)ctx.ndims; i++)
+ nelmts *= ctx.p_max_idx[i] - ctx.p_min_idx[i];
+
+ if (nelmts == 0)
+ return 0; /*nothing to print*/
+
+ ctx.size_last_dim = ctx.p_max_idx[ctx.ndims - 1];
+
+ /* Print it */
+ h5dump_simple_data(stream, info, obj_id, &ctx,
+ START_OF_DATA | END_OF_DATA, nelmts, type, mem);
+
+ /* Terminate the output */
+ if (ctx.cur_column) {
+ fputs(OPT(info->line_suf, ""), stream);
+ putc('\n', stream);
+ fputs(OPT(info->line_sep, ""), stream);
+ }
+
+ 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:
+ * Robb Matzke, 1999-06-04
+ * Added support for references.
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+h5dump_fixtype(hid_t f_type)
+{
+ hid_t m_type = FAIL, f_memb;
+ hid_t *memb = NULL;
+ char **name = NULL;
+ int nmembs = 0, i;
+ int ndims;
+ hsize_t dim[H5S_MAX_RANK];
+ size_t size, offset;
+ hid_t array_base;
+ /* H5T_str_t strpad; */
+
+ 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_SCHAR);
+ } 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_sign(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_STRING:
+ /*
+ * This is needed because the function in dumputil.c is the case where
+ * strDUAction == TRUE. if it is false we will do the original action
+ * here.
+ */
+ m_type = H5Tcopy(f_type);
+ H5Tset_cset(m_type, H5T_CSET_ASCII);
+ break;
+
+ case H5T_COMPOUND:
+ /*
+ * We have to do this in two steps. The first step scans the file
+ * type and converts the members to native types and remembers all
+ * their names and sizes, computing the size of the memory compound
+ * type at the same time. Then we create the memory compound type
+ * and add the members.
+ */
+ nmembs = H5Tget_nmembers(f_type);
+ assert(nmembs>0);
+ memb = calloc((size_t)nmembs, sizeof(hid_t));
+ name = calloc((size_t)nmembs, sizeof(char *));
+
+ for (i = 0, size = 0; i < nmembs; i++) {
+ /* Get the member type and fix it */
+ f_memb = H5Tget_member_type(f_type, i);
+ memb[i] = h5dump_fixtype(f_memb);
+ H5Tclose(f_memb);
+
+ if (memb[i] < 0)
+ goto done;
+
+ /* Get the member name */
+ name[i] = H5Tget_member_name(f_type, i);
+
+ if (name[i] == NULL)
+ goto done;
+
+ /*
+ * Compute the new offset so each member is aligned on a byte
+ * boundary which is the same as the member size.
+ */
+ size = ALIGN(size, H5Tget_size(memb[i])) + H5Tget_size(memb[i]);
+ }
+
+ m_type = H5Tcreate(H5T_COMPOUND, size);
+
+ for (i = 0, offset = 0; i < nmembs; i++) {
+ if (offset)
+ offset = ALIGN(offset, H5Tget_size(memb[i]));
+
+ H5Tinsert(m_type, name[i], offset, memb[i]);
+ offset += H5Tget_size(memb[i]);
+ }
+
+ break;
+
+ case H5T_ARRAY:
+ /* Get the array information */
+ ndims = H5Tget_array_ndims(f_type);
+ H5Tget_array_dims(f_type, dim, NULL);
+
+ /* Get the array's base type and convert it to the printable version */
+ f_memb = H5Tget_super(f_type);
+ array_base = h5dump_fixtype(f_memb);
+
+ /* Copy the array */
+ m_type = H5Tarray_create(array_base, ndims, dim, NULL);
+
+ /* Close the temporary datatypes */
+ H5Tclose(array_base);
+ H5Tclose(f_memb);
+ break;
+
+ case H5T_VLEN:
+ /* Get the VL sequence's base type and convert it to the printable version */
+ f_memb = H5Tget_super(f_type);
+ array_base = h5dump_fixtype(f_memb);
+
+ /* Copy the VL type */
+ m_type = H5Tvlen_create(array_base);
+
+ /* Close the temporary datatypes */
+ H5Tclose(array_base);
+ H5Tclose(f_memb);
+ break;
+
+ case H5T_ENUM:
+ case H5T_REFERENCE:
+ case H5T_OPAQUE:
+ /* Same as file type */
+ m_type = H5Tcopy(f_type);
+ break;
+
+ case H5T_BITFIELD:
+ /*
+ * Same as the file except the offset is set to zero and the byte
+ * order is set to little endian.
+ */
+ m_type = H5Tcopy(f_type);
+ H5Tset_offset(m_type, 0);
+ H5Tset_order(m_type, H5T_ORDER_LE);
+ break;
+
+ case H5T_TIME:
+ /*
+ * These type classes are not implemented yet.
+ */
+ break;
+
+ default:
+ /* What the heck? */
+ break;
+ }
+
+ done:
+ /* Clean up temp buffers */
+ if (memb && name) {
+ register int j;
+
+ for (j = 0; j < nmembs; j++) {
+ if (memb[j] >= 0)
+ H5Tclose(memb[j]);
+
+ if (name[j])
+ free(name[j]);
+ }
+
+ free(memb);
+ free(name);
+ }
+
+ return m_type;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_dset
+ *
+ * Purpose: Print some values from a dataset DSET to the file STREAM
+ * after converting all types to P_TYPE (which should be a
+ * native type). If P_TYPE is a negative value then it will be
+ * computed from the dataset type using only native types.
+ *
+ * Note: This function is intended only for datasets since it does
+ * some things like strip mining which are unnecessary for
+ * smaller objects such as attributes. The easiest way to print
+ * small objects is to read the object into memory and call
+ * h5dump_mem().
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ * Robb Matzke, 1999-06-07
+ * If info->raw is set then the memory datatype will be the same
+ * as the file datatype.
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+h5dump_dset(FILE *stream, const h5dump_t *info, hid_t dset, hid_t _p_type,
+ int indentlevel)
+{
+ hid_t f_space;
+ hid_t p_type = _p_type;
+ hid_t f_type;
+ int status = -1;
+ h5dump_t info_dflt;
+
+ /* Use default values */
+ if (!stream)
+ stream = stdout;
+
+ if (!info) {
+ memset(&info_dflt, 0, sizeof info_dflt);
+ info = &info_dflt;
+ }
+
+ if (p_type < 0) {
+ f_type = H5Dget_type(dset);
+
+ if (info->raw)
+ p_type = H5Tcopy(f_type);
+ else
+ p_type = h5dump_fixtype(f_type);
+
+ H5Tclose(f_type);
+
+ if (p_type < 0)
+ goto done;
+ }
+
+ /* Check the data space */
+ f_space = H5Dget_space(dset);
+
+ /* Print the data */
+ if (H5Sis_simple(f_space) > 0) {
+ status = h5dump_simple_dset(rawdatastream, info, dset, p_type,
+ indentlevel);
+ }
+
+ /* Close the dataspace */
+ H5Sclose(f_space);
+
+done:
+ if (p_type != _p_type)
+ H5Tclose(p_type);
+
+ return status;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_mem
+ *
+ * Purpose: Displays the data contained in MEM. MEM must have the
+ * specified data TYPE and SPACE. Currently only simple data
+ * spaces are allowed and only the `all' selection.
+ *
+ * Return: Success: 0
+ *
+ * Failure: -1
+ *
+ * Programmer: Robb Matzke
+ * Wednesday, January 20, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+h5dump_mem(FILE *stream, const h5dump_t *info, hid_t obj_id, hid_t type, hid_t space,
+ void *mem,int indentlevel)
+{
+ h5dump_t info_dflt;
+
+ /* Use default values */
+ if (!stream)
+ stream = stdout;
+
+ if (!info) {
+ memset(&info_dflt, 0, sizeof info_dflt);
+ info = &info_dflt;
+ }
+
+ /* Check the data space */
+ if (H5Sis_simple(space) <= 0)
+ return -1;
+
+ return h5dump_simple_mem(stream, info, obj_id, type, space, mem, indentlevel);
+}
+
+/*************************************************************************
+
+ from h5dumputil.c
+
+ *************************************************************************/
+
+/*-------------------------------------------------------------------------
+ * Function: indentation
+ *
+ * Purpose: Print spaces for indentation
+ *
+ * Return: void
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void indentation(int x)
+{
+ if (x < nCols) {
+ while (x-- > 0)
+ printf(" ");
+ } else {
+ fprintf(stderr, "error: the indentation exceeds the number of cols.\n");
+ exit(1);
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: print_version
+ *
+ * Purpose: Print the program name and the version information which is
+ * defined the same as the HDF5 library version.
+ *
+ * Return: void
+ *
+ * Programmer: unknown
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+print_version(const char *progname)
+{
+ printf("%s: Version %u.%u.%u%s%s\n",
+ progname, H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE,
+ H5_VERS_SUBRELEASE[0] ? "-" : "", H5_VERS_SUBRELEASE);
+}
+
+/*
+ *
+ * THE FUNCTIONS BELOW ARE FROM THE H5FINSHD.C FILE
+ *
+ */
+
+/*-------------------------------------------------------------------------
+ * Function: init_table
+ *
+ * Purpose: allocate and initialize tables for shared groups, datasets,
+ * and committed types
+ *
+ * Return: void
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+init_table(table_t** temp)
+{
+ int i;
+ table_t *table = malloc(sizeof(table_t));
+
+ table->size = 20;
+ table->nobjs = 0;
+ table->objs = malloc(table->size * sizeof(obj_t));
+
+ for (i = 0; i < table->size; i++) {
+ table->objs[i].objno[0] = table->objs[i].objno[1] = 0;
+ table->objs[i].displayed = 0;
+ table->objs[i].recorded = 0;
+ table->objs[i].objflag = 0;
+ }
+
+ *temp = table;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: init_prefix
+ *
+ * Purpose: allocate and initialize prefix
+ *
+ * Return: void
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+init_prefix(char **prefix, int prefix_len)
+{
+ assert(prefix_len > 0);
+ *prefix = calloc((size_t)prefix_len, 1);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: free_table
+ *
+ * Purpose: free tables for shared groups, datasets,
+ * and committed types
+ *
+ * Return: void
+ *
+ * Programmer: Paul Harten
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+free_table(table_t **table)
+{
+ HDfree((*table)->objs);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: search_obj
+ *
+ * Purpose: search the object specified by objno in the table
+ *
+ * Return: an integer, the location of the object
+ * -1 if object is not found
+ *
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+search_obj(table_t *table, unsigned long *objno)
+{
+ register int i;
+
+ for (i = 0; i < table->nobjs; i++)
+ if (table->objs[i].objno[0] == *objno && table->objs[i].objno[1] == *(objno + 1))
+ return i;
+
+ return -1;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: add_obj
+ *
+ * Purpose: add a shared object to the table
+ * realloc the table if necessary
+ *
+ * Return: void
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static void
+add_obj(table_t *table, unsigned long *objno, char *objname)
+{
+ register int i;
+
+ if (table->nobjs == table->size) {
+ table->size *= 2;
+ table->objs = realloc(table->objs, table->size*sizeof(obj_t));
+
+ for (i = table->nobjs; i < table->size; i++) {
+ table->objs[i].objno[0] = table->objs[i].objno[1] = 0;
+ table->objs[i].displayed = 0;
+ table->objs[i].recorded = 0;
+ table->objs[i].objflag = 0;
+ }
+ }
+
+ i = table->nobjs++;
+ table->objs[i].objno[0] = *objno;
+ table->objs[i].objno[1] = *(objno + 1);
+ strcpy(table->objs[i].objname, objname);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: Find_objs
+ *
+ * Purpose: Find objects, committed types and store them in tables
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+find_objs(hid_t group, const char *name, void *op_data)
+{
+ hid_t obj, type;
+ H5G_stat_t statbuf;
+ char *tmp;
+ find_objs_t *info = (find_objs_t*)op_data;
+ register int i;
+
+ if (info->threshold > 1)
+ /*will get an infinite loop if greater than 1*/
+ return FAIL;
+
+ H5Gget_objinfo(group, name, TRUE, &statbuf);
+
+ tmp = malloc(strlen(info->prefix) + strlen(name) + 2);
+ strcpy(tmp, info->prefix);
+
+ switch (statbuf.type) {
+ case H5G_GROUP:
+ if ((obj = H5Gopen(group, name)) >= 0) {
+ if (info->prefix_len < (int)(strlen(info->prefix) + strlen(name) + 2)) {
+ info->prefix_len *= 2;
+ info->prefix = realloc(info->prefix,
+ info->prefix_len * sizeof(char));
+ }
+
+ strcat(strcat(info->prefix,"/"), name);
+
+ if (statbuf.nlink > info->threshold) {
+ if (search_obj(info->group_table, statbuf.objno) < 0) {
+ add_obj(info->group_table, statbuf.objno, info->prefix);
+ H5Giterate(obj, ".", NULL, find_objs, (void *)info);
+ }
+ } else {
+ H5Giterate (obj, ".", NULL, find_objs, (void *)info);
+ }
+
+ strcpy(info->prefix, tmp);
+ H5Gclose (obj);
+ } else {
+ info->status = 1;
+ }
+
+ break;
+
+ case H5G_DATASET:
+ strcat(tmp,"/");
+ strcat(tmp,name); /* absolute name of the data set */
+
+ if (statbuf.nlink > info->threshold &&
+ search_obj(info->dset_table, statbuf.objno) < 0)
+ add_obj(info->dset_table, statbuf.objno, tmp);
+
+ if ((obj = H5Dopen (group, name)) >= 0) {
+ type = H5Dget_type(obj);
+
+ if (H5Tcommitted(type) > 0) {
+ H5Gget_objinfo(type, ".", TRUE, &statbuf);
+
+ if (search_obj (info->type_table, statbuf.objno) < 0) {
+ add_obj(info->type_table, statbuf.objno, tmp);
+ info->type_table->objs[info->type_table->nobjs - 1].objflag = 0;
+ }
+ }
+
+ H5Tclose(type);
+ H5Dclose (obj);
+ } else {
+ info->status = 1;
+ }
+
+ break;
+
+ case H5G_TYPE:
+ strcat(tmp,"/");
+ strcat(tmp,name); /* absolute name of the type */
+ i = search_obj(info->type_table, statbuf.objno);
+
+ if (i < 0) {
+ add_obj(info->type_table, statbuf.objno, tmp) ;
+
+ /* named data type */
+ info->type_table->objs[info->type_table->nobjs-1].recorded = 1;
+
+ /* named data type */
+ info->type_table->objs[info->type_table->nobjs-1].objflag = 1;
+ } else {
+ strcpy (info->type_table->objs[i].objname, tmp);
+ info->type_table->objs[i].recorded = 1;
+
+ /* named data type */
+ info->type_table->objs[info->type_table->nobjs-1].objflag = 1;
+ }
+
+ break;
+
+ default:
+ break;
+ }
+
+ free(tmp);
+ return SUCCEED;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: dump_tables
+ *
+ * Purpose: display the contents of tables for debugging purposes
+ *
+ * Return: void
+ *
+ * Programmer: Ruey-Hsia Li
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+dump_table(char* tablename, table_t *table)
+{
+ register int i;
+
+ printf("%s: # of entries = %d\n", tablename,table->nobjs);
+
+ for (i = 0; i < table->nobjs; i++)
+ printf("%lu %lu %s %d\n", table->objs[i].objno[0],
+ table->objs[i].objno[1],
+ table->objs[i].objname,
+ table->objs[i].objflag);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: get_table_idx
+ *
+ * Purpose: Determine if objects are in a link loop
+ *
+ * Return: Success: table index of object detected to be in loop
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Paul Harten
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+get_table_idx(table_t *table, unsigned long *objno)
+{
+ return search_obj(table, objno);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: Get table flag setting
+ *
+ * Purpose: Keep the structures and variables used private to
+ * this file.
+ *
+ * Return: Success: Boolean setting of the i'th element of the
+ * object table flag
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Paul Harten
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+get_tableflag(table_t *table, int idx)
+{
+ return table->objs[idx].objflag;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: Set table flag setting
+ *
+ * Purpose: Keep the structures and variables used private to
+ * this file.
+ *
+ * Return: Success: Boolean setting of the i'th element of the
+ * object table flag
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Paul Harten
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+set_tableflag(table_t *table, int idx)
+{
+ table->objs[idx].objflag = TRUE;
+ return SUCCEED;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: get_objectname
+ *
+ * Purpose: Get name of i'th object in table
+ *
+ * Return: Success: strdup() of object name character string
+ *
+ * Failure: NULL
+ *
+ * Programmer: Paul Harten
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+get_objectname(table_t *table, int idx)
+{
+ return strdup(table->objs[idx].objname);
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5dump_fopen
+ *
+ * Purpose: Attempts to open a file with various VFL drivers.
+ *
+ * Return: Success: a file id for the opened file. If
+ * DRIVERNAME is non-null then the first
+ * DRIVERNAME_SIZE-1 characters of the driver
+ * name are copied into the DRIVERNAME array
+ * and null terminated.
+ *
+ * Failure: -1. If DRIVERNAME is non-null then the
+ * first byte is set to the null terminator.
+ *
+ * Modifications:
+ * Robb Matzke, 2000-06-23
+ * We only have to initialize driver[] on the first call,
+ * thereby preventing memory leaks from repeated calls to
+ * H5Pcreate().
+ *
+ * Robb Matzke, 2000-06-23
+ * Added DRIVERNAME_SIZE arg to prevent overflows when
+ * writing to DRIVERNAME.
+ *
+ * Robb Matzke, 2000-06-23
+ * Added test to prevent coredump when the file could not be
+ * opened by any driver.
+ *
+ * Robb Matzke, 2000-06-23
+ * Changed name from H5ToolsFopen() so it jives better with
+ * the names we already have at the top of this source file.
+ *
+ * Thomas Radke, 2000-09-12
+ * Added Stream VFD to the driver[] array.
+ *
+ * Bill Wendling, 2001-01-10
+ * Changed macro behavior so that if we have a version other
+ * than 1.2.x (i.e., > 1.2), then we do the drivers check.
+ *-------------------------------------------------------------------------
+ */
+hid_t
+h5dump_fopen(const char *fname, char *drivername, size_t drivername_size)
+{
+ static struct {
+ const char *name;
+ hid_t fapl;
+ } driver[16];
+ static int ndrivers = 0;
+ hid_t fid = -1;
+#ifndef VERSION12
+ hid_t fapl = H5P_DEFAULT;
+#endif /* !VERSION12 */
+ int drivernum;
+
+ if (!ndrivers) {
+ /* Build a list of file access property lists which we should try
+ * when opening the file. Eventually we'd like some way for the
+ * user to augment/replace this list interactively. */
+ driver[ndrivers].name = "sec2";
+ driver[ndrivers].fapl = H5P_DEFAULT;
+ ndrivers++;
+
+#ifndef VERSION12
+ driver[ndrivers].name = "family";
+ driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS);
+ H5Pset_fapl_family(fapl, (hsize_t)0, H5P_DEFAULT);
+ ndrivers++;
+
+ driver[ndrivers].name = "split";
+ driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS);
+ H5Pset_fapl_split(fapl, "-m.h5", H5P_DEFAULT, "-r.h5", H5P_DEFAULT);
+ ndrivers++;
+
+ driver[ndrivers].name = "multi";
+ driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS);
+ H5Pset_fapl_multi(fapl, NULL, NULL, NULL, NULL, TRUE);
+ ndrivers++;
+
+#ifdef H5_HAVE_STREAM
+ driver[ndrivers].name = "stream";
+ driver[ndrivers].fapl = fapl = H5Pcreate(H5P_FILE_ACCESS);
+ H5Pset_fapl_stream(fapl, NULL);
+ ndrivers++;
+#endif /* H5_HAVE_STREAM */
+#endif /* !VERSION12 */
+ }
+
+ /* Try to open the file using each of the drivers */
+ for (drivernum = 0; drivernum < ndrivers; drivernum++) {
+ H5E_BEGIN_TRY {
+ fid = H5Fopen(fname, H5F_ACC_RDONLY, driver[drivernum].fapl);
+ } H5E_END_TRY;
+
+ if (fid >= 0)
+ break;
+ }
+
+ /* Save the driver name */
+ if (drivername && drivername_size){
+ if (fid >= 0) {
+ strncpy(drivername, driver[drivernum].name, drivername_size);
+ drivername[drivername_size - 1] = '\0';
+ } else {
+ drivername[0] = '\0'; /*no file opened*/
+ }
+ }
+
+ return fid;
+}
diff --git a/tools/lib/h5tools.h b/tools/lib/h5tools.h
new file mode 100644
index 0000000..2d04539
--- /dev/null
+++ b/tools/lib/h5tools.h
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 1998-2001 National Center for Supercomputing Applications
+ * 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 "hdf5.h"
+
+#if H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 2
+#define VERSION12
+#endif /* H5_VERS_MAJOR == 1 && H5_VERS_MINOR == 2 */
+
+#define ESCAPE_HTML 1
+
+#define OPT(X,S) ((X) ? (X) : (S))
+
+/*
+ * Information about how to format output.
+ */
+typedef struct h5dump_t {
+ /*
+ * Fields associated with formatting numeric data. If a datatype matches
+ * multiple formats based on its size, then the first applicable format
+ * from this list is used. However, if `raw' is non-zero then dump all
+ * data in hexadecimal format without translating from what appears on
+ * disk.
+ *
+ * raw: If set then print all data as hexadecimal without
+ * performing any conversion from disk.
+ *
+ * fmt_raw: The printf() format for each byte of raw data. The
+ * default is `%02x'.
+ *
+ * fmt_int: The printf() format to use when rendering data which is
+ * typed `int'. The default is `%d'.
+ *
+ * fmt_uint: The printf() format to use when rendering data which is
+ * typed `unsigned'. The default is `%u'.
+ *
+ * fmt_schar: The printf() format to use when rendering data which is
+ * typed `signed char'. The default is `%d'. This format is
+ * used ony if the `ascii' field is zero.
+ *
+ * fmt_uchar: The printf() format to use when rendering data which is
+ * typed `unsigned char'. The default is `%u'. This format
+ * is used only if the `ascii' field is zero.
+ *
+ * fmt_short: The printf() format to use when rendering data which is
+ * typed `short'. The default is `%d'.
+ *
+ * fmt_ushort: The printf() format to use when rendering data which is
+ * typed `unsigned short'. The default is `%u'.
+ *
+ * fmt_long: The printf() format to use when rendering data which is
+ * typed `long'. The default is `%ld'.
+ *
+ * fmt_ulong: The printf() format to use when rendering data which is
+ * typed `unsigned long'. The default is `%lu'.
+ *
+ * fmt_llong: The printf() format to use when rendering data which is
+ * typed `long long'. The default depends on what printf()
+ * format is available to print this datatype.
+ *
+ * fmt_ullong: The printf() format to use when rendering data which is
+ * typed `unsigned long long'. The default depends on what
+ * printf() format is available to print this datatype.
+ *
+ * fmt_double: The printf() format to use when rendering data which is
+ * typed `double'. The default is `%g'.
+ *
+ * fmt_float: The printf() format to use when rendering data which is
+ * typed `float'. The default is `%g'.
+ *
+ * ascii: If set then print 1-byte integer values as an ASCII
+ * character (no quotes). If the character is one of the
+ * standard C escapes then print the escaped version. If
+ * the character is unprintable then print a 3-digit octal
+ * escape. If `ascii' is zero then then 1-byte integers are
+ * printed as numeric values. The default is zero.
+ *
+ * str_locale: Determines how strings are printed. If zero then strings
+ * are printed like in C except. If set to ESCAPE_HTML then
+ * strings are printed using HTML encoding where each
+ * character not in the class [a-zA-Z0-9] is substituted
+ * with `%XX' where `X' is a hexadecimal digit.
+ *
+ * str_repeat: If set to non-zero then any character value repeated N
+ * or more times is printed as 'C'*N
+ *
+ * Numeric data is also subject to the formats for individual elements.
+ */
+ hbool_t raw;
+ const char *fmt_raw;
+ const char *fmt_int;
+ const char *fmt_uint;
+ const char *fmt_schar;
+ const char *fmt_uchar;
+ const char *fmt_short;
+ const char *fmt_ushort;
+ const char *fmt_long;
+ const char *fmt_ulong;
+ const char *fmt_llong;
+ const char *fmt_ullong;
+ const char *fmt_double;
+ const char *fmt_float;
+ int ascii;
+ int str_locale;
+ int str_repeat;
+
+ /*
+ * 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 ",\001" ("\001" indicates an optional line
+ * break).
+ *
+ * suf: A string to print at the end of each array. The default
+ * value is a right square bracket `]'.
+ *
+ * linebreaks: a boolean value to determine if we want to break the line
+ * after each row of an array.
+ */
+ const char *arr_pre;
+ const char *arr_sep;
+ const char *arr_suf;
+ int arr_linebreak;
+
+ /*
+ * 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 ", \001" (the \001 indicates an optional
+ * line break to allow structs to span multiple lines of
+ * output).
+ *
+ * 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 right curly brace.
+ *
+ * end: a string to print after we reach the last element of
+ * each compound type. prints out before the suf.
+ */
+ const char *cmpd_name;
+ const char *cmpd_sep;
+ const char *cmpd_pre;
+ const char *cmpd_suf;
+ const char *cmpd_end;
+
+ /*
+ * Fields associated with vlen data types.
+ *
+ * sep: A string that separates one member from another. The
+ * default is ", \001" (the \001 indicates an optional
+ * line break to allow structs to span multiple lines of
+ * output).
+ *
+ * pre: A string to print at the beginning of a vlen type.
+ * The default is a left parentheses.
+ *
+ * suf: A string to print at the end of each vlen type. The
+ * default is a right parentheses.
+ *
+ * end: a string to print after we reach the last element of
+ * each compound type. prints out before the suf.
+ */
+ const char *vlen_sep;
+ const char *vlen_pre;
+ const char *vlen_suf;
+ const char *vlen_end;
+
+ /*
+ * 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.
+ *
+ * per_line: If this field has a positive value then every Nth element
+ * will be printed at the beginning of a line.
+ *
+ * pre: Each line of output contains an optional prefix area
+ * before the data. This area can contain the index for the
+ * first datum (represented by `%s') as well as other
+ * constant text. The default value is `%s'.
+ *
+ * 1st: This is the format to print at the beginning of the first
+ * line of output. The default value is the current value of
+ * `pre' described above.
+ *
+ * cont: This is the format to print at the beginning of each line
+ * which was continued because the line was split onto
+ * multiple lines. This often happens with compound
+ * data which is longer than one line of output. The default
+ * value is the current value of the `pre' field
+ * described above.
+ *
+ * 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.
+ *
+ * multi_new: Indicates the algorithm to use when data elements tend to
+ * occupy more than one line of output. The possible values
+ * are (zero is the default):
+ *
+ * 0: No consideration. Each new element is printed
+ * beginning where the previous element ended.
+ *
+ * 1: Print the current element beginning where the
+ * previous element left off. But if that would result
+ * in the element occupying more than one line and it
+ * would only occupy one line if it started at the
+ * beginning of a line, then it is printed at the
+ * beginning of the next line.
+ *
+ * multi_new: If an element is continued onto additional lines then
+ * should the following element begin on the next line? The
+ * default is to start the next element on the same line
+ * unless it wouldn't fit.
+ *
+ * indentlevel: a string that shows how far to indent if extra spacing
+ * is needed. dumper uses it.
+ */
+ int line_ncols; /*columns of output */
+ size_t line_per_line; /*max elements per line */
+ const char *line_pre; /*prefix at front of each line */
+ const char *line_1st; /*alternate pre. on first line */
+ const char *line_cont; /*alternate pre. on continuation*/
+ const char *line_suf; /*string to append to each line */
+ const char *line_sep; /*separates lines */
+ int line_multi_new; /*split multi-line outputs? */
+ const char *line_indent; /*for extra identation if we need it*/
+
+ /*used to skip the first set of checks for line length*/
+ int skip_first;
+
+ /*flag used to hide or show the file number for obj refs*/
+ int obj_hidefileno;
+
+ /*string used to format the output for the obje refs*/
+ const char *obj_format;
+
+ /*flag used to hide or show the file number for dataset regions*/
+ int dset_hidefileno;
+
+ /*string used to format the output for the dataset regions*/
+ const char *dset_format;
+
+ const char *dset_blockformat_pre;
+ const char *dset_ptformat_pre;
+ const char *dset_ptformat;
+
+} h5dump_t;
+
+
+typedef struct dump_header{
+ const char *name;
+ const char *filebegin;
+ const char *fileend;
+ const char *bootblockbegin;
+ const char *bootblockend;
+ const char *groupbegin;
+ const char *groupend;
+ const char *datasetbegin;
+ const char *datasetend;
+ const char *attributebegin;
+ const char *attributeend;
+ const char *datatypebegin;
+ const char *datatypeend;
+ const char *dataspacebegin;
+ const char *dataspaceend;
+ const char *databegin;
+ const char *dataend;
+ const char *softlinkbegin;
+ const char *softlinkend;
+
+ const char *fileblockbegin;
+ const char *fileblockend;
+ const char *bootblockblockbegin;
+ const char *bootblockblockend;
+ const char *groupblockbegin;
+ const char *groupblockend;
+ const char *datasetblockbegin;
+ const char *datasetblockend;
+ const char *attributeblockbegin;
+ const char *attributeblockend;
+ const char *datatypeblockbegin;
+ const char *datatypeblockend;
+ const char *dataspaceblockbegin;
+ const char *dataspaceblockend;
+ const char *datablockbegin;
+ const char *datablockend;
+ const char *softlinkblockbegin;
+ const char *softlinkblockend;
+ const char *strblockbegin;
+ const char *strblockend;
+ const char *enumblockbegin;
+ const char *enumblockend;
+ const char *structblockbegin;
+ const char *structblockend;
+ const char *vlenblockbegin;
+ const char *vlenblockend;
+
+ const char *dataspacedescriptionbegin;
+ const char *dataspacedescriptionend;
+ const char *dataspacedimbegin;
+ const char *dataspacedimend;
+
+} dump_header;
+
+/*
+ * begin get_option section
+ */
+extern int opt_err; /* getoption prints errors if this is on */
+extern int opt_ind; /* token pointer */
+extern const char *opt_arg; /* flag argument (or value) */
+
+enum {
+ no_arg = 0, /* doesn't take an argument */
+ require_arg, /* requires an argument */
+ optional_arg /* argument is optional */
+};
+
+/*
+ * get_option determines which options are specified on the command line and
+ * returns a pointer to any arguments possibly associated with the option in
+ * the ``opt_arg'' variable. get_option returns the shortname equivalent of
+ * the option. The long options are specified in the following way:
+ *
+ * struct long_options foo[] = {
+ * { "filename", require_arg, 'f' },
+ * { "append", no_arg, 'a' },
+ * { "width", require_arg, 'w' },
+ * { NULL, 0, 0 }
+ * };
+ *
+ * Long named options can have arguments specified as either:
+ *
+ * ``--param=arg'' or ``--param arg''
+ *
+ * Short named options can have arguments specified as either:
+ *
+ * ``-w80'' or ``-w 80''
+ *
+ * and can have more than one short named option specified at one time:
+ *
+ * -aw80
+ *
+ * in which case those options which expect an argument need to come at the
+ * end.
+ */
+typedef struct long_options {
+ const char *name; /* name of the long option */
+ int has_arg; /* whether we should look for an arg */
+ char shortval; /* the shortname equivalent of long arg
+ * this gets returned from get_option */
+} long_options;
+
+extern int get_option(int argc, const char **argv, const char *opt,
+ const struct long_options *l_opt);
+/*
+ * end get_option section
+ */
+
+extern hid_t h5dump_fixtype(hid_t f_type);
+extern int h5dump_dset(FILE *stream, const h5dump_t *info, hid_t dset,
+ hid_t p_typ, int indentlevel);
+extern int h5dump_mem(FILE *stream, const h5dump_t *info, hid_t obj_id,
+ hid_t type, hid_t space, void *mem, int indentlevel);
+extern hid_t h5dump_fopen(const char *fname, char *drivername, size_t drivername_len);
+
+
+/*if we get a new program that needs to use the library add its name here*/
+typedef enum {
+ UNKNOWN = 0,
+ H5LS,
+ H5DUMP
+} ProgType;
+
+/*struct taken from the dumper. needed in table struct*/
+typedef struct obj_t {
+ unsigned long objno[2];
+ char objname[1024];
+ int displayed;
+ int recorded;
+ int objflag;
+} obj_t;
+
+/*struct for the tables that the find_objs function uses*/
+typedef struct table_t {
+ int size;
+ int nobjs;
+ obj_t *objs;
+} table_t;
+
+/*this struct stores the information that is passed to the find_objs function*/
+typedef struct find_objs_t {
+ int prefix_len;
+ char *prefix;
+ unsigned int threshold; /* should be 0 or 1 */
+ table_t *group_table;
+ table_t *type_table;
+ table_t *dset_table;
+ int status;
+} find_objs_t;
+
+extern herr_t find_objs(hid_t group, const char *name, void *op_data);
+extern int search_obj (table_t *temp, unsigned long *);
+extern void init_table(table_t **temp);
+extern void init_prefix(char **temp, int);
+
+/* taken from h5dump.h */
+#define ATTRIBUTE_DATA 0
+#define DATASET_DATA 1
+#define ENUM_DATA 2
+
+#define COL 3
+
+extern int indent; /*how far in to indent the line */
+extern int nCols; /*max number of columns for outputting */
+extern FILE *rawdatastream; /*output stream for raw data */
+
+extern void indentation(int);
+
+/* taken from h5dump.h*/
+#define BOOT_BLOCK "BOOT_BLOCK"
+#define GROUPNAME "GROUP"
+#define DATASET "DATASET"
+#define ATTRIBUTE "ATTRIBUTE"
+#define DATATYPE "DATATYPE"
+#define DATASPACE "DATASPACE"
+#define DATA "DATA"
+#define SCALAR "SCALAR"
+#define SIMPLE "SIMPLE"
+#define COMPLEX "COMPLEX"
+#define STORAGELAYOUT "STORAGELAYOUT"
+#define COMPRESSION "COMPRESSION"
+#define EXTERNAL "EXTERNAL"
+#define SOFTLINK "SOFTLINK"
+#define HARDLINK "HARDLINK"
+#define NLINK "NLINK"
+#define FILENO "FILENO"
+#define OBJNO "OBJNO"
+#define STRSIZE "STRSIZE"
+#define STRPAD "STRPAD"
+#define CSET "CSET"
+#define CTYPE "CTYPE"
+#define CONCATENATOR "//"
+#define DATASET "DATASET"
+#define OBJID "OBJECTID"
+#define BEGIN "{"
+#define END "}"
+
+/* Definitions of useful routines */
+extern void print_version(const char *progname);
+extern void h5tools_init(void);
+extern void h5tools_close(void);
+extern void error_msg(const char *progname, const char *fmt, ...);
+extern void warn_msg(const char *progname, const char *fmt, ...);
+
+#endif /* H5TOOLS_H__ */
diff --git a/tools/lib/h5tools_str.c b/tools/lib/h5tools_str.c
new file mode 100644
index 0000000..6fd6f85
--- /dev/null
+++ b/tools/lib/h5tools_str.c
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2001 National Center for Supercomputing Applications
+ * All rights reserved.
+ *
+ * Programmer: Bill Wendling <wendling@ncsa.uiuc.edu>
+ * Monday, 19. February 2001
+ *
+ * Purpose: These are string functions for us to use and abuse.
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "h5tools.h" /*for h5dump_t structure */
+#include "h5tools_str.h" /*function prototypes */
+
+/* Variable length string datatype */
+#define STR_INIT_LEN 4096 /*initial length */
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_close
+ *
+ * Purpose: Closes a string by releasing it's memory and setting the size
+ * information to zero.
+ *
+ * Return: void
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+void
+h5tools_str_close(h5tools_str_t *str)
+{
+ if (str && str->nalloc) {
+ free(str->s);
+ memset(str, 0, sizeof(h5tools_str_t));
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_len
+ *
+ * Purpose: Returns the length of the string, not counting the null
+ * terminator.
+ *
+ * Return: Success: Length of string
+ *
+ * Failure: 0
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+size_t
+h5tools_str_len(h5tools_str_t *str)
+{
+ return str->len;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_append
+ *
+ * Purpose: Formats variable arguments according to printf() format
+ * string and appends the result to variable length string STR.
+ *
+ * Return: Success: Pointer to buffer containing result.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+h5tools_str_append(h5tools_str_t *str/*in,out*/, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ /* Make sure we have some memory into which to print */
+ if (!str->s || str->nalloc <= 0) {
+ str->nalloc = STR_INIT_LEN;
+ str->s = malloc(str->nalloc);
+ assert(str->s);
+ str->s[0] = '\0';
+ str->len = 0;
+ }
+
+ while (1) {
+ size_t avail = str->nalloc - str->len;
+ size_t nchars = (size_t)vsnprintf(str->s + str->len, avail, fmt, ap);
+
+ if (nchars < avail) {
+ /* success */
+ str->len += nchars;
+ break;
+ }
+
+ /* Try again with twice as much space */
+ str->nalloc *= 2;
+ str->s = realloc(str->s, str->nalloc);
+ assert(str->s);
+ }
+
+ va_end(ap);
+ return str->s;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_reset
+ *
+ * Purpose: Reset the string to the empty value. If no memory is
+ * allocated yet then initialize the h5tools_str_t struct.
+ *
+ * Return: Success: Ptr to the buffer which contains a null
+ * character as the first element.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+h5tools_str_reset(h5tools_str_t *str/*in,out*/)
+{
+ if (!str->s || str->nalloc <= 0) {
+ str->nalloc = STR_INIT_LEN;
+ str->s = malloc(str->nalloc);
+ assert(str->s);
+ }
+
+ str->s[0] = '\0';
+ str->len = 0;
+ return str->s;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_trunc
+ *
+ * Purpose: Truncate a string to be at most SIZE characters.
+ *
+ * Return: Success: Pointer to the string
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+h5tools_str_trunc(h5tools_str_t *str/*in,out*/, size_t size)
+{
+ if (size < str->len) {
+ str->len = size;
+ str->s[size] = '\0';
+ }
+
+ return str->s;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_str_fmt
+ *
+ * Purpose: Reformat a string contents beginning at character START
+ * according to printf format FMT. FMT should contain no format
+ * specifiers except possibly the `%s' variety. For example, if
+ * the input string is `hello' and the format is "<<%s>>" then
+ * the output value will be "<<hello>>".
+ *
+ * Return: Success: A pointer to the resulting string.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Monday, April 26, 1999
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+h5tools_str_fmt(h5tools_str_t *str/*in,out*/, size_t start, const char *fmt)
+{
+ char _temp[1024], *temp = _temp;
+
+ /* If the format string is simply "%s" then don't bother doing anything */
+ if (!strcmp(fmt, "%s"))
+ return str->s;
+
+ /*
+ * Save the input value if there is a `%' anywhere in FMT. Otherwise
+ * don't bother because we don't need a temporary copy.
+ */
+ if (strchr(fmt, '%')) {
+ if (str->len - start + 1 > sizeof(_temp)) {
+ temp = malloc(str->len-start + 1);
+ assert(temp);
+ }
+
+ strcpy(temp, str->s + start);
+ }
+
+ /* Reset the output string and append a formatted version */
+ h5tools_str_trunc(str, start);
+ h5tools_str_append(str, fmt, temp);
+
+ /* Free the temp buffer if we allocated one */
+ if (temp != _temp)
+ free(temp);
+
+ return str->s;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: h5tools_prefix
+ *
+ * Purpose: Renders the line prefix value into string STR.
+ *
+ * Return: Success: Pointer to the prefix.
+ *
+ * Failure: NULL
+ *
+ * Programmer: Robb Matzke
+ * Thursday, July 23, 1998
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+h5tools_str_prefix(h5tools_str_t *str/*in,out*/, const h5dump_t *info,
+ hsize_t elmtno, int ndims, hsize_t min_idx[],
+ hsize_t max_idx[])
+{
+ hsize_t p_prod[H5S_MAX_RANK], p_idx[H5S_MAX_RANK];
+ hsize_t n, i = 0;
+
+ h5tools_str_reset(str);
+
+ if (ndims > 0) {
+ /*
+ * 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 */
+ for (i = 0; i < (hsize_t)ndims; i++) {
+ if (i)
+ h5tools_str_append(str, "%s", OPT(info->idx_sep, ","));
+
+ h5tools_str_append(str, OPT(info->idx_n_fmt, "%lu"),
+ (unsigned long)p_idx[i]);
+ }
+ } else {
+ /* Scalar */
+ h5tools_str_append(str, OPT(info->idx_n_fmt, "%lu"), (unsigned long)0);
+ }
+
+ /* Add prefix and suffix to the index */
+ return h5tools_str_fmt(str, 0, OPT(info->idx_fmt, "%s: "));
+}
diff --git a/tools/lib/h5tools_str.h b/tools/lib/h5tools_str.h
new file mode 100644
index 0000000..89c3322
--- /dev/null
+++ b/tools/lib/h5tools_str.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001 National Center for Supercomputing Applications
+ * All rights reserved.
+ *
+ * Programmer: Bill Wendling <wendling@ncsa.uiuc.edu>
+ * Monday, 19. February 2001
+ */
+#ifndef H5TOOLS_STR_H__
+#define H5TOOLS_STR_H__
+
+typedef struct h5tools_str_t {
+ char *s; /*allocate string */
+ size_t len; /*length of actual value */
+ size_t nalloc; /*allocated size of string */
+} h5tools_str_t;
+
+extern void h5tools_str_close(h5tools_str_t *str);
+extern size_t h5tools_str_len(h5tools_str_t *str);
+extern char *h5tools_str_append(h5tools_str_t *str, const char *fmt, ...);
+extern char *h5tools_str_reset(h5tools_str_t *str);
+extern char *h5tools_str_trunc(h5tools_str_t *str, size_t size);
+extern char *h5tools_str_fmt(h5tools_str_t *str, size_t start, const char *fmt);
+extern char *h5tools_str_prefix(h5tools_str_t *str, const h5dump_t *info,
+ hsize_t elmtno, int ndims, hsize_t min_idx[],
+ hsize_t max_idx[]);
+
+#endif /* H5TOOLS_STR_H__ */