diff options
-rw-r--r-- | tools/h5dump.c | 775 | ||||
-rw-r--r-- | tools/h5tools.c | 192 | ||||
-rw-r--r-- | tools/h5tools.h | 127 | ||||
-rwxr-xr-x | tools/testh5dump.sh | 16 |
4 files changed, 701 insertions, 409 deletions
diff --git a/tools/h5dump.c b/tools/h5dump.c index f984102..b8440a9 100644 --- a/tools/h5dump.c +++ b/tools/h5dump.c @@ -1,38 +1,29 @@ /*------------------------------------------------------------------------- * - * Copyright (C) 1998 National Center for Supercomputing Applications. - * All rights reserved. + * Copyright (C) 1998, 1999, 2000, 2001 + * National Center for Supercomputing Applications + * All rights reserved. * *------------------------------------------------------------------------- */ #include <stdio.h> +#include <stdlib.h> #include "h5dump.h" #include "H5private.h" #include "h5tools.h" -static int display_oid = 0; -static int display_data = 1; -static int d_status = 0; -static int unamedtype = 0; /* shared data type with no name */ +/* module-scoped global variables */ +static int display_oid; +static int display_data = 1; +static int d_status; +static int unamedtype; /* shared data type with no name */ +static int prefix_len = 1024; -static int prefix_len = 1024; -static table_t *group_table = NULL, *dset_table = NULL, *type_table = NULL; -static char *prefix; +static table_t *group_table, *dset_table, *type_table; +static char *prefix; static const dump_header *dump_header_format; -/* internal functions */ -static void dump_group(hid_t , const char* ); -static void dump_dataset(hid_t, const char*); -static void dump_data(hid_t, int); -static void dump_named_datatype(hid_t , const char *); -static void dump_oid(hid_t oid); -static void print_enum(hid_t type); - -/* external functions */ -extern void indentation(int); -extern int print_data(hid_t, hid_t, int); - static h5dump_t dataformat = { 0, /*raw*/ @@ -209,6 +200,17 @@ static const dump_header xmlformat = { ")", /*dataspacedimend*/ }; +/* internal functions */ +static void dump_group(hid_t , const char* ); +static void dump_dataset(hid_t, const char*); +static void dump_data(hid_t, int); +static void dump_named_datatype(hid_t , const char *); +static void dump_oid(hid_t oid); +static void print_enum(hid_t type); + +/* external functions */ +extern int print_data(hid_t, hid_t, int); + /*------------------------------------------------------------------------- * Function: usage * @@ -220,38 +222,38 @@ static const dump_header xmlformat = { * * Modifications: * - *-----------------------------------------------------------------------*/ + *------------------------------------------------------------------------- + */ static void -usage(void) +usage(const char *progname) { - fprintf(stderr, "\n\ -Usage of HDF5 Dumper:\n\ -\n\ -h5dump [-h] [-bb] [-header] [-v] [-V] [-a <names>] [-d <names>] [-g <names>]\n\ - [-l <names>] [-o <fname>] [-t <names>] [-w <number>] <file>\n\ -\n\ - -h Print information on this command and exit.\n\ - -bb Display the conent of the boot block. [Default: don't display]\n\ - -header Display header only; no data is displayed.\n\ - -v Display the object ids\n\ - -V Display version information and exit.\n\ - -a <path> Display the specified attribute(s).\n\ - -d <path> Display the specified dataset(s).\n\ - -g <path> Display the specified group(s) and all the members.\n\ - -l <path> Display the value(s) of the specified soft link(s).\n\ - -t <names> Display the specified named data type(s).\n\ - -w <number> Display the information with the specified maximum number of columns.\n\ - -o <fname> Output the raw data of datasets to a separate file <fname>.\n\ + fprintf(stderr, "\ +usage: %s [OPTIONS] file\n\ + OPTIONS\n\ + -h, --help Print a usage message and exit\n\ + -B, --bootblock Print the content of the boot block\n\ + -H, --header Print the header only; no data is displayed\n\ + -i, --object-ids Print the object ids\n\ + -V, --version Print version number and exit\n\ + -a P, --attribute=P Print the specified attribute\n\ + -d P, --dataset=P Print the specified dataset\n\ + -g P, --group=P Print the specified group and all members\n\ + -l P, --soft-link=P Print the value(s) of the specified soft link\n\ + -o F, --output=F Output raw data into file F\n\ + -t T, --datatype=T Print the specified named data type\n\ + -w #, --width=# Set the number of columns of output\n\ \n\ - <number> is an integer greater than 1.\n\ - <path> is the full path from the root group to the object.\n\ + P - is the full path from the root group to the object.\n\ + T - is the name of the data type.\n\ + F - is a filename.\n\ + # - is an integer greater than 1.\n\ \n\ Example:\n\ \n\ Attribute foo of the group /bar_none in file quux.h5\n\ \n\ h5dump -a /bar_none/foo quux.h5\n\ -\n"); +\n", progname); } /*------------------------------------------------------------------------- @@ -899,7 +901,7 @@ dump_all(hid_t group, const char *name, void UNUSED *op_data) int i; H5Gget_objinfo(group, name, FALSE, &statbuf); - tmp = (char *)malloc(strlen(prefix) + strlen(name) + 2); + tmp = malloc(strlen(prefix) + strlen(name) + 2); strcpy(tmp, prefix); switch (statbuf.type) { @@ -942,7 +944,7 @@ dump_all(hid_t group, const char *name, void UNUSED *op_data) H5Gget_objinfo(obj, ".", TRUE, &statbuf); if (statbuf.nlink > 1) { - i = search_obj (dset_table, statbuf.objno); + i = search_obj(dset_table, statbuf.objno); if (i < 0) { indentation(indent); @@ -1086,7 +1088,7 @@ dump_group(hid_t gid, const char *name) H5Gget_objinfo(gid, ".", TRUE, &statbuf); if (statbuf.nlink > 1) { - i = search_obj (group_table, statbuf.objno); + i = search_obj(group_table, statbuf.objno); if (i < 0) { indentation(indent); @@ -1327,6 +1329,261 @@ set_output_file(const char *fname) return -1; } +static void +handle_attributes(hid_t fid, const char *attr) +{ + dump_selected_attr(fid, attr); +} + +static void +handle_datasets(hid_t fid, const char *dset) +{ + H5G_stat_t statbuf; + hid_t dsetid; + + if ((dsetid = H5Dopen(fid, dset)) < 0) { + begin_obj(dump_header_format->datasetbegin, dset, + dump_header_format->datasetblockbegin); + indentation(COL); + fprintf(stdout, "h5dump error: unable to open %s\n", dset); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + d_status = 1; + } else { + H5Gget_objinfo(dsetid, ".", TRUE, &statbuf); + + if (statbuf.nlink > 1) { + int index = search_obj(dset_table, statbuf.objno); + + if (index >= 0) { + if (dset_table->objs[index].displayed) { + begin_obj(dump_header_format->datasetbegin, dset, + dump_header_format->datasetblockbegin); + indentation(indent + COL); + printf("%s \"%s\"\n", HARDLINK, + dset_table->objs[index].objname); + indentation(indent); + end_obj(dump_header_format->datasetend, + dump_header_format->datasetblockend); + } else { + strcpy(dset_table->objs[index].objname, dset); + dset_table->objs[index].displayed = 1; + dump_dataset(dsetid, dset); + } + } else { + d_status = 1; + } + } else { + dump_dataset(dsetid, dset); + } + + if (H5Dclose(dsetid) < 1) + d_status = 1; + } +} + +static void +handle_groups(hid_t fid, const char *group) +{ + H5G_stat_t statbuf; + hid_t gid; + + if ((gid = H5Gopen(fid, group)) < 0) { + begin_obj(dump_header_format->groupbegin, group, + dump_header_format->groupblockbegin); + indentation(COL); + fprintf(stdout, "h5dump error: unable to open %s\n", group); + end_obj(dump_header_format->groupend, + dump_header_format->groupblockend); + d_status = 1; + } else { + H5Gget_objinfo(gid, ".", TRUE, &statbuf); + strcpy(prefix, group); + dump_group(gid, group); + + if (H5Gclose(gid) < 0) + d_status = 1; + } +} + +static void +handle_links(hid_t fid, const char *link) +{ + H5G_stat_t statbuf; + + if (H5Gget_objinfo(fid, link, FALSE, &statbuf) < 0) { + begin_obj(dump_header_format->softlinkbegin, link, + dump_header_format->softlinkblockbegin); + indentation(COL); + fprintf(stdout, "h5dump error: unable to get obj info from %s\n", link); + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + d_status = 1; + } else if (statbuf.type == H5G_LINK) { + char *buf = malloc(statbuf.linklen*sizeof(char)); + + begin_obj(dump_header_format->softlinkbegin, link, + dump_header_format->softlinkblockbegin); + indentation(COL); + + if (H5Gget_linkval(fid, link, statbuf.linklen, buf) >= 0) { + printf("LINKTARGET \"%s\"\n", buf); + } else { + fprintf(stdout, "h5dump error: unable to get link value\n"); + d_status = 1; + } + + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + free(buf); + } else { + begin_obj(dump_header_format->softlinkbegin, link, + dump_header_format->softlinkblockbegin); + indentation(COL); + fprintf(stdout, "h5dump error: %s is not a link\n", link); + end_obj(dump_header_format->softlinkend, + dump_header_format->softlinkblockend); + d_status = 1; + } +} + +static void +handle_datatypes(hid_t fid, const char *type) +{ + hid_t typeid; + + if ((typeid = H5Topen(fid, type)) < 0) { + /* check if type is unamed data type */ + int index = 0; + + while (index < type_table->nobjs ) { + char name[128], name1[128]; + + if (!type_table->objs[index].recorded) { + /* unamed data type */ + sprintf(name, "#%lu:%lu\n", + type_table->objs[index].objno[0], + type_table->objs[index].objno[1]); + sprintf(name1, "/#%lu:%lu\n", + type_table->objs[index].objno[0], + type_table->objs[index].objno[1]); + + if (!strncmp(name, type, strlen(type)) || + !strncmp(name1, type, strlen(type))) + break; + } + + index++; + } + + if (index == type_table->nobjs) { + /* unknown type */ + begin_obj(dump_header_format->datatypebegin, type, + dump_header_format->datatypeblockbegin); + indentation(COL); + fprintf(stdout, "h5dump error: unable to open %s\n", type); + end_obj(dump_header_format->datatypeend, + dump_header_format->datatypeblockend); + d_status = 1; + } else { + hid_t dsetid = H5Dopen(fid, type_table->objs[index].objname); + typeid = H5Dget_type(dsetid); + dump_named_datatype(typeid, type); + H5Tclose(typeid); + H5Dclose(dsetid); + } + } else { + dump_named_datatype(typeid, type); + + if (H5Tclose(typeid) < 0) + d_status = 1; + } +} + +/* + * Command-line options: The user can specify short or long-named + * parameters. The long-named ones can be partially spelled. When + * adding more, make sure that they don't clash with each other. + */ +static const char *s_opts = "hBHvVa:d:g:l:t:w:xD:o:"; +static struct long_options l_opts[] = { + { "help", no_arg, 'h' }, + { "hel", no_arg, 'h' }, + { "boot-block", no_arg, 'B' }, + { "boot-bloc", no_arg, 'B' }, + { "boot-blo", no_arg, 'B' }, + { "boot-bl", no_arg, 'B' }, + { "boot-b", no_arg, 'B' }, + { "boot", no_arg, 'B' }, + { "boo", no_arg, 'B' }, + { "bo", no_arg, 'B' }, + { "header", no_arg, 'H' }, + { "heade", no_arg, 'H' }, + { "head", no_arg, 'H' }, + { "hea", no_arg, 'H' }, + { "he", no_arg, 'H' }, + { "object-ids", no_arg, 'i' }, + { "object-id", no_arg, 'i' }, + { "object-i", no_arg, 'i' }, + { "object", no_arg, 'i' }, + { "objec", no_arg, 'i' }, + { "obje", no_arg, 'i' }, + { "obj", no_arg, 'i' }, + { "ob", no_arg, 'i' }, + { "version", no_arg, 'V' }, + { "versio", no_arg, 'V' }, + { "versi", no_arg, 'V' }, + { "vers", no_arg, 'V' }, + { "ver", no_arg, 'V' }, + { "ve", no_arg, 'V' }, + { "attribute", require_arg, 'a' }, + { "attribut", require_arg, 'a' }, + { "attribu", require_arg, 'a' }, + { "attrib", require_arg, 'a' }, + { "attri", require_arg, 'a' }, + { "attr", require_arg, 'a' }, + { "att", require_arg, 'a' }, + { "at", require_arg, 'a' }, + { "dataset", require_arg, 'd' }, + { "datase", require_arg, 'd' }, + { "datas", require_arg, 'd' }, + { "group", require_arg, 'g' }, + { "grou", require_arg, 'g' }, + { "gro", require_arg, 'g' }, + { "gr", require_arg, 'g' }, + { "soft-link", require_arg, 'l' }, + { "soft-lin", require_arg, 'l' }, + { "soft-li", require_arg, 'l' }, + { "soft-l", require_arg, 'l' }, + { "soft", require_arg, 'l' }, + { "sof", require_arg, 'l' }, + { "so", require_arg, 'l' }, + { "datatype", require_arg, 't' }, + { "datatyp", require_arg, 't' }, + { "dataty", require_arg, 't' }, + { "datat", require_arg, 't' }, + { "width", require_arg, 'w' }, + { "widt", require_arg, 'w' }, + { "wid", require_arg, 'w' }, + { "wi", require_arg, 'w' }, + { "xml", no_arg, 'x' }, + { "xm", no_arg, 'x' }, + { "xml-dtd", require_arg, 'D' }, + { "xml-dt", require_arg, 'D' }, + { "xml-d", require_arg, 'D' }, + { "output", require_arg, 'o' }, + { "outpu", require_arg, 'o' }, + { "outp", require_arg, 'o' }, + { "out", require_arg, 'o' }, + { "ou", require_arg, 'o' }, + { NULL, 0, '\0' } +}; + +struct handler_t { + void (*func)(hid_t, const char *); + const char *obj; +}; + /*------------------------------------------------------------------------- * Function: main * @@ -1341,23 +1598,24 @@ set_output_file(const char *fname) * Albert Cheng, 2000/09/30 * Add the -o option--output file for datasets raw data * - *-----------------------------------------------------------------------*/ + *------------------------------------------------------------------------- + */ int -main(int argc, char *argv[]) +main(int argc, const char *argv[]) { - hid_t fid, gid, dsetid, typeid; - char *fname = NULL; - int i, index, curr_arg, display_bb=0, display_all=1, newwidth= 0; - int nopts=0, *opts; - char *buf, name[128], name1[128]; - H5G_stat_t statbuf; - void *edata; - hid_t (*func)(void*); - find_objs_t *info = malloc(sizeof(find_objs_t)); + hid_t fid, gid; + const char *progname = "h5dump"; + char *fname = NULL; + int i, display_bb = 0, display_all = 1, newwidth = 0; + void *edata; + hid_t (*func)(void*); + find_objs_t info; + int opt; + struct handler_t *hand; if (argc < 2) { - usage(); - exit(1); + usage(progname); + exit(EXIT_FAILURE); } dump_header_format = &standardformat; @@ -1369,112 +1627,109 @@ main(int argc, char *argv[]) /* Initialize h5tools lib */ h5tools_init(); - opts = malloc((argc / 2) * sizeof(int)); - opts[0] = -1; + /* this will be plenty big enough for holding the info */ + hand = calloc(argc, sizeof(struct handler_t)); /* parse command line options */ - for (curr_arg = 1; curr_arg < argc; curr_arg++) { - if (argv[curr_arg][0] == '-') { - opts[nopts++] = curr_arg; - - if (!strcmp(argv[curr_arg],"-h")) { - usage(); - free(opts); - exit(0); - } else if (!strcmp(argv[curr_arg],"-V")) { - print_version("h5dump"); - free(opts); - exit(0); - } else if (!strcmp(argv[curr_arg],"-bb")) { - display_bb = 1; - } else if (!strcmp(argv[curr_arg],"-header")) { - display_data=0; - } else if (!strcmp(argv[curr_arg],"-v")) { - display_oid = 1; - } else if (!strcmp(argv[curr_arg],"-w")) { - /* - * this way we know which arg was the -w we know it won't be 0 - * since curr_arg starts at 1 - */ - newwidth = curr_arg; - } else if (!strcmp(argv[curr_arg], "-o")) { - /* a separate output file for dataset raw data */ - if (argc == curr_arg){ - /* missing <fname> */ - usage(); - free(opts); - exit(1); + while ((opt = get_option(argc, argv, s_opts, l_opts)) != EOF) { + switch ((char)opt) { + case 'B': + display_bb = TRUE; + break; + case 'H': + display_data = FALSE; + break; + case 'v': + display_oid = TRUE; + break; + case 'V': + print_version(progname); + exit(EXIT_SUCCESS); + break; + case 'w': + nCols = atoi(opt_arg); + break; + case 'a': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_attributes; + hand[i].obj = opt_arg; + break; } - if (set_output_file(argv[curr_arg+1]) < 0){ - /* failed to set output file */ - usage(); - free(opts); - exit(1); + break; + case 'd': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datasets; + hand[i].obj = opt_arg; + break; } - } else if (!strcmp(argv[curr_arg], "-xml")) { - dump_header_format = &xmlformat; - } else if (strcmp(argv[curr_arg],"-a") && - strcmp(argv[curr_arg],"-d") && - strcmp(argv[curr_arg],"-g") && - strcmp(argv[curr_arg],"-l") && - strcmp(argv[curr_arg],"-t")) { - fprintf(stderr, "h5dump error: illegal option %s \n", - argv[curr_arg]); - usage(); - free(opts); - exit(1); - } else { - display_all = 0; - } - } - } - /* check names */ - if (argc == 2) { - if (opts[0] == 1) { - /* argv[1] is an option */ - fprintf(stderr, "h5dump error: no <names> or no <file>\n"); - usage(); - free(opts); - exit(1); - } - } else { - for (i = 0; i < nopts-1; i++) { - if (opts[i + 1] - opts[i] == 1) { - if (strcmp(argv[opts[i]], "-bb") && - strcmp(argv[opts[i]], "-header") && - strcmp(argv[opts[i]], "-xml") && - strcmp(argv[opts[i]], "-v")) { - fprintf(stderr, - "h5dump error: no <names> after option %s\n", - argv[opts[i]]); - usage(); - free(opts); - exit(1); + break; + case 'g': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_groups; + hand[i].obj = opt_arg; + break; } - } - } - if (argc - opts[nopts - 1] == 1) { - fprintf(stderr,"h5dump error: no <file>\n"); - usage(); - free(opts); - exit(1); - } + break; + case 'l': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_links; + hand[i].obj = opt_arg; + break; + } - if (argc - opts[nopts - 1] == 2) { - if (strcmp(argv[opts[i]], "-bb") && - strcmp(argv[opts[i]], "-header") && - strcmp(argv[opts[i]], "-xml") && - strcmp(argv[opts[i]], "-v")) { - fprintf(stderr, - "h5dump error: no <file> or no <names> " - "or no <number> after option %s\n", argv[opts[i]]); - usage(); - free(opts); - exit(1); + break; + case 't': + display_all = 0; + + for (i = 0; i < argc; i++) + if (!hand[i].func) { + hand[i].func = handle_datatypes; + hand[i].obj = opt_arg; + break; + } + + break; + case 'o': + if (set_output_file(opt_arg) < 0){ + /* failed to set output file */ + usage(progname); + exit(EXIT_FAILURE); } + break; +#ifdef 0 + case 'x': + /* select XML output */ + doxml = TRUE; + dump_header_format = &xmlformat; + dump_function_table = &xml_function_table; + break; + case 'D': + /* specify alternative XML DTD */ + xml_dtd_uri = strdup(opt_arg); + break; +#endif /* for future XML stuff */ + case 'h': + usage(progname); + exit(EXIT_SUCCESS); + case '?': + default: + usage(progname); + exit(EXIT_FAILURE); } } @@ -1486,10 +1741,9 @@ main(int argc, char *argv[]) fid = h5dump_fopen(fname, NULL, 0); if (fid < 0) { - fprintf(stderr, "h5dump error: unable to open file %s \n", fname); - free(opts); - exit(1); - } + fprintf(stderr, "h5dump error: unable to open file %s\n", fname); + exit(EXIT_FAILURE); + } /* allocate and initialize internal data structure */ init_table(&group_table); @@ -1498,17 +1752,17 @@ main(int argc, char *argv[]) init_prefix(&prefix, prefix_len); /* init the find_objs_t */ - info->threshold = 0; - info->prefix_len = 1024; - info->prefix = malloc(info->prefix_len); - info->prefix[0] = '\0'; - info->group_table = group_table; - info->type_table = type_table; - info->dset_table = dset_table; - info->status = d_status; + info.threshold = 0; + info.prefix_len = prefix_len; + info.prefix = malloc(info.prefix_len); + info.prefix[0] = '\0'; + info.group_table = group_table; + info.type_table = type_table; + info.dset_table = dset_table; + info.status = d_status; /* find all shared objects */ - H5Giterate(fid, "/", NULL, find_objs, (void*)info); + H5Giterate(fid, "/", NULL, find_objs, (void *)&info); strcpy(prefix, ""); /* does there exist unamed committed data type */ @@ -1520,7 +1774,7 @@ main(int argc, char *argv[]) dump_tables(); #endif - if (info->status) { + if (info.status) { printf("internal error! \n"); goto done; } @@ -1541,182 +1795,16 @@ main(int argc, char *argv[]) d_status = 1; } else { dump_group(gid, "/"); - } + } if (H5Gclose (gid) < 0) { fprintf(stdout, "h5dump error: unable to close root group\n"); d_status = 1; } } else { - for (i = 0; i < nopts; i++) { - if (!strcmp(argv[opts[i]],"-a")) { - for (curr_arg = opts[i] + 1; - curr_arg < ((i + 1) == nopts ? (argc - 1) : opts[i + 1]); - curr_arg++) - dump_selected_attr (fid, argv[curr_arg]); - } else if (!strcmp(argv[opts[i]],"-d")) { - for (curr_arg = opts[i] + 1; - curr_arg < ((i + 1) == nopts ? (argc - 1) : opts[i + 1]); - curr_arg++) { - - if ((dsetid = H5Dopen (fid, argv[curr_arg]))<0) { - begin_obj(dump_header_format->datasetbegin, argv[curr_arg], - dump_header_format->datasetblockbegin); - indentation(COL); - fprintf(stdout, "h5dump error: unable to open %s\n", - argv[curr_arg]); - end_obj(dump_header_format->datasetend, - dump_header_format->datasetblockend); - d_status = 1; - } else { - H5Gget_objinfo(dsetid, ".", TRUE, &statbuf); - - if (statbuf.nlink > 1) { - index = search_obj (dset_table, statbuf.objno); - - if (index >= 0) { - if (dset_table->objs[index].displayed) { - begin_obj(dump_header_format->datasetbegin, - argv[curr_arg], - dump_header_format->datasetblockbegin); - indentation(indent + COL); - printf("%s \"%s\"\n", HARDLINK, - dset_table->objs[index].objname); - indentation(indent); - end_obj(dump_header_format->datasetend, - dump_header_format->datasetblockend); - } else { - strcpy(dset_table->objs[index].objname, - argv[curr_arg]); - dset_table->objs[index].displayed = 1; - dump_dataset(dsetid, argv[curr_arg]); - } - } else { - d_status = 1; - } - } else { - dump_dataset(dsetid, argv[curr_arg]); - } - - if (H5Dclose(dsetid) < 1) - d_status = 1; - } - } - } else if (!strcmp(argv[opts[i]],"-g")) { - for (curr_arg = opts[i] + 1; - curr_arg < ((i + 1) == nopts ? (argc - 1) : opts[i + 1]); - curr_arg++) { - if ((gid = H5Gopen(fid, argv[curr_arg])) < 0) { - begin_obj(dump_header_format->groupbegin, argv[curr_arg], - dump_header_format->groupblockbegin); - indentation(COL); - fprintf(stdout, "h5dump error: unable to open %s\n", - argv[curr_arg]); - end_obj(dump_header_format->groupend, - dump_header_format->groupblockend); - d_status = 1; - } else { - H5Gget_objinfo(gid, ".", TRUE, &statbuf); - strcpy(prefix, argv[curr_arg]); - dump_group(gid, argv[curr_arg]); - - if (H5Gclose(gid) < 0) - d_status = 1; - } - } - } else if (!strcmp(argv[opts[i]],"-l")) { - for (curr_arg = opts[i] + 1; - curr_arg < ((i + 1) == nopts ? (argc - 1) : opts[i + 1]); - curr_arg++) { - if (H5Gget_objinfo(fid, argv[curr_arg], FALSE, &statbuf) < 0) { - begin_obj(dump_header_format->softlinkbegin, - argv[curr_arg], - dump_header_format->softlinkblockbegin); - indentation(COL); - fprintf(stdout, "h5dump error: unable to get obj info from %s\n", - argv[curr_arg]); - end_obj(dump_header_format->softlinkend, - dump_header_format->softlinkblockend); - d_status = 1; - } else if (statbuf.type == H5G_LINK) { - buf = malloc(statbuf.linklen*sizeof(char)); - begin_obj(dump_header_format->softlinkbegin, - argv[curr_arg], - dump_header_format->softlinkblockbegin); - indentation(COL); - - if (H5Gget_linkval(fid, argv[curr_arg], statbuf.linklen, buf) >= 0) { - printf("LINKTARGET \"%s\"\n", buf); - } else { - fprintf(stdout, "h5dump error: unable to get link value\n"); - d_status = 1; - } - - end_obj(dump_header_format->softlinkend, - dump_header_format->softlinkblockend); - free(buf); - } else { - begin_obj(dump_header_format->softlinkbegin, - argv[curr_arg], - dump_header_format->softlinkblockbegin); - indentation(COL); - fprintf(stdout, "h5dump error: %s is not a link\n", argv[curr_arg]); - end_obj(dump_header_format->softlinkend, - dump_header_format->softlinkblockend); - d_status = 1; - } - } - } else if (!strcmp(argv[opts[i]],"-t")) { - for (curr_arg = opts[i] + 1; - curr_arg < ((i + 1) == nopts ? (argc - 1) : opts[i + 1]); - curr_arg++) { - if ((typeid = H5Topen(fid, argv[curr_arg])) < 0) { - /* check if argv[curr_arg] is unamed data type */ - index = 0; - - while (index < type_table->nobjs ) { - if (!type_table->objs[index].recorded) { /* unamed data type */ - sprintf(name, "#%lu:%lu\n", - type_table->objs[index].objno[0], - type_table->objs[index].objno[1]); - sprintf(name1, "/#%lu:%lu\n", - type_table->objs[index].objno[0], - type_table->objs[index].objno[1]); - - if (!strncmp(name, argv[curr_arg], strlen(argv[curr_arg])) || - !strncmp(name1, argv[curr_arg], strlen(argv[curr_arg]))) - break; - } - - index++; - } - - if (index == type_table->nobjs) { - /* unknown type */ - begin_obj(dump_header_format->datatypebegin, argv[curr_arg], - dump_header_format->datatypeblockbegin); - indentation(COL); - fprintf(stdout, "h5dump error: unable to open %s\n", - argv[curr_arg]); - end_obj(dump_header_format->datatypeend, - dump_header_format->datatypeblockend); - d_status = 1; - } else { - dsetid = H5Dopen(fid, type_table->objs[index].objname); - typeid = H5Dget_type(dsetid); - dump_named_datatype(typeid, argv[curr_arg]); - H5Tclose(typeid); - H5Dclose(dsetid); - } - } else { - dump_named_datatype(typeid, argv[curr_arg]); - - if (H5Tclose(typeid) < 0) - d_status = 1; - } - } - } - } + for (i = 0; i < argc; i++) + if (hand[i].func) + hand[i].func(fid, hand[i].obj); } end_obj(dump_header_format->fileend, dump_header_format->fileblockend); @@ -1725,17 +1813,16 @@ done: if (H5Fclose(fid) < 0) d_status = 1; + free(hand); + free(group_table->objs); free(dset_table->objs); free(type_table->objs); free(prefix); - free(info->prefix); - free(info); - free(opts); + free(info.prefix); h5tools_close(); H5Eset_auto(func, edata); - return d_status; } diff --git a/tools/h5tools.c b/tools/h5tools.c index 4f92a17..1af7a6b 100644 --- a/tools/h5tools.c +++ b/tools/h5tools.c @@ -1,6 +1,6 @@ /* - * Copyright © 1998 NCSA - * All rights reserved. + * Copyright © 1998, 2001 National Center for Supercomputing Applications + * All rights reserved. * * Programmer: Robb Matzke <matzke@llnl.gov> * Thursday, July 23, 1998 @@ -8,6 +8,12 @@ * 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 <assert.h> #include <ctype.h> #include <stdio.h> @@ -21,15 +27,6 @@ /* taken from h5dumputil.c */ -int indent; -int compound_data; -int nCols = 80; -FILE *rawdatastream; /* should initialize to stdout but gcc moans about it */ - -static int h5tools_init_g = 0; /* if h5tools lib has been initialized */ - -int print_data(hid_t oid, hid_t _p_type, int obj_data); - /* * If REPEAT_VERBOSE is defined then character strings will be printed so * that repeated character sequences like "AAAAAAAAAA" are displayed as @@ -50,21 +47,35 @@ int print_data(hid_t oid, hid_t _p_type, int obj_data); * largest value suitable for your machine (for testing use a small value). */ #if 1 -#define H5DUMP_BUFSIZE (1024 * 1024) +#define H5DUMP_BUFSIZE (1024 * 1024) #else -#define H5DUMP_BUFSIZE (1024) +#define H5DUMP_BUFSIZE (1024) #endif -#define OPT(X,S) ((X) ? (X) : (S)) -#define ALIGN(A,Z) ((((A) + (Z) - 1) / (Z)) * (Z)) -#define START_OF_DATA 0x0001 -#define END_OF_DATA 0x0002 +#define OPT(X,S) ((X) ? (X) : (S)) +#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" +#define OPTIONAL_LINE_BREAK "\001" /* Variable length string datatype */ -#define STR_INIT_LEN 4096 /*initial length */ +#define STR_INIT_LEN 4096 /*initial length */ + +/* 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) */ typedef struct h5dump_str_t { char *s; /*allocate string */ @@ -94,6 +105,7 @@ typedef struct h5dump_context_t { typedef herr_t (*H5G_operator_t)(hid_t, const char*, void*); +extern int print_data(hid_t oid, hid_t _p_type, int obj_data); extern void init_prefix(char **temp, int length); extern void init_table(table_t **table); extern void free_table(table_t **table); @@ -105,6 +117,148 @@ extern int get_tableflag(table_t*, int); extern int set_tableflag(table_t*, int); extern char *get_objectname(table_t*, int); + +/*------------------------------------------------------------------------- + * 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++) { + int 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 * diff --git a/tools/h5tools.h b/tools/h5tools.h index e9638a5..f48c7af 100644 --- a/tools/h5tools.h +++ b/tools/h5tools.h @@ -1,26 +1,28 @@ /* - * Copyright © 1998 NCSA - * All rights reserved. + * Copyright © 1998, 1999, 2000, 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 +#ifndef H5TOOLS_H_ +#define H5TOOLS_H_ #include <hdf5.h> #include <stdio.h> + #if H5_VERS_MAJOR == 1 -#if H5_VERS_MINOR == 2 -#define VERSION12 -#elif H5_VERS_MINOR == 3 -#define VERSION13 -#endif -#endif -#define ESCAPE_HTML 1 +# if H5_VERS_MINOR == 2 +# define VERSION12 +# elif H5_VERS_MINOR == 3 +# define VERSION13 +# endif /* H5_VERS_MINOR == 2 */ +#endif /* H5_VERS_MAJOR = 1 */ +#define ESCAPE_HTML 1 /* * Information about how to format output. @@ -366,23 +368,75 @@ typedef struct dump_header{ } dump_header; -hid_t h5dump_fixtype(hid_t f_type); -int h5dump_dset(FILE *stream, const h5dump_t *info, hid_t dset, hid_t p_typ, - int indentlevel); -int h5dump_mem(FILE *stream, const h5dump_t *info, hid_t obj_id, hid_t type, - hid_t space, void *mem, int indentlevel); -hid_t h5dump_fopen(const char *fname, char *drivername, size_t drivername_len); +/* + * 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[] = { + * { "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, + UNKNOWN = 0, H5LS, H5DUMP } ProgType; - - /*struct taken from the dumper. needed in table struct*/ typedef struct obj_t { unsigned long objno[2]; @@ -392,7 +446,6 @@ typedef struct obj_t { int objflag; } obj_t; - /*struct for the tables that the find_objs function uses*/ typedef struct table_t { int size; @@ -400,8 +453,6 @@ typedef struct table_t { 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; @@ -413,22 +464,22 @@ typedef struct find_objs_t { int status; } find_objs_t; -herr_t find_objs(hid_t group, const char *name, void *op_data); -int search_obj (table_t *temp, unsigned long *); -void init_table(table_t **temp); -void init_prefix(char **temp, int); +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 ATTRIBUTE_DATA 0 #define DATASET_DATA 1 -#define ENUM_DATA 2 +#define ENUM_DATA 2 -#define COL 3 -extern int indent; -extern void indentation(int); -extern int nCols; -extern FILE *rawdatastream; /* output stream for raw data */ +#define COL 3 +extern int indent; +extern void indentation(int); +extern int nCols; +extern FILE *rawdatastream; /* output stream for raw data */ /* taken from h5dump.h*/ #define BOOT_BLOCK "BOOT_BLOCK" @@ -460,8 +511,8 @@ extern FILE *rawdatastream; /* output stream for raw data */ #define END "}" /* Definitions of useful routines */ -void print_version(const char *program_name); -void h5tools_init(void); -void h5tools_close(void); +extern void print_version(const char *program_name); +extern void h5tools_init(void); +extern void h5tools_close(void); -#endif +#endif /* H5TOOLS_H_ */ diff --git a/tools/testh5dump.sh b/tools/testh5dump.sh index 8046a10..f38209e 100755 --- a/tools/testh5dump.sh +++ b/tools/testh5dump.sh @@ -73,19 +73,19 @@ TOOLTEST() # test for displaying groups TOOLTEST tgroup-1.ddl tgroup.h5 # test for displaying the selected groups -TOOLTEST tgroup-2.ddl -g /g2 / /y tgroup.h5 +TOOLTEST tgroup-2.ddl -g /g2 -g / -g /y tgroup.h5 # test for displaying simple space datasets TOOLTEST tdset-1.ddl tdset.h5 # test for displaying selected datasets -TOOLTEST tdset-2.ddl -header -d dset1 /dset2 dset3 tdset.h5 +TOOLTEST tdset-2.ddl -H -d dset1 -d /dset2 --dataset=dset3 tdset.h5 # test for displaying attributes TOOLTEST tattr-1.ddl tattr.h5 # test for displaying the selected attributes of string type and scalar space -TOOLTEST tattr-2.ddl -a attr1 attr4 attr5 tattr.h5 +TOOLTEST tattr-2.ddl -a attr1 --attribute attr4 --attribute=attr5 tattr.h5 # test for header and error messages -TOOLTEST tattr-3.ddl -header -a attr2 attr tattr.h5 +TOOLTEST tattr-3.ddl --header -a attr2 --attribute=attr tattr.h5 # test for displaying soft links TOOLTEST tslink-1.ddl tslink.h5 @@ -94,15 +94,15 @@ TOOLTEST tslink-2.ddl -l slink2 tslink.h5 # tests for hard links TOOLTEST thlink-1.ddl thlink.h5 -TOOLTEST thlink-2.ddl -d /g1/dset2 /dset1 /g1/g1.1/dset3 thlink.h5 -TOOLTEST thlink-3.ddl -d /g1/g1.1/dset3 /g1/dset2 /dset1 thlink.h5 +TOOLTEST thlink-2.ddl -d /g1/dset2 --dataset /dset1 --dataset=/g1/g1.1/dset3 thlink.h5 +TOOLTEST thlink-3.ddl -d /g1/g1.1/dset3 --dataset /g1/dset2 --dataset=/dset1 thlink.h5 TOOLTEST thlink-4.ddl -g /g1 thlink.h5 TOOLTEST thlink-5.ddl -d /dset1 -g /g2 -d /g1/dset2 thlink.h5 # tests for compound data types TOOLTEST tcomp-1.ddl tcompound.h5 # test for named data types -TOOLTEST tcomp-2.ddl -t /type1 /type2 /group1/type3 tcompound.h5 +TOOLTEST tcomp-2.ddl -t /type1 --datatype /type2 --datatype=/group1/type3 tcompound.h5 # test for unamed type TOOLTEST tcomp-3.ddl -t /#5992:0 -g /group2 tcompound.h5 @@ -111,7 +111,7 @@ TOOLTEST tnestcomp-1.ddl tnestedcomp.h5 # test for options TOOLTEST tall-1.ddl tall.h5 -TOOLTEST tall-2.ddl -header -g /g1/g1.1 -a attr2 tall.h5 +TOOLTEST tall-2.ddl --header -g /g1/g1.1 -a attr2 tall.h5 TOOLTEST tall-3.ddl -d /g2/dset2.1 -l /g1/g1.2/g1.2.1/slink tall.h5 # test for loop detection |