/****************************************************************************
* NCSA HDF *
* Software Development Group *
* National Center for Supercomputing Applications *
* University of Illinois at Urbana-Champaign *
* 605 E. Springfield, Champaign IL 61820 *
* *
* For conditions of distribution and use, see the accompanying *
* hdf/COPYING file. *
* *
****************************************************************************/
#ifdef RCSID
static char RcsId[] = "@(#)1.1";
#endif
/* hdp_util.c,v 1.1 1994/04/18 15:49:18 georgev Exp */
#include "hdp.h"
const char *unknown_tag = "Unknown Tag";
char *
tagnum_to_name(intn num)
{
char *ret;
ret = HDgettagsname(num);
if (ret == NULL)
ret = HDstrdup(unknown_tag);
return (ret);
} /* end tagnum_to_name() */
intn
tagname_to_num(const char *name)
{
return (HDgettagnum(name));
} /* end tagname_to_num() */
/*
* Routines to create a list of file names from the command line
*/
/* assumes that curr_arg is pointing to the first file name */
filelist_t *
make_file_list(intn curr_arg, intn argc, char *argv[])
{
intn i;
filelist_t *ret;
if (curr_arg > argc) /* consistency check */
return (NULL);
ret = (filelist_t *) HDmalloc(sizeof(filelist_t));
if (ret == NULL)
{
fprintf(stderr, "make_file_list: space allocation failed\n");
return (NULL);
}
ret->file_arr = (char **) HDmalloc(sizeof(char *) * ((argc - curr_arg) + 1));
if (ret->file_arr == NULL)
{
fprintf(stderr, "make_file_list: space allocation failed\n");
HDfree(ret);
return (NULL);
} /* end if */
ret->max_files = (argc - curr_arg);
ret->curr_file = 0;
for (i = 0; curr_arg < argc; i++, curr_arg++)
ret->file_arr[i] = HDstrdup(argv[curr_arg]);
return (ret);
} /* end make_file_list() */
char *
get_next_file(filelist_t * f_list, intn advance)
{
if (advance)
f_list->curr_file++;
if (f_list->curr_file >= f_list->max_files)
return (NULL);
return (f_list->file_arr[f_list->curr_file]);
} /* end get_next_file() */
/* free_struct_list use HDfree to free the list of vgroup info structs */
vg_info_t ** free_vginfo_list(
vg_info_t **nodelist,
int32 num_items )
{
intn i;
/* if the list is not NULL, free each node then reset the list to NULL */
if( nodelist != NULL)
{
for( i = 0; i < num_items; i++ )
if( nodelist[i] != NULL )
HDfree( nodelist[i] );
HDfree( nodelist );
}
return( NULL );
} /* end of free_vginfo_list */
/* free_str_list use HDfree to free the list of strings of characters */
char** free_str_list( char **str_list,
int32 num_items )
{
intn i;
if( str_list != NULL)
{
for( i = 0; i < num_items; i++ )
free_char_list( str_list[i] );
HDfree( str_list );
}
return( NULL );
} /* end of free_str_list */
/* free_num_list use HDfree to free the string of characters; this routine
is short but can be used in many different places and very convenient */
char* free_char_list( char *char_list )
{
if( char_list != NULL)
HDfree( char_list );
return( NULL );
} /* end of free_char_list */
/* free_num_list use HDfree to free the list of integers; this routine
is short but can be used in many different places and very convenient */
int32* free_num_list( int32 *num_list )
{
if( num_list != NULL)
HDfree( num_list );
return( NULL );
} /* end of free_num_list */
void
free_file_list(filelist_t * f_list)
{
intn i;
for (i = 0; i < f_list->max_files; i++)
HDfree(f_list->file_arr[i]);
HDfree(f_list->file_arr);
HDfree(f_list);
} /* end free_file_list() */
/*
* Routines to manipulate group lists
*/
groupinfo_t *
make_group_list(int32 fid, uint16 tag, uint16 ref)
{
intn nobj;
intn i;
groupinfo_t *ret;
int32 gid;
if (tag == DFTAG_RIG || tag == DFTAG_SDG || tag == DFTAG_NDG)
{
if ((gid = DFdiread(fid, tag, ref)) == FAIL)
return (NULL);
if ((nobj = DFdinobj(gid)) == FAIL)
return (NULL);
if ((ret = (groupinfo_t *) HDmalloc(sizeof(groupinfo_t))) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
return (NULL);
}
ret->max_dds = nobj;
ret->curr_dd = 0;
if (nobj > 0)
{
if ((ret->dd_arr = (DFdi *) HDmalloc(sizeof(DFdi) * nobj)) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
HDfree(ret);
return (NULL);
} /* end if */
for (i = 0; i < nobj; i++)
{
if (DFdiget(gid, &ret->dd_arr[i].tag, &ret->dd_arr[i].ref) == FAIL)
{
HDfree(ret->dd_arr);
HDfree(ret);
return (NULL);
} /* end if */
} /* end for */
} /* end if */
else
{ /* paranoia sets in... */
ret->max_dds = ret->curr_dd = 0;
ret->dd_arr = NULL;
} /* end else */
} /* end if */
else
{ /* check for Vgroup? */
int32 vkey;
/* Yes, I know this wastes time, but at least it allows uniform access */
/* to both types of groups in HDF files... */
if (vinit_done == FALSE)
{ /* check whether we've already init'ed Vsets */
vinit_done = TRUE;
Vinitialize(fid);
} /* end if */
if ((vkey = Vattach(fid, ref, "r")) != FAIL)
{
if ((nobj = Vntagrefs(vkey)) != FAIL)
{
if( nobj > 0 ) { /* Albert fixed */
int32 *temp_tag;
int32 *temp_ref;
if ((temp_tag = (int32 *) HDmalloc(sizeof(int32) * nobj)) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
Vdetach(vkey);
return (NULL);
} /* end if */
if ((temp_ref = (int32 *) HDmalloc(sizeof(int32) * nobj)) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
Vdetach(vkey);
HDfree(temp_tag);
return (NULL);
} /* end if */
if (Vgettagrefs(vkey, temp_tag, temp_ref, nobj) == FAIL)
{
Vdetach(vkey);
HDfree(temp_tag);
HDfree(temp_ref);
return (NULL);
} /* end if */
if ((ret = (groupinfo_t *) HDmalloc(sizeof(groupinfo_t))) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
Vdetach(vkey);
HDfree(temp_tag);
HDfree(temp_ref);
return (NULL);
} /* end if */
ret->max_dds = nobj;
ret->curr_dd = 0;
if ((ret->dd_arr = (DFdi *) HDmalloc(sizeof(DFdi) * nobj)) == NULL)
{
fprintf(stderr, "make_group_list: space allocation failed\n");
Vdetach(vkey);
HDfree(temp_tag);
HDfree(temp_ref);
HDfree(ret);
return (NULL);
} /* end if */
/*
printf("make_group_list for tag/ref = %d/%d\n", tag, ref );
*/
for (i = 0; i < nobj; i++)
{
ret->dd_arr[i].tag = (uint16) temp_tag[i];
ret->dd_arr[i].ref = (uint16) temp_ref[i];
/*
printf("element %d: tag/ref = %d/%d\n", i, temp_tag[i], temp_ref[i] );
*/
} /* end for */
HDfree(temp_tag);
HDfree(temp_ref);
} /* if nobj > 0 */
/* BMR: 7/28/00 must add this one, otherwise, HDfree fails later */
else /* nobj <= 0 */
return( NULL );
} /* end if */
else /* bad vkey? */
return (NULL);
Vdetach(vkey); /* release the Vgroup */
} /* end if */
else /* failed to attach */
return (NULL);
} /* end else */
return (ret);
} /* end make_group_list() */
DFdi *
get_next_group(groupinfo_t * g_list, intn advance)
{
if (advance)
g_list->curr_dd++;
if (g_list->curr_dd >= g_list->max_dds)
return (NULL);
return (&g_list->dd_arr[g_list->curr_dd]);
} /* end get_next_group() */
int32
get_group_max(groupinfo_t * g_list)
{
if (g_list != NULL)
return (g_list->max_dds);
return (FAIL);
} /* end get_group_max() */
void
free_group_list(groupinfo_t * g_list)
{
if( g_list != NULL )
{
if( g_list->dd_arr != NULL )
HDfree(g_list->dd_arr);
HDfree(g_list);
}
} /* end free_group_list() */
/*
* Routines to manipulate tag/ref lists
*/
objlist_t *
make_obj_list(int32 fid, uint32 options)
{
intn nobj; /* number of DDs in the file */
int32 status; /* status of various HDF calls */
int32 aid; /* temporary AID to use while getting DD info */
int16 tmp_spec; /* temporary storage for special status */
objlist_t *obj_ret; /* pointer to the dd list to return */
objinfo_t *obj_ptr; /* temporary pointer to a working DD object */
sp_info_block_t info; /* temp. storage for special elem. info */
intn n, m; /* local counting variable */
/* get the number of all objects in the file */
nobj = Hnumber(fid, DFTAG_WILDCARD);
if (nobj == FAIL || nobj <= 0 ) /* BMR: added check for nobj<=0 */
return (NULL);
/* allocate space for the object list - exit at failure??? */
if ((obj_ret = (objlist_t *) HDmalloc(sizeof(objlist_t))) == NULL)
{
fprintf(stderr, "make_obj_list: space allocation failed\n");
return (NULL);
}
obj_ret->max_obj = nobj; /* set the number of objects */
obj_ret->curr_obj = 0;
obj_ret->raw_obj_arr = (objinfo_t *) HDmalloc(sizeof(objinfo_t) * nobj);
/* should it exit on failure ??? */
if( obj_ret->raw_obj_arr == NULL)
{
fprintf(stderr, "make_obj_list: space allocation failed\n");
HDfree(obj_ret);
return (NULL);
} /* end if */
/* Clear array of dd/object information */
HDmemset(obj_ret->raw_obj_arr, 0, sizeof(objinfo_t) * nobj);
/*
* Read all the tag/ref's in the file into an array
*/
/* start the reading of an access element */
aid = Hstartread(fid, DFTAG_WILDCARD, DFREF_WILDCARD);
if (aid == FAIL)
{
HEprint(stderr, 0);
HDfree(obj_ret->raw_obj_arr);
HDfree(obj_ret);
return (NULL);
} /* end if */
/* for each element */
for (n = 0, status = SUCCEED; (n < nobj) && (status != FAIL); n++)
{
Hinquire(aid, NULL, &(obj_ret->raw_obj_arr[n].tag),
&(obj_ret->raw_obj_arr[n].ref), &(obj_ret->raw_obj_arr[n].length),
&(obj_ret->raw_obj_arr[n].offset), NULL, NULL, &tmp_spec);
if (options & CHECK_SPECIAL)
{ /* are we looking for spec. elem. ? */
obj_ret->raw_obj_arr[n].is_special = (tmp_spec != 0);
if (obj_ret->raw_obj_arr[n].is_special)
{ /* get the special info. */
if ((status = HDget_special_info(aid, &info)) == FAIL)
{
obj_ret->raw_obj_arr[n].is_special = 0;
} /* end if */
else
{ /* copy over special information we found */
obj_ret->raw_obj_arr[n].spec_info = (sp_info_block_t *) HDmalloc(sizeof(sp_info_block_t));
if( obj_ret->raw_obj_arr[n].spec_info == NULL)
{
fprintf(stderr, "make_obj_list: space allocation failed\n");
obj_ret->raw_obj_arr[n].is_special = 0;
}
else
HDmemcpy(obj_ret->raw_obj_arr[n].spec_info, &info, sizeof(sp_info_block_t));
} /* end else */
} /* end if */
} /* end if */
status = Hnextread(aid, DFTAG_WILDCARD, DFREF_WILDCARD, DF_CURRENT);
} /* end for */
if (Hendaccess(aid) == FAIL)
{
HEprint(stderr, 0);
HDfree(obj_ret->raw_obj_arr);
HDfree(obj_ret);
return (NULL);
} /* end if */
/* Post-process the list of dd/objects, adding more information */
/* Also set up the pointers for the sorted list to be manipulated later */
obj_ret->srt_obj_arr = (objinfo_t **) HDmalloc(sizeof(objinfo_t *) * nobj);
if( obj_ret->srt_obj_arr == NULL )
{
fprintf(stderr, "make_obj_list: space allocation failed\n");
HDfree(obj_ret->raw_obj_arr);
HDfree(obj_ret);
return (NULL);
} /* end if */
/* Loop for more information */
for (n = 0; n < nobj; n++)
{
obj_ptr = obj_ret->srt_obj_arr[n] = &obj_ret->raw_obj_arr[n];
/* set the index value to a flag for later */
obj_ptr->index = (-1);
/* check for a group */
if (options & CHECK_GROUP)
{ /* are we looking for groups ? */
if (obj_ptr->tag == DFTAG_RIG || obj_ptr->tag == DFTAG_SDG
|| obj_ptr->tag == DFTAG_NDG || obj_ptr->tag == DFTAG_VG)
{
obj_ptr->is_group = TRUE;
obj_ptr->group_info = make_group_list(fid, obj_ptr->tag, obj_ptr->ref);
if( obj_ptr->group_info == NULL )
{
/* do not free these because even this element has no group
list, it still can be displayd */
/*
HDfree(obj_ret->raw_obj_arr);
HDfree(obj_ret);
return (NULL);
*/
} /* end if */
} /* end if */
} /* end if */
} /* end for */
/* Loop once more to figure out the index information */
for (n = 0, obj_ptr = &obj_ret->raw_obj_arr[0]; n < nobj; n++, obj_ptr++)
{
if (obj_ptr->index == (-1))
{ /* first object of this type in the file */
int32 temp_index = 0;
objinfo_t *temp_ptr; /* temporary pointer to a working DD object */
/* the object gets index of 0 */
obj_ptr->index = 0;
/* look for other objects of this tag */
for (m = n, temp_ptr = obj_ptr + 1; m+1 < nobj; m++, temp_ptr++)
{
if (temp_ptr->tag == obj_ptr->tag)
temp_ptr->index = ++temp_index; /* set next index */
} /* end for */
} /* end if */
} /* end for */
obj_ret->options = options;
return (obj_ret);
} /* end make_dd_list() */
objinfo_t* get_next_obj(
objlist_t * o_list, intn advance )
{
if( advance )
o_list->curr_obj++;
if( o_list->curr_obj >= o_list->max_obj )
return (NULL);
return( o_list->srt_obj_arr[o_list->curr_obj] );
} /* end get_next_obj() */
objinfo_t* goto_nth_obj(
objlist_t * o_list, intn n )
{
if( n >= 0 && n < o_list->max_obj )
o_list->curr_obj = n;
return( o_list->srt_obj_arr[o_list->curr_obj] );
} /* end goto_nth_obj() */
void reset_obj_list(
objlist_t * o_list )
{
if( o_list != NULL )
o_list->curr_obj = 0;
} /* end reset_obj_list() */
void free_obj_list(
objlist_t * o_list )
{
intn i; /* local counting variable */
objinfo_t *obj_ptr; /* temporary pointer to a working DD object */
/* BMR: verify that o_list is not nil before accessing */
if( o_list != NULL )
{
for (i = 0, obj_ptr = o_list->raw_obj_arr; i < o_list->max_obj;
i++, obj_ptr++)
{
/* group_info can be NULL while is_group is set, how to handle
this one??? BMR 8/1/2000
if( obj_ptr->is_group && obj_ptr->group_info != NULL ) */
if( obj_ptr->is_group )
free_group_list( obj_ptr->group_info );
if( obj_ptr->is_special )
HDfree( obj_ptr->spec_info );
} /* end for */
HDfree(o_list->srt_obj_arr);
HDfree(o_list->raw_obj_arr);
HDfree(o_list);
}
else
fprintf(stderr, ">>>free_obj_list failed - attempting to free a NULL list \n");
} /* end free_obj_list() */
int sort_obj_list_by_tag(const void *p1, const void *p2)
{
const objinfo_t *a = (const objinfo_t *) *((const void **) p1);
const objinfo_t *b = (const objinfo_t *) *((const void **) p2);
if (a->tag > b->tag)
return (1);
if (a->tag < b->tag)
return (-1);
if (a->ref > b->ref)
return (1);
if (a->ref < b->ref)
return (-1);
return (0);
} /* end sort_obj_info_by_tag() */
#if 0 /* No longer possible since objects can have more than one label
* -GV 6/12/97 */
int sort_obj_list_by_name(const void *p1, const void *p2)
{
const objinfo_t *a = (const objinfo_t *) *((void **) p1);
const objinfo_t *b = (const objinfo_t *) *((void **) p2);
/* Any label has priority over no label, else sort alphabetically */
if (a->has_label)
{
if (b->has_label)
return (HDstrcmp(a->lab_info, b->lab_info));
else
return (1);
} /* end if */
else
{
if (b->has_label)
return (-1);
else
return (0);
} /* end else */
} /* end sort_obj_info_by_tag() */
#endif
void sort_obj_list(objlist_t * o_list, sort_t sort_type)
{
switch (sort_type)
{
#if 0 /* No longer possible since objects can have more than one label
* -GV 6/12/97 */
case ONAME: /* sort by name order */
qsort(o_list->srt_obj_arr, o_list->max_obj, sizeof(objinfo_t *), sort_obj_list_by_name);
break;
#endif
case OGROUP: /* sort by group order */
break; /* not currently implemented */
case OTAG: /* sort by tag order */
qsort(o_list->srt_obj_arr, o_list->max_obj, sizeof(objinfo_t *), sort_obj_list_by_tag);
break;
case OFILE: /* sort by file order */
default:
break;
} /* end switch() */
} /* end sort_obj_list() */
/* Misc. utility functions */
int int32_compare(const void *a, const void *b)
{
if (*(const int32 *) a > *(const int32 *) b)
return (1);
else if (*(const int32 *) a < *(const int32 *) b)
return (-1);
else
return (0);
} /* end int32_compare() */
void sort(int32 *chosen, int32 choices)
{
qsort((void *) chosen, choices, sizeof(int32), int32_compare);
}
/* resetBuff frees the passed-in pointer and resets it to NULL,
if it is not NULL. Its purpose is to make cleaning up simpler
throughout the entire dumper */
void resetBuff( VOIDP *ptr )
{
if( *ptr != NULL )
{
HDfree(*ptr);
*ptr = NULL;
}
}
/* parse_number_opts take a list of numbers separated by commas then
retrieves the numbers and stores them in the structure provided by
the caller. This routine is used by all the routines
parse_dumpxx_opts to parse the index or ref list that accompanies
option -i or -r */
void
parse_number_opts( char *argv[],
int *curr_arg,
number_filter_t *filter)
{
int32 numItems = 0, i;
char *tempPtr = NULL;
char *ptr = NULL;
/* put a temp ptr at the beginning of the given list of numbers,
separated by commas, for example, 1,2,3 */
ptr = argv[*curr_arg];
/* check if it's the end of the command */
if( ptr == NULL )
{
printf("Missing values for option\n");
exit(1);
}
/* then traverse the list and count the number of items in it */
while ((tempPtr = HDstrchr(ptr, ',')) != NULL)
{
numItems++; /* count number of items in the list */
ptr = tempPtr + 1;/* forward pointer to next item, after a comma */
} /* end while */
if (*ptr != '\0') /* count the last item */
numItems++;
/* allocate space to hold all the items in the list */
filter->num_list = (int32 *) HDmalloc(sizeof(intn) * numItems);
CHECK_ALLOC( filter->num_list, "filter->num_list", "parse_number_opts" );
/* go back to the beginning of the list and read in the numbers */
ptr = argv[*curr_arg];
i = 0; /* index of the list */
while ( i < numItems )
{
tempPtr = HDstrchr(ptr, ',');
if( tempPtr != NULL )
*tempPtr = '\0'; /* end the string of digits */
filter->num_list[i] = atoi(ptr); /* convert string to digits */
ptr = tempPtr + 1;
i++;
}
filter->num_items = numItems; /* save the number of items */
} /* parse_number_opts */
/* parse_string_opts take a list of strings separated by commas then
retrieves the strings and stores them in the structure provided by
the caller. This routine is used by all the routines
parse_dumpxx_opts to parse the name or class list that accompanies
option -n or -c */
void
parse_string_opts( char *argv[],
int *curr_arg,
char_filter_t *filter)
{
int32 numItems = 0, i;
char *tempPtr = NULL;
char *ptr = NULL;
/* put a temp pointer at the beginning of the list of strings,
separated by commas */
ptr = argv[*curr_arg];
/* check if it's the end of the command */
if( ptr == NULL )
{
printf("Missing values for option\n");
exit(1);
}
/* then traverse the list and count the number of strings in it */
while ((tempPtr = HDstrchr(ptr, ',')) != NULL)
{
numItems++;
ptr=tempPtr+1;
} /* end while */
if (*ptr != '\0') /* count the last item */
numItems++;
/* allocate space to hold pointers that will point to the given strings */
filter->str_list = (char **) HDmalloc(sizeof(char *) * numItems);
CHECK_ALLOC( filter->str_list, "filter->str_list", "parse_string_opts" );
/* go back to the beginning of the list and read in the given strings */
ptr = argv[*curr_arg];
i = 0; /* init the index of the list */
while ( i < numItems )
{
tempPtr = HDstrchr(ptr, ','); /* find the end of a string */
if( tempPtr != NULL )
*tempPtr = '\0'; /* end the string with a NULL char */
/* allocate space for each string */
filter->str_list[i] = (char *)HDmalloc(sizeof(char) * (HDstrlen(ptr)+1));
CHECK_ALLOC( filter->str_list[i], "filter->str_list[i]", "parse_string_opts" );
HDstrcpy(filter->str_list[i], ptr); /* get the current string */
ptr = tempPtr + 1; /* move pointer to next item or end of list */
i++;
} /* end while */
filter->num_items = numItems; /* save the number of items */
} /* parse_string_opts */
/* validate_pos makes sure that number is > 0 so we are not going to
allocate 0 elements
This routine is replaced by the macro called CHECK_POS just because
the error checkings are being done that way! 7/27/00
*/
/* if there are any specific datasets requested, alloc_index_list
allocates space for the list of indices of these requested items */
void
alloc_index_list(
int32 **index_list,
int32 num_chosen )
{
int32 i = -1; /* used to pass into HDmemfill as dummmy? */
*index_list = (int32 *) HDmalloc(sizeof(int32) * num_chosen);
CHECK_ALLOC( *index_list, "index_list", "alloc_index_list" );
i = (-1);
HDmemfill(*index_list, &i, sizeof(int32), num_chosen);
} /* end of alloc_index_list */
syntax highlighted by Code2HTML, v. 0.9.1