From 37957dfe1dcc08ec9a34ddc26fed2d9ae1dd4509 Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Thu, 8 Mar 2001 15:18:42 -0500 Subject: [svn-r3571] Purpose: New Modules Description: Separated the "generic" functions out of the h5tools module into their own separate module to make things a bit nicer to deal with. Platforms tested: Linux --- tools/lib/h5tools_utils.c | 648 ++++++++++++++++++++++++++++++++++++++++++++++ tools/lib/h5tools_utils.h | 114 ++++++++ 2 files changed, 762 insertions(+) create mode 100644 tools/lib/h5tools_utils.c create mode 100644 tools/lib/h5tools_utils.h diff --git a/tools/lib/h5tools_utils.c b/tools/lib/h5tools_utils.c new file mode 100644 index 0000000..df12a99 --- /dev/null +++ b/tools/lib/h5tools_utils.c @@ -0,0 +1,648 @@ +/* + * Copyright (c) 2001 National Center for Supercomputing Applications + * All rights reserved. + * + * 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); + 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: 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); +} + + +/*------------------------------------------------------------------------- + * 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 = 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; + } + + *tbl = 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: 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) +{ + 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 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; + 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) == 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); + } + + 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) == 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: + strcat(tmp,"/"); + strcat(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 { + 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_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) +{ + register 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 strdup(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) +{ + 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[0]; + table->objs[i].objno[1] = objno[1]; + strcpy(table->objs[i].objname, objname); +} diff --git a/tools/lib/h5tools_utils.h b/tools/lib/h5tools_utils.h new file mode 100644 index 0000000..eda8e00b --- /dev/null +++ b/tools/lib/h5tools_utils.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2001 National Center for Supercomputing Applications + * All rights reserved. + * + * Programmer: Bill Wendling + * Tuesday, 6. March 2001 + * + * Purpose: Support functions for the various tools. + */ +#ifndef H5TOOLS_UTILS_H__ +#define H5TOOLS_UTILS_H__ + +#include "hdf5.h" + +/* + * 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 + */ + +/*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 int nCols; /*max number of columns for outputting */ + +/* Definitions of useful routines */ +extern void indentation(int); +extern void print_version(const char *progname); +extern void error_msg(const char *progname, const char *fmt, ...); +extern void warn_msg(const char *progname, const char *fmt, ...); +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); +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 **tbl); +extern void init_prefix(char **temp, int); + +#endif /* H5TOOLS_UTILS_H__ */ -- cgit v0.12