/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Programmer: Bill Wendling * Tuesday, 6. March 2001 */ /* * Portions of this work are derived from _Obfuscated C and Other Mysteries_, * by Don Libes, copyright (c) 1993 by John Wiley & Sons, Inc. */ #include #include #include #include #include "h5tools_utils.h" #include "H5private.h" /* global variables */ int nCols = 80; /* ``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) */ /* local functions */ static void add_obj(table_t *table, unsigned long *objno, char *objname); /*------------------------------------------------------------------------- * 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); HDfflush(stdout); #ifdef WIN32 HDfprintf(stdout, "%s error: ", progname); HDvfprintf(stdout, fmt, ap); #else HDfprintf(stderr, "%s error: ", progname); HDvfprintf(stderr, fmt, ap); #endif 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); HDfflush(stdout); #ifdef WIN32 HDfprintf(stdout, "%s warning: ", progname); HDvfprintf(stdout, fmt, ap); #else /* WIN32 */ HDfprintf(stderr, "%s warning: ", progname); HDvfprintf(stderr, fmt, ap); #endif /* WIN32 */ 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 (HDstrcmp(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]; int i; for (i = 0; l_opts && l_opts[i].name; i++) { size_t len = HDstrlen(l_opts[i].name); if (HDstrncmp(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) HDfprintf(stderr, "%s: option required for \"--%s\" flag\n", argv[0], arg); opt_opt = '?'; } } else { if (arg[len] == '=') { if (opt_err) HDfprintf(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) HDfprintf(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) HDfprintf(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) HDfprintf(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: 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 { HDfprintf(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); } /*------------------------------------------------------------------------- * 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 **tbl) { int i; table_t *table = HDmalloc(sizeof(table_t)); table->size = 20; table->nobjs = 0; table->objs = HDmalloc(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; table->objs[i].objname = NULL; } *tbl = table; } /*------------------------------------------------------------------------- * Function: init_prefix * * Purpose: allocate and initialize prefix * * Return: void * * Modifications: * *------------------------------------------------------------------------- */ void init_prefix(char **prefix, size_t prefix_len) { assert(prefix_len > 0); *prefix = HDcalloc(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: Success: an integer, the location of the object * * Failure: FAIL if object is not found * * Programmer: Ruey-Hsia Li * * Modifications: * *------------------------------------------------------------------------- */ int search_obj(table_t *table, unsigned long *objno) { 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 FAIL; } /*------------------------------------------------------------------------- * 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; int i; if (info->threshold > 1) /*will get an infinite loop if greater than 1*/ return FAIL; H5Gget_objinfo(group, name, TRUE, &statbuf); tmp = HDmalloc(HDstrlen(info->prefix) + HDstrlen(name) + 2); HDstrcpy(tmp, info->prefix); switch (statbuf.type) { case H5G_GROUP: if ((obj = H5Gopen(group, name)) >= 0) { if (info->prefix_len < (HDstrlen(info->prefix) + HDstrlen(name) + 2)) { info->prefix_len *= 2; info->prefix = HDrealloc(info->prefix, info->prefix_len * sizeof(char)); } HDstrcat(HDstrcat(info->prefix,"/"), name); if (statbuf.nlink > info->threshold) { if (search_obj(info->group_table, statbuf.objno) == FAIL) { add_obj(info->group_table, statbuf.objno, info->prefix); H5Giterate(obj, ".", NULL, find_objs, (void *)info); } } else { H5Giterate (obj, ".", NULL, find_objs, (void *)info); } HDstrcpy(info->prefix, tmp); H5Gclose (obj); } else { info->status = 1; } break; case H5G_DATASET: HDstrcat(tmp,"/"); HDstrcat(tmp,name); /* absolute name of the data set */ if (statbuf.nlink > info->threshold && search_obj(info->dset_table, statbuf.objno) == FAIL) 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) == FAIL) { 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: HDstrcat(tmp,"/"); HDstrcat(tmp,name); /* absolute name of the type */ i = search_obj(info->type_table, statbuf.objno); if (i == FAIL) { 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 { free(info->type_table->objs[i].objname); info->type_table->objs[i].objname = HDstrdup(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; } HDfree(tmp); return SUCCEED; } /*------------------------------------------------------------------------- * Function: dump_table * * Purpose: display the contents of tables for debugging purposes * * Return: void * * Programmer: Ruey-Hsia Li * * Modifications: * *------------------------------------------------------------------------- */ void dump_table(char* tablename, table_t *table) { int i; printf("%s: # of entries = %d\n", tablename,table->nobjs); for (i = 0; i < table->nobjs; i++) printf("\t%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_tableflag * * Purpose: Return the i'th element's flag setting * * Return: Boolean setting of the i'th element of the object table flag * * Programmer: Paul Harten * *------------------------------------------------------------------------- */ int get_tableflag(table_t *table, int idx) { return table->objs[idx].objflag; } /*------------------------------------------------------------------------- * Function: set_tableflag * * Purpose: Set the i'th element of the object table's flag to TRUE * * Return: Success: SUCCEED * * Failure: N/A * * 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 and sets errno to ENOMEM * * Programmer: Paul Harten * *------------------------------------------------------------------------- */ char * get_objectname(table_t *table, int idx) { return HDstrdup(table->objs[idx].objname); } /*------------------------------------------------------------------------- * 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) { int i; if (table->nobjs == table->size) { table->size *= 2; table->objs = HDrealloc(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; table->objs[i].objname = NULL; } } i = table->nobjs++; table->objs[i].objno[0] = objno[0]; table->objs[i].objno[1] = objno[1]; free(table->objs[i].objname); table->objs[i].objname = HDstrdup(objname); }