/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by  The HDF Group and                                           *
 *               The Board of Trustees of the University of Illinois.        *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of H4H5TOOLS. The full H4H5TOOLS copyright notice,      *
 * including terms governing use, modification, and redistribution, is       *
 * contained in the COPYING file, which can be found at the root of the      *
 * source code distribution tree. The copyright notice can also be found     *
 * at https://www.hdfgroup.org/licenses.  If you do not have access to       *
 * either file, you may request a copy from help@hdfgroup.org.               *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/*****************************************************************************

  Description: This file contains routines to translate H5 files to H4 files.
 
  Author:  Paul Harten for the University of Illinois, NCSA
 
  Creation Date:  04 October 1998

  History:


*****************************************************************************/

#include <errno.h>
#include <string.h>
#include <fcntl.h>

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#define H5TOH4_DEBUG
#include "h5toh4.h"

#ifdef WIN32
typedef unsigned int mode_t;
#else
#include <unistd.h>
#endif  /* WIN32 */

#ifndef S_ISDIR
#define S_ISDIR(mode)   (((mode)&0xF000) == S_IFDIR)
#endif  /* !S_ISDIR */

int debug = 0;
int debug1 = 0;

/* library version for API switching */
unsigned int majnum;
unsigned int minnum;
unsigned int relnum;

/*struct taken from the dumper. needed in table struct*/
typedef struct obj_t {
    unsigned long objno[2];
    char *objname;
    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 void PrintOptions_h5toh4(void);
extern char *BuildFilename(char *h5_filename, char *h4_extension);
extern int test_file(char *filename, int oflag, mode_t mode);
extern int test_dir(char *);
extern int h5toh4(char *, char *, int);

extern herr_t convert_group(hid_t, char *, op_data_t *);
extern herr_t convert_dataset(hid_t, char *, op_data_t *);
extern herr_t convert_all(hid_t, char *, op_data_t *);
extern herr_t convert_attr(hid_t, char *, op_data_t *);
extern herr_t convert_shared_dataset(hid_t, int, op_data_t *, int dset_type);
extern herr_t convert_shared_group(hid_t, int, op_data_t *);
extern herr_t convert_dataset_string(hid_t, char *, op_data_t *);
extern int32 h5type_to_h4type(hid_t);
extern hid_t h4type_to_memtype(int32);

typedef herr_t (*H5G_operator_t)(hid_t, const char*, void*);

static int prefix_len = 1024;
static char *prefix=NULL;
static table_t *group_table;
static table_t *dset_table;
static table_t *type_table;

/* pkamat */
static int32 rootgroup_ref=-1;
static herr_t process_rootgroup_attr(int32 file_id, int32 sd_id, int32 gr_id, int32 an_id);
static herr_t isPrefix(char *attrname, const char *pref);
static herr_t isSuffix(char *attrname, const char *suffix);
static int getAttrType(char *attr_name);
static int32 valueOfAttr(hid_t did, const char* attr_name, void* attr_value);
static herr_t convert_image_attr (hid_t attr, char *attr_name, op_data_t *op_data);
static herr_t inImageAttrSkipList(char *name);
static herr_t inHDF5ImageSpecAttrList(char *name);
static herr_t convert_image (hid_t did, char *name, op_data_t *op_data);
static herr_t convert_palette (hid_t did, int32 grimage_id, op_data_t *op_data);
static int gtoken(char *s);
static herr_t convert_palette_attr (hid_t attr, char *attr_name, op_data_t *op_data);
static herr_t convert_table_attr (hid_t attr, char *attr_name, op_data_t *op_data);
herr_t convert_table (hid_t did, char *name, op_data_t *op_data);

void process_one_dimscale( hid_t h5file, int32 sds_id, char *dimname );
int push_dimname( char * name) ;
void process_dimscales( hid_t dsetid, int32 sdsid ) ;
char * strip_dimgroup( char * dimpath) ;

#define ATTR_ABSENT   -2
#define DSET_IMAGE   -3
#define DSET_PALETTE  -4
#define DSET_TABLE  -5
#define DSET    -6
/* pkamat */


static herr_t h5atomic_type_to_h4type(const hid_t h5type, hid_t* h5memtype,
                                      size_t* h5memsize, int32* h4type);
/* local table access functions */
static void init_table(table_t **tbl);
static void init_prefix(char **prefx, int prefx_len);
static void free_table(table_t **table);
static int search_obj(table_t *table, unsigned long *objno);
static herr_t find_objs(hid_t group, const char *name, void *op_data);
static int get_table_idx(table_t *table, unsigned long *objno);
static int get_tableflag(table_t *table, int idx);
static int set_tableflag(table_t *table, int idx);
static char * get_objectname(table_t *table, int idx);
static void add_obj(table_t *table, unsigned long *objno, char *objname);

static char * stringify( void * value, int count, int32 nt ) ;

/* pkamat [MOD1] Structs infilesformat and Options used for the cleaner implementation 
 * (using state table) of command line arguments. The function gtoken() does token processing
 * and function main() implements the state machine
 */

struct infilesformat
{
  char datafile[256];
  int root; /*  suppress root? No - TRUE. Yes - FALSE */
};

struct Options
{
  struct infilesformat  infiles[30];  /* structure to hold the list of input file names. Limited to 30*/
  char   outfile[256];  /* output file name */
  int    fcount;       /* number of input files */      
};

/*
 * state table tokens
 */
#define NUM_TOKENS 4 /* Number of tokens not counting ERR */
#define FILNAME 0    /* filename */
#define OPT_h   1    /* request for explanation */
#define OPT_m   2    /* multiple HDF5 files */
#define OPT_r   3    /* suppress root */
#define TOK_ERR    20    /* invalid token */

#define NUM_STATES 8
static int  state_table[NUM_STATES][NUM_TOKENS] =
{
  /* token ordering:
     FILNAME      OPT_h   OPT_m  OPT_r */

  /* state 0: start */
  {1, 4, 5, TOK_ERR},

  /* state 1: h5toh4 h5file */
  {3, TOK_ERR, TOK_ERR, 2},

  /* state 2: h5toh4 h5file -r */
  {3, TOK_ERR, TOK_ERR, TOK_ERR},

  /* state 3: h5toh4 h5file [-r] h4file */
  {TOK_ERR, TOK_ERR, TOK_ERR, TOK_ERR},

  /* state 4: h5toh4 -h */
  {TOK_ERR, TOK_ERR, TOK_ERR, TOK_ERR},

  /* state 5: h5toh4 -m  */
  {6, TOK_ERR, TOK_ERR, TOK_ERR},
   
  /* state 6: h5toh4 -m h5file1 .. h5fileN  */
  {6, TOK_ERR, TOK_ERR, 7},

  /* state 7: h5toh4 -m [..] h5fileN [-r]  */
  {6, TOK_ERR, TOK_ERR, TOK_ERR}

};

static int
gtoken(char *s)
{
  size_t      len;
  int         token;

  const char *err1 = "Illegal argument: %s.\n";

  /*
   * identify the token type
   */
  if (s[0] == '-')
  {     
    /* option name (or negative number) */
    token = TOK_ERR;
    len = HDstrlen(&s[1]);
    switch (s[1])
    {
      case 'm':
        if (!HDstrncmp("multiple", &s[1], len))
          token = OPT_m;
      break;
       
      case 'r':
        if (!HDstrncmp("root", &s[1], len))
          token = OPT_r;
      break;
    
      case 'h':
        if (!HDstrncmp("help", &s[1], len))
          token = OPT_h;
      break; 
      default:
      break;
    }
    
    if (token == TOK_ERR)
      (void) fprintf(stderr, err1, s);
  }
  else    /* filename */
  {
    token = FILNAME;
  }
  return (token);
}


/*****************************************************************************

  Routine: main()
 
  Description: This routine check out arguments sent, makes sure everything is
               ok, chooses between the acceptable argument formats and then
               calls h5toh4().
           
  Input: arg  - the number of arguments from the call + 1;
         argv  - a pointer to an array of strings which are the arguments.
                  This includes the routine name as the first string.
 
  Output: function return  - error status

  Exit Status:
    EXIT_SUCCESS(0)   Succeeded.
    EXIT_FAILURE(1)   An error occurred.

*****************************************************************************/

int
main(int argc, char *argv[])
{
    char *h5_filename=NULL;
    char *h4_filename=NULL;
    char *h4_extension;
    int status = 0;
    int status2 = 0;
    const char *err1 = "Invalid number of arguments:  %d.\n";
    const char *err2 = "Error in state table.\n";
    const char *err4 = "Program aborted.\n";
    int outfile_named = FALSE;
    int indx = 0;
    int i;
    int state = 0;
    int    token;
    struct  Options opt;
 /*
  * validate the number of command line arguments
  */
 
  if (argc < 2)
  {
    (void) fprintf(stderr, err1, argc);
    PrintOptions_h5toh4();
    (void) fprintf(stderr, err4);
    return EXIT_FAILURE;
  }

  /* Get library version for API switching */
  H5get_libversion(&majnum, &minnum, &relnum);

  /* Initialize the file count to 0 */
  opt.fcount = 0;

  for (i = 1; i < argc; i++)
  {
    if ((token = gtoken(argv[i])) == TOK_ERR)
    {
      PrintOptions_h5toh4();
      (void) fprintf(stderr, err4);
      return EXIT_FAILURE;
    }

    state = state_table[state][token];

    switch (state)
    {    
      case 1: 
        (void) HDstrcpy(opt.infiles[opt.fcount].datafile, argv[i]);
        opt.infiles[opt.fcount].root = FALSE;
        opt.fcount++;
      break;

      case 2: 
        opt.infiles[opt.fcount-1].root = TRUE;
      break;

      case 3: 
        (void) HDstrcpy(opt.outfile, argv[i]);
        outfile_named = TRUE;
      break;

      case 4: 
        PrintOptions_h5toh4();
        exit(EXIT_SUCCESS);             

      case 5: 
      break;
  
      case 6: 
        (void) HDstrcpy(opt.infiles[opt.fcount].datafile, argv[i]);
        opt.infiles[opt.fcount].root = FALSE;
        opt.fcount++;
      break;

      case 7: 
        opt.infiles[opt.fcount-1].root = TRUE;
      break;

      case TOK_ERR:   /* command syntax error */
      default:
        (void) fprintf(stderr, err2);
        PrintOptions_h5toh4();
        (void) fprintf(stderr, err4);
        return EXIT_FAILURE;
    }
  }
  
  indx = -1;

  while (indx < opt.fcount-1) {
      indx++;
      h5_filename = opt.infiles[indx].datafile;

#ifndef WIN32
            if (test_file(h5_filename, O_EXCL, 292) != 0 ) {
                /* 292 Decimal - 0444 Octal, a+r */
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "main", __FILE__, __LINE__);
                status2 = -1;
                continue;
            }

            if (test_dir(h5_filename) != 0 ) {
                fprintf(stderr, "%s: Is a directory\n", h5_filename);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "main", __FILE__, __LINE__);
                status2 = -1;
                continue;
            }
#endif  /* !WIN32 */

      if (outfile_named == FALSE)
      {
            h4_extension = HDstrdup("hdf");
            h4_filename = BuildFilename(h5_filename, h4_extension);

            if (h4_filename == NULL) {
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "main", __FILE__, __LINE__);
                status2 = -1;
                free(h4_extension);
                free(h4_filename);
                continue;
            }

#ifndef WIN32
            if (test_file(h4_filename, O_CREAT | O_EXCL, 436) != 0) {
                /* 436 Decimal - 0664 Octal, ug+rw,o+r */
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "main", __FILE__, __LINE__);
                status2 = -1;
                free(h4_extension);
                free(h4_filename);
                continue;
            }
#endif  /* !WIN32 */

           free(h4_extension);
     } 
     else /* if (outfile_named != FALSE) */
     {
        h4_filename = opt.outfile;
     } /* end of if (outfile_named == FALSE) */

     status = h5toh4(h5_filename, h4_filename, opt.infiles[indx].root);
     if (status != 0) {
          fprintf(stderr, "Error: Problem with %s\n", h5_filename);
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "main", __FILE__, __LINE__);
          status2 = status;
     }
     if (outfile_named == FALSE)
              free(h4_filename);
     }

  if (status2 == 0)
    return EXIT_SUCCESS;
  else
    return EXIT_FAILURE;
}
/* end pkamat [MOD1] */

/*****************************************************************************

  Routine: PrintOptions_h5toh4()
 
  Description: This routine prints the acceptable argument formats out to stderr.
           
  Input: None
 
  Output: output to stderr

*****************************************************************************/

void PrintOptions_h5toh4(void)
{
    fprintf(stderr, "\nh5toh4 -h (gives this print-out)\n");
    fprintf(stderr, "h5toh4 file.h5 [-r] file.hdf\n");
    fprintf(stderr, "h5toh4 file.h5 [-r]\n");
    fprintf(stderr, "h5toh4 -m file1.h5 file2.h5 ... [-r]\n");
    fprintf(stderr, "       [-r] create a VGroup for the root group\n\n");
}

int ndimns  = 0;
char ** dimnames = NULL;
char *dimnamesptr = NULL;

int push_dimname( char * name) {
int i;
char **tp;
char *tp_ptr = NULL;
char **tp2;
char **dp;

  if (name == NULL) return 0;

  if (ndimns == 0) {

    dimnamesptr = malloc(sizeof(char **));
    dimnames = (char **)dimnamesptr;
    *dimnames = malloc (strlen(name)+1);
    strcpy(*dimnames,name);
    ndimns = 1;
    return 0;
  }

  /* check if name is in the table */

  dp = dimnames;
  for (i = 0; i < ndimns; i++) {
    if (strcmp(name,*dp)==0) return 1;
    dp++;
  }

    tp_ptr = malloc((ndimns+1)*sizeof(char**));
  tp2 = tp = (char **)tp_ptr;
  dp = dimnames;
  for (i = 0; i < ndimns; i++) {
    *tp = malloc(strlen(*dp)+1);
    strcpy(*tp, *dp);
    tp++;
    dp++;
  }
  *tp = malloc(strlen(name)+1);
  strcpy(*tp,name);
if(dimnames!=NULL) {
        for(i = 0;i<ndimns;i++){
           free(*dimnames);
           dimnames++;
        }

}
ndimns++;

if(dimnamesptr!=NULL) {
   free(dimnamesptr);
   dimnamesptr= NULL;
}
  dimnames = tp2;
    dimnamesptr = tp_ptr;
  return 0;
}

char * strip_dimgroup( char * dimpath) {
        if(dimpath != NULL) {
      if (strncmp(dimpath,"/HDF4_DIMGROUP/",15) == 0) {
        return dimpath+15;
            }
  }
  return dimpath;
}

void process_one_dimscale( hid_t h5file, int32 sds_id, char *dimname ) {
    void *edata;
    /*hid_t (*func)(void*);*/
    H5E_auto_t func;
    hid_t dim_id;
    hid_t dspace;
    hid_t dtype;
    herr_t status;
    int nd;
    int32 h4_type;
    int32 res;
    size_t typesize;
    char *valbuf;
    hid_t  mem_type;
    hsize_t dims[1];
    hsize_t maxdims[1];

  /* need to strip off the 'HDF...' */
  res = SDsetdimname(sds_id,strip_dimgroup(dimname));
  if (push_dimname(dimname)) {
/*
    printf("dimscale already created, just set name\n");
*/
  } else {
/*
    printf("need to create dimscale now %s\n",dimname);
*/
                H5EGET_AUTO (&func, &edata);
                H5ESET_AUTO (NULL, NULL);

    /* get info about the DS and create a dimension */
    dim_id = H5DOPEN(h5file,dimname);
    if (dim_id < 0) {
        fprintf(stderr, "Error: Dimension scale dataset open failed?\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        return;
    }

         dspace = H5Dget_space(dim_id);
    if (dspace < 0) {
        fprintf(stderr, "Error: Dimension scale dataspace failed?\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        H5Dclose(dim_id);
        return;
    }

         if (H5Sget_simple_extent_ndims(dspace) != 1) {
        fprintf(stderr, "Error: Dimension scale not 1D?\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        H5Sclose(dspace);
        H5Dclose(dim_id);
        return;
    }

    nd = H5Sget_simple_extent_dims(dspace, dims, maxdims );
    if (nd != 1) {
        fprintf(stderr, "Error: Dimension scale not 1D?\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        H5Sclose(dspace);
        H5Dclose(dim_id);
        return;
    }
       
    dtype = H5Dget_type(dim_id);
    if (dtype < 0) {
        fprintf(stderr, "Error: Dimension scale type not found\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        H5Sclose(dspace);
        H5Dclose(dim_id);
        return;
    }
        
    if (FAIL == h5atomic_type_to_h4type(dtype, &mem_type, &typesize, &h4_type)){
        fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
        H5Sclose(dspace);
        H5Tclose(dtype);
        H5Dclose(dim_id);
        return;
    }

    valbuf = malloc(H5Tget_size(mem_type)*H5Sget_simple_extent_npoints(dspace));

    status = H5Dread(dim_id,mem_type,H5S_ALL,H5S_ALL,H5P_DEFAULT,valbuf);
    if (status < 0) {
        fprintf(stderr, "Error: Problems reading h5 dimension\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
      H5Sclose(dspace);
      H5Tclose(dtype);
      H5Dclose(dim_id);
      free(valbuf);
      return;
    }


    res = SDsetdimscale(sds_id,H5Sget_simple_extent_npoints(dspace),h4_type,valbuf);
    if (res < 0) {
        fprintf(stderr, "Error: Problems creating h4 dimension\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "process_one_dimscale", __FILE__, __LINE__);
      H5Sclose(dspace);
      H5Tclose(dtype);
      H5Dclose(dim_id);
      free(valbuf);
      return;
    }


    H5EGET_AUTO (&func, &edata);

  H5Sclose(dspace);
  H5Tclose(dtype);
  H5Dclose(dim_id);
  free(valbuf);
    }
    return;
}
void process_dimscales( hid_t dsetid, int32 sdsid ) {
  hid_t attr;
  herr_t status;
  hid_t dt;
  hid_t ds;
  int i;
  int size;
  int count;
  int32 sd_dim_id;
  hsize_t dims[1];
  hsize_t maxdims[1];
  char * valbuf;
  char * cp;
  void *edata;
  /*hid_t (*func)(void*);*/
    H5E_auto_t func;

        H5EGET_AUTO (&func, &edata);
        H5ESET_AUTO (NULL, NULL);
  attr =H5Aopen_name(dsetid, "HDF4_DIMENSION_LIST");
  if (attr < 0) {
    /* nothing to do */
    H5EGET_AUTO (&func, &edata);
    return;
  }
  H5EGET_AUTO (&func, &edata);
  if ((dt = H5Aget_type(attr)) < 0) {
      fprintf(stderr, "Error:  dimlist datatype not found?\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Aclose(attr);
      return;
  }
  if (H5Tget_class(dt) != H5T_STRING) {
      fprintf(stderr, "Error:  dimlist datatype not string?\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Aclose(attr);
      return;
  }
  size = H5Tget_size(dt);
  if ((ds = H5Aget_space(attr)) < 0) {
      fprintf(stderr, "Error:  dimlist dataspace not found?\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Aclose(attr);
      return;
  }
  if (H5Sget_simple_extent_ndims(ds) != 1) {
      fprintf(stderr, "Error:  dimlist not 1D?\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Sclose(ds);
      H5Aclose(attr);
      return;
  }
  if ( H5Sget_simple_extent_dims(ds, dims, maxdims ) != 1) {
      fprintf(stderr, "Error:  dimscale not 1D?\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Sclose(ds);
      H5Aclose(attr);
      return;
  }

  count = dims[0];

  valbuf = malloc(size*count);

  if (valbuf == NULL) {
      fprintf(stderr, "Error: malloc fialed for dimscale\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Sclose(ds);
      H5Aclose(attr);
            return;
        }

  /* fix memtype */
  
  status = H5Aread(attr,dt,valbuf);

  if (status < 0) {
      fprintf(stderr, "Error: Problems reading dimension names\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_dimscales", __FILE__, __LINE__);
      H5Tclose(dt);
      H5Sclose(ds);
      H5Aclose(attr);
            free(valbuf);
            return;
  }

  cp = valbuf;
  for (i = 0; i < count; i++ ) {
    sd_dim_id = SDgetdimid(sdsid,i);
    /* check error? */
    process_one_dimscale(dsetid,sd_dim_id,cp);
    cp += size;
  }

  H5Tclose(dt);
  H5Sclose(ds);
  H5Aclose(attr);
        free(valbuf);
        return;
}

/*****************************************************************************

  Routine: h5toh4()
 
  Description: This routine translates information from a HDF5 file into a
               HDF4 file.
           
  Input: h5_filename  - filename of HDF5 file,
         h4_filename  - filename of HDF4 file
 
  Output: function return  - error status

*****************************************************************************/

int h5toh4(char *h5_filename, char *h4_filename, int root)
{
    hid_t fid;
    hid_t gid;
    hid_t plist=H5P_DEFAULT;
    int status = 0;
    int32 hfile_id;
    int32 sd_id;
    op_data_t op_data;
    void *edata;
    /*hid_t (*func)(void*); */
    H5E_auto_t func;
    int32 gr_id;
    int32 an_id;
    int i = 0;

    find_objs_t *info = malloc(sizeof(find_objs_t));

    /* open hdf5 file */
    if ((fid = H5Fopen(h5_filename, H5F_ACC_RDONLY, plist)) <= 0) {
        fprintf(stderr, "Error: Unable to open file %s\n", h5_filename);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "h5toh4", __FILE__, __LINE__);
        free(info);
        return fid;
    }

    /* open root group */
    if ((gid = H5GOPEN (fid, "/")) <= 0 ) {
        fprintf(stderr, "Error: Unable to open root group\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "h5toh4", __FILE__, __LINE__);
        free(info);
        return gid;
    } else {
        /* open hdf4 file */
        if ((hfile_id = Hopen(h4_filename, DFACC_CREATE, 0)) <= 0) {
            fprintf(stderr, "Error: Unable to open file %s\n", h4_filename);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5toh4", __FILE__, __LINE__);
            free(info);
            return hfile_id;
        } else {
            if ((sd_id = SDstart(h4_filename, DFACC_RDWR)) <= 0) {
                fprintf(stderr, "Error: Unable to open file %s, using SDstart\n",
                        h4_filename);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "h5toh4", __FILE__, __LINE__);
                free(info);
                return sd_id;
            } else {

        /* Initialize GR interface */
                if ((gr_id = GRstart(hfile_id)) == FAIL) {
                    fprintf(stderr, "Error: Unable to inititalize GR interface\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "h5toh4", __FILE__, __LINE__);
                    free(info);
                    return FAIL;
                }  

                /* Initialize AN interface */
                if ((an_id = ANstart(hfile_id)) == FAIL) {
                    fprintf(stderr, "Error: Unable to inititalize AN interface\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "h5toh4", __FILE__, __LINE__);
                    free(info);
                    GRend(hfile_id);
                    return FAIL;
                }

                /* Initialize Vgroup interface */
                if ((status = Vstart(hfile_id)) != SUCCEED) {
                    fprintf(stderr, "Error: Unable to initialize Vgroup interface\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                    free(info);
                    GRend(hfile_id);
                    ANend(an_id);
                    return FAIL;
                }

                /* allocate and initialize internal data structure */
                init_table(&group_table);
                init_table(&type_table);
                init_table(&dset_table);
                init_prefix(&prefix, prefix_len);

                /* init the find_objs_t*/
                info->threshold = 0;
                info->prefix_len = prefix_len;
                info->prefix = prefix;
                info->group_table = group_table;
                info->type_table = type_table;
                info->dset_table = dset_table;
                info->status = status;

                /* Disable error reporting */
                H5EGET_AUTO (&func, &edata);
                H5ESET_AUTO (NULL, NULL);

                /* find all objects one time */
                if ((status = H5Giterate(fid, "/", NULL,
                                         (H5G_operator_t)find_objs,
                                         (void*)info)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to iterate over all of the groups\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                }

                /* Enable error reporting */
                H5ESET_AUTO(func, edata);

                if (status != SUCCEED) {
                    fprintf(stderr,"Error: internal error! \n");
                    goto done;
                }

                op_data.hfile_id = hfile_id;
                op_data.sd_id = sd_id;
                op_data.gr_id = gr_id;
                op_data.an_id = an_id;
                op_data.vgroup_id = 0;

                /* start at root group */
                /*if ((status = convert_group(gid, HDstrdup("/"), &op_data)) != SUCCEED) */
                if ((status = convert_group(gid, "/", &op_data)) != SUCCEED) {
                    fprintf(stderr, "Error: convert_group did not work for %s\n", "/");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                    status = FAIL;
                    goto done;
                }
                
                /* pkamat [MOD2] Process Root Group Attributes */
                if (process_rootgroup_attr(hfile_id, sd_id, gr_id, an_id) != SUCCEED) {
                    fprintf(stderr, "Error: Unable to process root group attributes\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                    status = FAIL;  
                    goto done;
                }  
                
               /* By default delete root group. If the option is set to not delete then skip this step. */
                if (root != TRUE) {
                    if ( -1 != rootgroup_ref)  {
                        if ((status = Vdelete(hfile_id, rootgroup_ref)) != SUCCEED) {
                            fprintf(stderr, "Error: Unable to delete root group from  file %s\n", h4_filename);
                            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                        "h5toh4", __FILE__, __LINE__);
                            status = FAIL;
                            goto done;
                        }
                    }
                }
                
                /* end pkamat [MOD2] */

                /* Terminate access to GR interface */
                if ((status = GRend(gr_id)) != SUCCEED) {
                   fprintf(stderr, "Error: Unable to terminate GR interface\n");
                   DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                   status = FAIL;
                   goto done;
                }

                /* Terminate access to AN interface */
                if ((status = ANend(an_id)) != SUCCEED) {
                   fprintf(stderr, "Error: Unable to terminate AN interface\n");
                   DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                   status = FAIL;
                   goto done;
                }

                /* Terminate access to Vgroup interface */
                if ((status = Vend(hfile_id)) != SUCCEED) {
                    fprintf(stderr, "Error: Unable to terminate Vgroup interface\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "h5toh4", __FILE__, __LINE__);
                    status = FAIL;
                    goto done;
                }
            }

            /* close hdf4 SDS */
            if ((status = SDend(sd_id)) != SUCCEED) {
                fprintf(stderr, "Error: Unable to close file %s, from SDstart\n",
                        h4_filename);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "h5toh4", __FILE__, __LINE__);
                status = FAIL;
                goto done;
            }
        }

        /* close hdf4 file */
        if ((status = Hclose(hfile_id)) != SUCCEED) {
            fprintf(stderr, "Error: Unable to close file %s\n", h4_filename);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5toh4", __FILE__, __LINE__);
            status = FAIL;
            goto done;
        }
    }

    if ((status = H5Gclose (gid)) != SUCCEED) {
        fprintf(stderr, "Error: Unable to close root group\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "h5toh4", __FILE__, __LINE__);
        status = FAIL;
        goto done;
    }

    if ((status = H5Fclose (fid)) != SUCCEED) {
        fprintf(stderr, "Error: Unable to close file %s\n", h5_filename);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "h5toh4", __FILE__, __LINE__);
        status = FAIL;
    }

done:
    free_table(&group_table);
    free_table(&dset_table);
    free_table(&type_table);
    free(info);
    if(prefix!=NULL)
        free(prefix);

    if(dimnames!=NULL) {
        for(i = 0;i<ndimns;i++){
           free(*dimnames);
           dimnames++;
        }
    }
    if(dimnamesptr!=NULL) free(dimnamesptr);
    return status;
}

/*-------------------------------------------------------------------------
 * Function:    convert_group
 *
 * Purpose:     Dump everything within the specified group
 *
 * Return:      status
 *
 * Programmer:  Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_group (hid_t gid, char *name, op_data_t *op_data)
{
    H5G_stat_t statbuf;
    int32 hfile_id;
    int32 vgroup_id;
    int32 obj_idx;
    int32 status;
    int idx;
    int flag;
    hsize_t  a_index = 0;
    
    if (strcmp(name, "HDF4_PALGROUP") == 0) {
        /* special group created by h4 to h5.  Suppress it. */
        return SUCCEED;
    }
    if (strcmp(name, "HDF4_DIMGROUP") == 0) {
        /* special group created by h4 to h5.  Suppress it. */
        return SUCCEED;
    }
    hfile_id = op_data->hfile_id;
    if ((vgroup_id = Vattach(hfile_id, -1, "w")) <= 0 ) {
        fprintf(stderr, "Error: Unable to create new vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        return vgroup_id;
    }

    /* pkamat. Storing the reference to the dummy root group. Will be deleted later by default, 
     * if the option to preserve the root group is not set.
    */

    if (strcmp(name, "/") == 0)
    {
        if ((rootgroup_ref = VQueryref(vgroup_id)) == FAIL) {
            fprintf(stderr, "Error: Unable to get ref from id\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5toh4", __FILE__, __LINE__);
            status = FAIL;
            return status;
        }
    }
    /* end pkamat */

    if ((status = Vsetname(vgroup_id, name)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set name on new vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        return status;
    }

    if ((status = Vsetclass(vgroup_id, "HDF5")) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set class on new vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        return status;
    }

    if (op_data->vgroup_id == 0) {
        obj_idx = -1; /* Indexes assigned below start from 0 */
    } else if ((obj_idx = Vinsert(op_data->vgroup_id, vgroup_id)) < 0) {
        fprintf(stderr, "Error: Index %d of the new vgroup is illegal\n",
                (int)obj_idx);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        return obj_idx;
    }

    op_data->vgroup_id = vgroup_id;
    op_data->sds_id = 0;
    op_data->vdata_id = 0;
    op_data->grimage_id = 0;
    op_data->obj_idx = obj_idx;

    /* hard link */
    if ((status = H5Gget_objinfo(gid, ".", TRUE, &statbuf)) != SUCCEED ) {
        fprintf(stderr, "Error: H5Gget_objinfo() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        return status;
    }

    if (strcmp(name,"/") == 0) {
        /* this is the root group, just iterate */
        if ((status = H5AITERATE(gid, &a_index, (H5A_operator_t)convert_attr, op_data)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to iterate over all of the attributes\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_group", __FILE__, __LINE__);
            return status;
        }
        if ((status = H5Giterate(gid, ".", NULL, (H5G_operator_t)convert_all,
                                 op_data)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to iterate over all of the groups\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_group", __FILE__, __LINE__);
            return status;
        }
    } else {
        if ((idx = get_table_idx(group_table, statbuf.objno)) < 0 ) {
            fprintf(stderr, "Error: object not found, %s\n", name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_group", __FILE__, __LINE__);
            status = FAIL;
        } else if((flag = get_tableflag(group_table,idx)) < 0 ) {
            fprintf(stderr, "Error: get_tableflag() should never return < 0\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_group", __FILE__, __LINE__);
            status = FAIL;
        } else if(flag == TRUE ) {
            /* this has already been converted, don't convert the
             * attributes again */
            if ((status = H5Giterate(gid, ".", NULL,
                                     (H5G_operator_t)convert_all,
                                     op_data)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to iterate over all of the groups\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_group", __FILE__, __LINE__);
                return status;
            }
        } else { /* flag == FALSE */
            /* this is now being converted */
            if ((status = set_tableflag(group_table,idx)) < 0 ) {
                fprintf(stderr, "Error: set_tableflag should never return < 0\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_group", __FILE__, __LINE__);
                return status;
            }
            if ((status = H5AITERATE(gid, &a_index,
                                     (H5A_operator_t)convert_attr,
                                     op_data)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to iterate over all of the attributes\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_group", __FILE__, __LINE__);
                return status;
            }
            if ((status = H5Giterate(gid, ".", NULL,
                                     (H5G_operator_t)convert_all,
                                     op_data)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to iterate over all of the groups\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_group", __FILE__, __LINE__);
                return status;
            }
        }
    }

    if ((status = Vdetach(vgroup_id)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to detach the new Vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_group", __FILE__, __LINE__);
        status = FAIL;
    }

    return status;
}

/*-------------------------------------------------------------------------
 * Function:    convert_dataset
 *
 * Purpose:     Convert the specified data set
 *
 * Return:      status
 *
 * Programmer:  Paul Harten
 *
 * Modifications:
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_dataset (hid_t did, char *name, op_data_t *op_data)
{
    hid_t  type;
    hid_t  space;
    hid_t  t_class;
    hid_t  mem_type;
    hid_t  type2;
    /* H5G_stat_t statbuf; */
    size_t typesize;
    int i;
    int idx;
    int32 dim_sizes[32], start[32], edges[32];
    int ndims;
    int ndimf;
    hsize_t dims[32];
    hsize_t maxdims[32];
    hsize_t dimf[4]; /* WHY this is hard-coded to 4 ??? Needs to be fixed or find the reason KY 2007-3-7 */
    int32 hfile_id;
    int32 sd_id;    
    int32 sds_id;
    int32 vdata_id;
    int32 vgroup_id;
    int32 n_values;
    int32 status;
    int32 h4_type;
    int32 recsize;

    int32 n_records;
    int32 num_of_recs;
    int32  record_pos;

    int nmembers;
    char *buffer=NULL; /* read/write buffer*/
    char fieldname_list[4096] = "\0";
    char *fieldname=NULL;
    hid_t fieldtype;
    int32 order;
    size_t offset;
    size_t offset_array[512];
    hid_t h4type_array[512];
    hid_t memtype_array[512];
    int32 order_array[512];
    
/* pkamat */
    char attr_value[256];

    hsize_t a_index = 0;
    
  /* pkamat [MOD3] Check if the dataset is an Image, Palette, Table or ordinary dataset. Image, Palettes and Tables
   * are identified by the value of CLASS attribute. If CLASS attribute is absent OR does not have the values 
   * "IMAGE", "PALETTE" or "TABLE" then it is a ordinary dataset. Here is where the processing branch outs. 
   * convert_image() is called for an image and convert_table() is called for a table. For a palette, no action is taken
   * as an image's palette is converted in the call to convert_image(). Thereby, any palette that is not being used is discared.
   * If it is an ordinary dataset, the processing is as before. 
   */


/* Image / Table / Palette Processing */
/* Needs to be fixed */
    if (debug) printf("converting dataset %s\n", name);

    if ((status = valueOfAttr(did, "CLASS", attr_value)) == FAIL ) {
        fprintf(stderr,"Error: problem with getting value of attribute\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        return FAIL;
    }

    if (status == SUCCEED) {      
        if (HDstrncmp(attr_value, "IMAGE", 5) == SUCCEED) {
            if (debug) printf("converting image\n");
            if ((status = convert_image (did, name, op_data)) == FAIL ) {
                fprintf(stderr, "Error: Cannot convert the image\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "convert_dataset", __FILE__, __LINE__);
            }
            return status;
        }

        if (HDstrncmp(attr_value, "PALETTE", 7) == SUCCEED) {
            return DSET_PALETTE;
        }

        if (HDstrncmp(attr_value, "TABLE", 5) == SUCCEED) {
            if (debug) printf("converting table\n");
            if ((status = convert_table (did, name, op_data)) == FAIL ) {
                fprintf(stderr, "Error: Cannot convert the table\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_dataset", __FILE__, __LINE__);
            }
            return status;
        }
    }
    /* end pkamat [MOD3] */

    /* hard link */
#if 0
    /* COMMENTED OUT FOR NOW */
    if ((status = H5Gget_objinfo(did, ".", TRUE, &statbuf)) != SUCCEED ) {
        fprintf(stderr, "Error: H5Gget_objinfo() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        return (status);
    }
#endif  /* 0 */

    if ((type = H5Dget_type(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((ndims = H5Sget_simple_extent_dims(space,dims,maxdims)) < 0 ) {
        fprintf(stderr, "Error: Problems getting ndims, dims, and maxdims of dataset\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = ndims;
        return status;
    }

    if ((t_class = H5Tget_class(type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting class\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    switch (t_class) {
    case H5T_INTEGER:
    case H5T_FLOAT:
        sd_id = op_data->sd_id;

#define NEWWAY
#ifdef NEWWAY
    if (FAIL == h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            break;
    }
#else
    if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            break;
    }

    if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            return status;
    }

    if ((typesize = H5Tget_size(mem_type)) <= 0) {
            fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            break;
    }
#endif  /* NEWWAY */

    if ((buffer = malloc(n_values*typesize)) == NULL) {
            fprintf(stderr, "Error: Problems with malloc of memory space\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            break;
    }

        if ((status = H5Dread(did, mem_type, space, space, H5P_DEFAULT, buffer)) != SUCCEED) {
            fprintf(stderr, "Error: Problems with H5Dread\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        for (i = 0; i < ndims; ++i) {
            if (maxdims[i] == H5S_UNLIMITED) {
                if ( i == 0 ) {
                    /* this is how HDF4 communicates unlimited dimension */
                    dim_sizes[0] = 0;
                } else {
                    dim_sizes[i] = (int32)dims[i];
                }
            } else {
                dim_sizes[i] = (int32)maxdims[i];
            }

            start[i] = 0;
            edges[i] = (int32)dims[i];
    }

    if ((sds_id = SDcreate(sd_id, name, h4_type, ndims, dim_sizes)) <= 0 ) {
        fprintf(stderr, "Error: Unable to create SDS %s.\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
        status = FAIL;
        break;
    }

/* do all the dim scales */
    process_dimscales(did,sds_id);
    op_data->sds_id = sds_id;
    if ((status = SDwritedata(sds_id, start, NULL, edges, buffer)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to write SDS %s.\n", name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
    }
    if ((status = H5AITERATE(did, &a_index, (H5A_operator_t)convert_attr, op_data)) < 0 ) {
            fprintf(stderr,"Error: iterate over attributes\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
    }
    if ((status = SDendaccess(sds_id)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to end access to SDS %s.\n",name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_dataset", __FILE__, __LINE__);
    }
    break;

    case H5T_TIME:
        fprintf(stderr,"Warning: H5T_TIME not yet implemented.\n");
        break;

    case H5T_STRING:
        if (ndims == 1)
            convert_dataset_string(did, name, op_data);
        else
            fprintf(stderr, "Warning: HDF5 datasets of H5T_STRING type with ndims > 1 are not converted.\n");

        break;

    case H5T_BITFIELD:
        fprintf(stderr,"Warning: H5T_BITFIELD not yet implemented.\n");
        break;

    case H5T_OPAQUE:
        fprintf(stderr,"Warning: H5T_OPAQUE not yet implemented.\n");
        break;

    case H5T_ARRAY:
        fprintf(stderr,"Warning: H5T_OPAQUE not yet implemented.\n");
        break;

    case H5T_COMPOUND:
        if (ndims == 1) {
            if ((nmembers = H5Tget_nmembers(type)) <= 0 ) {
                fprintf(stderr, "Error: Unable to get information about compound datatype %d\n",nmembers);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            offset = 0;

            for (idx = 0; idx < nmembers; ++idx) {
                if ((fieldtype = H5Tget_member_type(type, idx)) < 0 ) {
                    fprintf(stderr,
                            "Error: H5 datasets of H5T_COMPOUND type with fieldtype, idx %d.\n",
                             idx);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    break;
                }

                /* Special case for array fields */
                if (H5Tget_class(fieldtype) == H5T_ARRAY) {
                    hid_t   arr_base_type;

                    /* Get the number of dimensions */
                    if ((ndimf = H5Tget_array_ndims(fieldtype)) < 0 || ndimf > H5S_MAX_RANK ) {
                        fprintf(stderr, "Error: rank of members of compound type should not be %d\n",
                                ndimf);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    /* Get the dimensions and dimension permutations */
                    if (H5TGET_ARRAY_DIMS(fieldtype,dimf,NULL) < 0) {
                        fprintf(stderr, "Error: cannot retrieve dimensions for array\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    /* Get the 'real' field type */
                    if ((arr_base_type=H5Tget_super(fieldtype)) < 0) {
                        fprintf(stderr, "Error: cannot retrieve base type for array\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    if (H5Tclose(fieldtype) < 0 ) {
                        fprintf(stderr,"Error: closing type\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    /* Assign the array's base type as the field type for future use */
                    fieldtype = arr_base_type;
                } else {
                    ndimf = 0;
                }

#ifdef NEWWAY
                if (FAIL==h5atomic_type_to_h4type(fieldtype, &mem_type, &typesize, &h4_type)){
                    fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }
#else
                if ((h4_type = h5type_to_h4type(fieldtype)) < 0 ) {
                    fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    break;
                }

                if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
                    fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    return FAIL;
                }

                if ((typesize = H5Tget_size(mem_type)) <= 0) {
                    fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }
#endif  /* NEWWAY */

/* Consider the HDF5 string datatype */
                
                order = 1;
                {
                int temp_i;
                for(temp_i=0;temp_i<ndimf;temp_i++)
                   order *= dimf[temp_i];
                if (H5T_STRING == H5Tget_class(fieldtype))
                   order *= typesize;
                }

                h4type_array[idx] = h4_type;  /* used for VSfdefine */
                memtype_array[idx] = mem_type;  /* used during the build of the memory compound type */
                offset_array[idx] = offset;  /* used during the build of the memory compound type */
                order_array[idx] = order;  /* used for VSfdefine */

                if(H5T_STRING == H5Tget_class(fieldtype)) 
                  offset +=order;
                else 
                  offset += order * typesize;  /* calculating packed size of memory compound type */
            }

            hfile_id = op_data->hfile_id;
            vgroup_id = op_data->vgroup_id;

            if ((vdata_id = VSattach(hfile_id, -1, "w")) <= 0 ) {
                fprintf(stderr, "Error: Unable to create vdata %s.\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }

#if 0
/*
 * This step is done during the convert_shared_dataset() call instead of here.
 */
            if (debug) printf("calling Vinsert\n");
            if ((idx = Vinsert(vgroup_id, vdata_id)) < 0 ) {
                fprintf(stderr, "Error: Unable to insert vdata %s.\n", name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
#endif  /* 0 */

            op_data->vdata_id = vdata_id;

            if ((status = VSsetname(vdata_id, name)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set vdata name %s.\n", name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            if ((status = VSsetclass(vdata_id, "HDF5")) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set class on vdata %s\n", name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            if ((type2 = H5Tcreate(H5T_COMPOUND, (size_t)offset)) <= 0 ) {
                fprintf(stderr, "Error: unable to execute H5Tcreate()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            for (idx = 0; idx < nmembers; ++idx) {
                /* Special case for array fields */
                if(H5Tget_member_class(type,idx)==H5T_ARRAY) {
                    hid_t   arr_type;

                    if ((arr_type = H5Tget_member_type(type, idx)) < 0 ) {
                        fprintf(stderr,"Error: H5 datasets of H5T_COMPOUND type with fieldtype, idx %d.\n",idx);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        break;
                    }

                    /* Get the number of dimensions */
                    if ((ndimf = H5Tget_array_ndims(arr_type)) < 0 || ndimf > H5S_MAX_RANK ) {
                        fprintf(stderr, "Error: rank of members of compound type should not be %d\n",ndimf);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    /* Get the dimensions and dimension permutations */
                    if (H5TGET_ARRAY_DIMS(arr_type,dimf,NULL) < 0) {
                        fprintf(stderr, "Error: cannot retrieve dimensions for array\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    if (H5Tclose(arr_type) < 0 ) {
                        fprintf(stderr, "Error: closing type\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }
                } else {
                    ndimf = 0;
                }

                if ((fieldname = H5Tget_member_name(type, idx)) == NULL ) {
                    fprintf(stderr, "Error: Unable to get fieldname for compound type, idx %d\n",  idx);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    break;
                }


                /* Consider the fixed-string datatype */
                if (H5T_STRING == H5Tget_class(memtype_array[idx])) 
                     offset = 0;
                else {
                    if ((int)(offset = H5Tget_offset(memtype_array[idx])) < 0 || offset >= 128 ) {

                        fprintf(stderr, "Error: H5Tget_offset() is returning a bad value %d\n",(int)offset);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                }


                if (ndimf == 0 ) {
                    if ((status = H5Tinsert(type2, fieldname,
                                            offset_array[idx] + offset,
                                            memtype_array[idx])) != SUCCEED ) {
                        fprintf(stderr, "Error: Problems inserting field into compound datatype\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }
                } else {
                    hid_t   arr_type;

                    /* Create the array datatype */
                    if ((arr_type = H5TARRAY_CREATE(memtype_array[idx], ndimf, dimf, NULL)) < 0 ) {
                        fprintf(stderr,"Error: cannot create array datatype\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        break;
                    }

                    if ((status = H5Tinsert(type2,fieldname,offset_array[idx]+offset,arr_type)) != SUCCEED ) {
                        fprintf(stderr, "Error: Problems inserting field into compound datatype\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }

                    if (H5Tclose(arr_type) < 0 ) {
                        fprintf(stderr,"Error: closing type\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_dataset", __FILE__, __LINE__);
                        return FAIL;
                    }
                }

                if ((status = VSfdefine(vdata_id, fieldname,
                                        h4type_array[idx],
                                        order_array[idx])) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set field %d\n", idx);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_dataset", __FILE__, __LINE__);
                    break;
                }

                strcat(fieldname_list,fieldname);

                if (idx<nmembers-1)
                    strcat(fieldname_list,", ");

#if H5_VERSION_GE(1,8,13)
        /* use library free function for 1.8.13 and above */
            H5free_memory(fieldname);
#else
            free(fieldname);
#endif
            }
            if ((status = VSsetfields(vdata_id, fieldname_list)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set fieldname list  %s\n", name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            if ((status = VSsetinterlace(vdata_id, FULL_INTERLACE)) != SUCCEED ) {
                fprintf(stderr,
                        "Error: Unable to set FULL_INTERLACE mode, status %d\n",
                        (int)status);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            if ((recsize = H5Tget_size(type2)) <= 0 ) {
                fprintf(stderr, "Error: Unable to get record size %d\n", (int)recsize);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }

            /* Since the space is rank 1, n_records does not
             * depend on maxdims. */
            n_records = n_values;

            if ((buffer = malloc((unsigned)(n_records*recsize))) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }

            if ((status = H5Dread(did, type2, space, space,
                                  H5P_DEFAULT, buffer)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Dread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }

            if ((status = H5Tclose(type2)) < 0 ) {
                fprintf(stderr,"Error: closing type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }

            if ((record_pos = VSseek(vdata_id, 0)) != 0 ) {
                fprintf(stderr,
                        "Error: Could not seek the beginning of the Vdata, %d\n",
                        (int)record_pos);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = record_pos;
                break;
            }

            if ((num_of_recs = VSwrite(vdata_id, (void *)buffer,
                                       n_records, FULL_INTERLACE)) != n_records ) {
                fprintf(stderr, "Error: Only able to write %d of %d records\n",
                        (int)num_of_recs, (int)n_records);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = num_of_recs;
                break;
            }

            /* there are only vdata attributes, no field attributes */
            if ((status = H5AITERATE(did, &a_index,
                                     (H5A_operator_t)convert_attr,
                                     op_data)) < 0 ) {
                fprintf(stderr,"Error: iterate over attributes\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }
            if ((status = VSdetach(vdata_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to detach to vdata %s.\n", name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                break;
            }
        } else {
            fprintf(stderr, "Warning: HDF5 datasets of H5T_COMPOUND type with ndims > 1 are not converted.\n");
        }

    break;

    default:
        fprintf(stderr, "Error:  class not found\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
    }

    if (H5Tclose(type) < 0 ) {
        fprintf(stderr, "Error: closing type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
    }

    if (H5Sclose(space) < 0 ) {
        fprintf(stderr, "Error: closing space\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
    }
    free(buffer);
    status = DSET;
    return status;
}

/*-------------------------------------------------------------------------
 * Function:    convert_attr
 *
 * Purpose:     dump the attribute
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 * Programmer: Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/

herr_t
convert_attr (hid_t attr, char *attr_name, op_data_t *op_data)
{
    hid_t  attr_id;
    hid_t type;
    hid_t space;
    hid_t mem_type;
    hid_t t_class;
    size_t typesize;
    char   *attr_values=NULL;
    int32  status;
    int32  h4_type;
    int32  sds_id;
    int32  an_id;
    int32  ann_id;
    int32  vdata_id;
    int32  vgroup_id;
    int32  n_values;
    int32  order;
    hid_t fxdlenstr;
    size_t lenstr;
    H5T_cset_t cset;
    H5T_str_t strpad;
    char * ann_value;

    sds_id = op_data->sds_id;
    vdata_id = op_data->vdata_id;
    vgroup_id = op_data->vgroup_id;
    an_id = op_data->an_id;

    if (strncmp(attr_name,"HDF4_",5) == 0) {
        if ((strncmp(attr_name,"HDF4_FILE_DESCRIPTION",21) != 0)
          && (strncmp(attr_name,"HDF4_FILE_LABEL",15) != 0)) {
      
            status = SUCCEED;
            return status;
        }
    }
    if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) {
        if ((type = H5Aget_type(attr_id)) <= 0) {
            fprintf(stderr, "Error: H5Aget_type() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
        }

        if ((t_class = H5Tget_class(type)) < 0 ) {
            fprintf(stderr,"Error: problem with getting class\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_attr", __FILE__, __LINE__);
            status = t_class;
            return status;
        }

        switch (t_class) {
        case H5T_INTEGER:
        case H5T_FLOAT:
            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

#ifdef NEWWAY
            if (FAIL==h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
#else
            if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((typesize = H5Tget_size(mem_type)) <= 0) {
                fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
#endif  /* NEWWAY */

            if ((attr_values = malloc(n_values*typesize)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                free (attr_values);
                return status;
            }
            if (strncmp(attr_name,"HDF4_FILE_DESCRIPTION",21) == 0) {
            /* create file descr */
                if ((ann_id = ANcreatef(an_id, AN_FILE_DESC)) == FAIL)
                {
                    fprintf(stderr, "Error: ANcreatef() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_attr", __FILE__, __LINE__);
                    free (attr_values);
                    return FAIL;
                }
                ann_value = stringify(attr_values, n_values, h4_type);
                if ((status = ANwriteann(ann_id, ann_value, (int32)strlen(ann_value))) == FAIL)
                {
                    fprintf(stderr, "Error: ANwriteann() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                     "create_attr", __FILE__, __LINE__);
                    free (attr_values);
                    free(ann_value);
                    ANendaccess(ann_id);
                    return status;
                }
                if ((status = ANendaccess(ann_id)) == FAIL)
                {
                    fprintf(stderr, "Error: ANendaccess() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "create_attr", __FILE__, __LINE__);
                    free (attr_values);
                    free(ann_value);
                    return status;
                }
            } else if (strncmp(attr_name,"HDF4_FILE_LABEL",15) == 0) {
            /* create file label */
                if ((ann_id = ANcreatef(an_id, AN_FILE_LABEL)) == FAIL)
                {
                    fprintf(stderr, "Error: ANcreatef() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    free (attr_values);
                    return FAIL;
                }
                ann_value = stringify(attr_values,n_values, h4_type);
                if ((status = ANwriteann(ann_id, ann_value, (int32)strlen(ann_value))) == FAIL)
                {
                    fprintf(stderr, "Error: ANwriteann() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "create_attr", __FILE__, __LINE__);
                    free (attr_values);
                    free(ann_value);
                    ANendaccess(ann_id);
                    return status;
                }
                if ((status = ANendaccess(ann_id)) == FAIL)
                {
                    fprintf(stderr, "Error: ANendaccess() did not work\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "create_attr", __FILE__, __LINE__);
                    free (attr_values);
                    free(ann_value);
                    return status;
                }
        
           } else if (sds_id != 0) {
                if ((status = SDsetattr(sds_id, attr_name, h4_type,
                                        n_values, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free (attr_values);
                    return status;
                }
            } else if (vdata_id != 0) {
                if ((status = VSsetattr(vdata_id, -1, attr_name, h4_type,
                                        n_values, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free (attr_values);
                    return status;
                }
            } else {
                    if((status = Vsetattr(vgroup_id, attr_name, h4_type,
                                          n_values, attr_values)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                free (attr_values);
                return status;
            }

            }
            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                free (attr_values);
                return status;
            }

#if 0
            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
    free (attr_values);
                return status;
            }
#endif

            status = SUCCEED;
            free(attr_values);
            break;

        case H5T_TIME:
            fprintf(stderr,"Warning: H5T_TIME attribute not yet implemented.\n");
            break;

        case H5T_STRING:
            fxdlenstr = type;
            h4_type = DFNT_CHAR;

            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((mem_type = H5Tcopy(H5T_C_S1)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = mem_type;
                return status;
            }

            if ((lenstr = H5Tget_size(fxdlenstr)) <= 0 ) {
                fprintf(stderr, "Error: size of fixed length string type should not be %d\n",(int)lenstr);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return lenstr;
            }

            if ((status = H5Tset_size(mem_type,lenstr)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_size()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return status;
            }

            strpad = H5Tget_strpad(fxdlenstr);

            if ((strpad != H5T_STR_NULLTERM) && (strpad != H5T_STR_NULLPAD)
                        && (strpad != H5T_STR_SPACEPAD)) {
                fprintf(stderr, "Error: Invalid string padding value, %d\n",(int)strpad);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return strpad;
            }

            if ((status = H5Tset_strpad(mem_type, H5T_STR_SPACEPAD)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_strpad()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return status;
            }

            if ((cset = H5Tget_cset(fxdlenstr)) != H5T_CSET_ASCII ) {
                fprintf(stderr, "Error: cset value != %d\n",(int)H5T_CSET_ASCII);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return cset;
            }

            if ((status = H5Tset_cset(mem_type,cset)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_cset()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                return status;
            }

            order = n_values * lenstr;

            if ((attr_values = malloc((unsigned)order)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
#if 0
      if (strncmp(attr_name,"HDF4_FILE_DESCRIPTION",21) == 0) {
    /* create file descr */
    if ((ann_id = ANcreatef(an_id, AN_FILE_DESC)) == FAIL)
    {
      fprintf(stderr, "Error: ANcreatef() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_attr", __FILE__, __LINE__);
    free (attr_values);
      return FAIL;
    }
    //ann_value = stringify(attr_values, n_values, h4_type);
    //if ((status = ANwriteann(ann_id, ann_value, (int32)strlen(ann_value))) == FAIL)
    if ((status = ANwriteann(ann_id, attr_values, (int32)strlen(attr_values))) == FAIL)
    {
      fprintf(stderr, "Error: ANwriteann() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "create_attr", __FILE__, __LINE__);
      free (attr_values);
      ANendaccess(ann_id);
      return status;
    }
    if ((status = ANendaccess(ann_id)) == FAIL)
    {
      fprintf(stderr, "Error: ANendaccess() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "create_attr", __FILE__, __LINE__);
      free (attr_values);
      return status;
    }
      } else if (strncmp(attr_name,"HDF4_FILE_LABEL",15) == 0) {
    /* create file label */
    if ((ann_id = ANcreatef(an_id, AN_FILE_LABEL)) == FAIL)
    {
      fprintf(stderr, "Error: ANcreatef() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_attr", __FILE__, __LINE__);
            free (attr_values);
      return FAIL;
    }
    //ann_value = stringify(attr_values,n_values, h4_type);
    //if ((status = ANwriteann(ann_id, ann_value, (int32)strlen(ann_value))) == FAIL)
    if ((status = ANwriteann(ann_id, attr_values, (int32)strlen(attr_values))) == FAIL)
    {
      fprintf(stderr, "Error: ANwriteann() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "create_attr", __FILE__, __LINE__);
      free (attr_values);
      ANendaccess(ann_id);
      return status;
    }
    if ((status = ANendaccess(ann_id)) == FAIL)
    {
      fprintf(stderr, "Error: ANendaccess() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "create_attr", __FILE__, __LINE__);
      free (attr_values);
      return status;
    }
      }
#endif 
      /*else if (sds_id != 0) */
//#if 0
      if (sds_id != 0) {
                if ((status = SDsetattr(sds_id, attr_name, h4_type,
                                        order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    status = FAIL;
                    return status;
                }
            } else if (vdata_id != 0) {
                if ((status = VSsetattr(vdata_id, -1, attr_name,
                                        h4_type, order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    status = FAIL;
                    return status;
                }
            } else {
                if ((status = Vsetattr(vgroup_id, attr_name, h4_type,
                                       order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_attr", __FILE__, __LINE__);
                    status = FAIL;
                    return status;
                }
            }
            if((status = H5Tclose(mem_type)) != SUCCEED) {
                fprintf(stderr, "Error: Problems closing H5Tclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

#if 0
            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
#endif

            status = SUCCEED;
            free(attr_values);
            break;

        case H5T_BITFIELD:
            fprintf(stderr,"Warning: H5T_BITFIELD attribute not yet implemented.\n");
            break;

        case H5T_OPAQUE:
            fprintf(stderr,"Warning: H5T_OPAQUE attribute not yet implemented.\n");
            break;

        case H5T_COMPOUND:
            fprintf(stderr,"Warning: H5T_COMPOUND attribute not implemented.\n");
            break;

        case H5T_REFERENCE:
            fprintf(stderr,"Warning: H5T_REFERENCE attribute not implemented.\n");
            break;
        default:
            fprintf(stderr,"Error: class not found\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_attr", __FILE__, __LINE__);
            status = FAIL;
        }

        if ((status = H5Tclose(type)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Tclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
        }
    } else {
        status = FAIL;
    }

    if(attr_id!=-1) {
       if ((status = H5Aclose(attr_id)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Aclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
       }
    }
    return status;
}

/*-------------------------------------------------------------------------
 * Function:    convert_all
 *
 * Purpose:     Dump everything in the specified object
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 * Programmer:  Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_all (hid_t group, char *name, op_data_t *op_data)
{
    hid_t obj;
    H5G_stat_t statbuf;
    int status;
    op_data_t op_data_save;
    int idx;
    int flag;
    void *edata;
   /* hid_t (*func)(void*);*/
    H5E_auto_t func;

    op_data_save = *op_data;

    if ((status = H5Gget_objinfo(group, name, FALSE, &statbuf)) != SUCCEED ) {
        fprintf(stderr,"Error: H5Gget_objinfo() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_all", __FILE__, __LINE__);
        return status;
    }

    switch (statbuf.type) {
    case H5G_LINK: /* this is a soft link only */
        /* Disable error reporting */
        H5EGET_AUTO (&func, &edata);
        H5ESET_AUTO (NULL, NULL);

        /* test to see if object exists */
        if ((status = H5Gget_objinfo(group, name, TRUE, NULL)) != SUCCEED )
            fprintf(stderr,"Warning: the object pointed to by the symbolic link \"%s\" does not exist.\n",name);

        /* Enable error reporting */
        H5ESET_AUTO (func, edata);

        if (status != SUCCEED)
            break;

        /* follow link for type */
        if ((status = H5Gget_objinfo(group, name, TRUE, &statbuf)) != SUCCEED ) {
            fprintf(stderr,"Error: H5Gget_objinfo() did not work\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_all", __FILE__, __LINE__);
            return status;
        }

        if (statbuf.type == H5G_DATASET ) {
            if ((idx = get_table_idx(dset_table, statbuf.objno)) < 0 ) {
                fprintf(stderr,"Error: object not found\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
            } else if ((flag = get_tableflag(dset_table,idx)) < 0 ) {
                fprintf(stderr,"Error: get_tableflag() should never return < 0\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
            } else if (flag == TRUE) {
                /* this has already been converted, add as a tag/ref */
                if ((obj = H5DOPEN (group, name)) <= 0 ) {
                    fprintf(stderr,"Error: Unable to open H5 dataset\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    return obj;
                } else {
                    if ((status = convert_shared_dataset(obj, idx, op_data, DSET)) != SUCCEED ) {
                        fprintf(stderr,"Error: Unable to convert to tag/ref\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                        status = FAIL;
                   }
                }

                if ((status = H5Dclose(obj)) != SUCCEED) {
                    fprintf(stderr,"Error: Unable to close H5 dataset %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }
            } else { /* flag == FALSE */
                if ((obj = H5DOPEN (group, name)) <= 0 ) {
                    fprintf(stderr,"Error: Unable to open H5 dataset\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    return obj;
                } else {
                    if (( status = convert_dataset (obj, name, op_data)) == FAIL) {
                        fprintf(stderr,"Error: convert_dataset did not work for %s\n",name);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_all", __FILE__, __LINE__);
                        status = FAIL;
                        break;
                    }

                    if (status != DSET_PALETTE) /* pkamat */
                    {
                        if ((status = convert_shared_dataset(obj, idx, op_data, status)) != SUCCEED ) {
                            fprintf(stderr,"Error: Unable to convert to tag/ref\n");
                            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_all", __FILE__, __LINE__);
                            status = FAIL;
                        }
                    }

                    if ((status = set_tableflag(dset_table,idx)) != SUCCEED) {
                        fprintf(stderr,"Error: set_tableflag() did not work for %s\n", name);
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_all", __FILE__, __LINE__);
                        break;
                    }
                }

                if ((status = H5Dclose(obj)) != SUCCEED) {
                   fprintf(stderr,"Error: Unable to close H5 dataset %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                   status = FAIL;
                   break;
               }
           }
           } else if (statbuf.type == H5G_GROUP ) {
               if ((idx = get_table_idx(group_table, statbuf.objno)) < 0 ) {
                   fprintf(stderr,"Error: object not found\n");
                   DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                   status = FAIL;
               } else if ((flag = get_tableflag(group_table,idx)) < 0 ) {
                   fprintf(stderr,"Error: get_tableflag() should never return < 0\n");
                   DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                   status = FAIL;
               } else if(flag == TRUE ) {
                   if (( status = convert_shared_group (group, idx, op_data)) != SUCCEED) {
                       fprintf(stderr,"Error: convert_group did not work for %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }
            } else {
                /* flag == FALSE */
                if ((obj = H5GOPEN (group, name)) <= 0 ) {
                    fprintf(stderr,"Error: Unable to open group\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    return obj;
                } else if (( status = convert_group (obj, name, op_data)) != SUCCEED) {
                    fprintf(stderr,"Error: convert_group did not work for %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }

                if ((status = H5Gclose(obj)) != SUCCEED) {
                    fprintf(stderr,"Error: Unable to close group %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }
            }
        }

        break;

    case H5G_GROUP:
        if ((idx = get_table_idx(group_table, statbuf.objno)) < 0 ) {
            fprintf(stderr,"Error: object not found\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_all", __FILE__, __LINE__);
            status = FAIL;
        } else if((flag = get_tableflag(group_table,idx)) < 0 ) {
            fprintf(stderr,"Error: get_tableflag() should never return < 0\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_all", __FILE__, __LINE__);
            status = FAIL;
        } else if (flag == TRUE ) {
            if (( status = convert_shared_group (group, idx, op_data)) != SUCCEED) {
                fprintf(stderr,"Error: convert_group did not work for %s\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
        } else {
            /* flag == FALSE */
            if ((obj = H5GOPEN (group, name)) <= 0 ) {
                fprintf(stderr,"Error: Unable to open group\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                return obj;
            } else if (( status = convert_group (obj, name, op_data)) != SUCCEED) {
                fprintf(stderr,"Error: convert_group did not work for %s\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
                break;
            }

            if ((status = H5Gclose(obj)) != SUCCEED) {
                fprintf(stderr,"Error: Unable to close group %s\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
        }

        break;

    case H5G_DATASET:
        
        if ((idx = get_table_idx(dset_table, statbuf.objno)) < 0 ) {
            fprintf(stderr,"Error: object not found\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_all", __FILE__, __LINE__);
            status = FAIL;
        } else if((flag = get_tableflag(dset_table,idx)) < 0 ) {
            fprintf(stderr,"Error: get_tableflag() should never return < 0\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_all", __FILE__, __LINE__);
            status = FAIL;
        } else if (flag == TRUE ) {
            /* this has already been converted, add as a tag/ref */
            if ((obj = H5DOPEN (group, name)) <= 0 ) {
                fprintf(stderr,"Error: Unable to open H5 dataset\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                return obj;
            } 
            else {
                if ((status = convert_shared_dataset(obj, idx, op_data, DSET)) != SUCCEED ) {
                    fprintf(stderr,"Error: Unable to convert to tag/ref\n");
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                }
            }

            if ((status = H5Dclose(obj)) != SUCCEED) {
                fprintf(stderr,"Error: Unable to close H5 dataset %s\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
        } else {
            /* flag == FALSE */
            if ((obj = H5DOPEN (group, name)) <= 0 ) {
                fprintf(stderr,"Error: Unable to open H5 dataset\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                return obj;
            } else {
                if (( status = convert_dataset (obj, name, op_data)) == FAIL) {
                    fprintf(stderr,"Error: convert_dataset did not work for %s\n",name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    status = FAIL;
                    break;
                }

                if (status != DSET_PALETTE) /* pkamat */
                {
                    if ((status = convert_shared_dataset(obj, idx, op_data, status)) != SUCCEED ) {
                        fprintf(stderr,"Error: Unable to convert to tag/ref\n");
                        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                        status = FAIL;
                    }
                }
                if(( status = set_tableflag(dset_table,idx)) != SUCCEED ) {
                    fprintf(stderr,"Error: set_tableflag() did not work for %s\n", name);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_all", __FILE__, __LINE__);
                    break;
                }
            }

            if ((status = H5Dclose(obj)) != SUCCEED) {
                fprintf(stderr,"Error: Unable to close H5 dataset %s\n",name);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_all", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
        }

        break;

    case H5G_TYPE:
        /* object is ignored */
        break;

    default:
        fprintf (stderr,"Unknown Object %s\n", name);
        status = FAIL; 
        break;
    }

    *op_data = op_data_save;
    return SUCCEED;
}


/*-------------------------------------------------------------------------
 * Function:    convert_shared_dataset
 *
 * Purpose:     Handle a shared dataset which has already been converted.
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 * Programmer:  Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_shared_dataset(hid_t did, int idx, op_data_t *op_data, int dset_type)
{
    int status=SUCCEED;
    int32 vgroup_id;
    char *dataset_name=NULL;
    char *dataset_name2=NULL;
    int32 hfile_id;
    int32 sd_id;
    int32 sds_id = FAIL;
    int32 sds_ref;    
    int32 vdata_ref;
    int32 sds_index = FAIL;
    int32 numtagref;
    hid_t  type;
    hid_t space;
    hid_t t_class;
    hsize_t dims[32];
    hsize_t maxdims[32];
    int n_values;
    int ndims;

    /* PMK */
    int32 gr_id;
    int32 grimage_id;
    int32 grimage_index;
    int32 grimage_ref;
    
    vgroup_id = op_data->vgroup_id;

    if ((dataset_name = get_objectname(dset_table, idx)) == NULL ) {
        fprintf(stderr,"Error: get_objectname() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "convert_shared_dataset", __FILE__, __LINE__);
        return status;
    }

    if ((dataset_name2 = strrchr(dataset_name,'/')) == NULL) {  /* find last "/" in dataset_name */
        dataset_name2 = dataset_name;        /* no "/"s were found */
    } 
    else {
        dataset_name2 = dataset_name2 + sizeof(char);    /* 1 character past last "/" */
    }

    if ((type = H5Dget_type(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_shared_dataset", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_dataset", __FILE__, __LINE__);
        status = FAIL;
       return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "convert_shared_dataset", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((ndims = H5Sget_simple_extent_dims(space,dims,maxdims)) < 0 ) {
        fprintf(stderr, "Error: Problems getting ndims, dims, and maxdims of dataset\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "convert_shared_dataset", __FILE__, __LINE__);
        status = ndims;
        return status;
    }

    if ((t_class = H5Tget_class(type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting class\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "convert_shared_dataset", __FILE__, __LINE__);
        status = t_class;
        return status;
    }


    if (dset_type == DSET_IMAGE) {
        if (t_class != H5T_INTEGER && t_class != H5T_FLOAT) {
          fprintf (stderr,"Image data can only be int or float.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_shared_dataset", __FILE__, __LINE__);
            return sds_index;  
        }
    }

    switch (t_class) {
    case H5T_INTEGER:
    case H5T_FLOAT:

    /* pkamat [MOD4] 
     If the type of dataset is image (DSET_IMAGE), use the image interface to add the tags. 
     If it is an ordinary dataset (DSET) use the SD interface. 
    */

    if (dset_type == DSET) {      
        sd_id = op_data->sd_id;

        if ((sds_index = SDnametoindex(sd_id, dataset_name2)) < 0 ) {
           fprintf (stderr,"Error: Problem with SDnametoindex().\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
           return sds_index;
        }

        if ((sds_id = SDselect(sd_id, sds_index)) < 0 ) {
           fprintf (stderr,"Error: Problem with SDselect().\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
           return sds_id;
       }

       if ((sds_ref = SDidtoref(sds_id)) < 0 ) {
          fprintf (stderr,"Error: Problem with SDidtoref().\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
          return sds_ref;
       }

       if ((numtagref = Vaddtagref(vgroup_id, DFTAG_NDG, sds_ref)) < 0 ) {
          fprintf (stderr,"Error: Problem with Vaddtagref().\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
          return numtagref;
      }

    }
    else {
        gr_id = op_data->gr_id;      
        if ((grimage_index = GRnametoindex(gr_id, dataset_name2)) < 0 ) {
            fprintf (stderr,"Error: Problem with GRnametoindex().\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
            return grimage_index;
        }

        if ((grimage_id = GRselect(gr_id, grimage_index)) < 0 ) {
            fprintf (stderr,"Error: Problem with GRselect().\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
            return grimage_id;
        }

        if ((grimage_ref = GRidtoref(grimage_id)) < 0 ) {
           fprintf (stderr,"Error: Problem with GRidtoref().\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
           return grimage_ref;
        }

        if ((numtagref = Vaddtagref(vgroup_id, DFTAG_RIG, grimage_ref)) < 0 ) {
           fprintf (stderr,"Error: Problem with Vaddtagref().\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
           return numtagref;
        }
        if ((status = GRendaccess(grimage_id)) < 0 ) {
            fprintf (stderr,"Error: Problem with GRendaccess().\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_shared_dataset", __FILE__, __LINE__);
            return status;

        }
    }

    break;

    case H5T_TIME:
        fprintf(stderr,"Error: H5T_TIME not yet implemented.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_dataset", __FILE__, __LINE__);
        break;

    case H5T_STRING:
        hfile_id = op_data->hfile_id;

        if (ndims == 1) {
            if ((vdata_ref = VSfind(hfile_id,dataset_name2)) <= 0 ) {
                fprintf (stderr,"Error: Problem with VSfind().\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_shared_dataset", __FILE__, __LINE__);
                return vdata_ref;
            }

            if ((numtagref = Vaddtagref(vgroup_id, DFTAG_VH, vdata_ref)) < 0 ) {
                fprintf (stderr,"Error: Problem with Vaddtagref().\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_shared_dataset", __FILE__, __LINE__);
                return numtagref;
            }

        }

        break;

    case H5T_BITFIELD:
        fprintf(stderr,"Error: H5T_BITFIELD not yet implemented.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_dataset", __FILE__, __LINE__);
        break;

    case H5T_OPAQUE:
        fprintf(stderr,"Error: H5T_OPAQUE not yet implemented.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_dataset", __FILE__, __LINE__);
        break;

    case H5T_COMPOUND:
        hfile_id = op_data->hfile_id;
        if (ndims == 1) {
            if (debug1) printf("Writing tag of vdata\n");
            if ((vdata_ref = VSfind(hfile_id,dataset_name2)) <= 0 ) {
                fprintf (stderr,"Error: Problem with VSfind().\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_shared_dataset", __FILE__, __LINE__);
                return vdata_ref;
            }

/*      if ((idx = Vinsert(vgroup_id, vdata_id)) < 0 ) {
        fprintf(stderr, "Error: Unable to insert vdata %s.\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_dataset", __FILE__, __LINE__);
        return FAIL; 
      }
*/
            if ((numtagref = Vaddtagref(vgroup_id, DFTAG_VS, vdata_ref)) < 0 ) {
                fprintf (stderr,"Error: Problem with Vaddtagref().\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_shared_dataset", __FILE__, __LINE__);
                return numtagref;
            }
        }
        break;

    default:
        fprintf(stderr,"Error: class not found\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_dataset", __FILE__, __LINE__);
    status = FAIL;
    }

    if ((status = H5Tclose(type)) < 0 ) {
        fprintf(stderr,"Error: closing type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset", __FILE__, __LINE__);
        status = FAIL;
    }

    free(dataset_name);
    return status;
}


/*-------------------------------------------------------------------------
 * Function:    convert_shared_group
 *
 * Purpose:     Handle a shared group which has already been converted.
 *
 * Return:      status
 *
 * Programmer:  Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_shared_group (hid_t group, int idx, op_data_t *op_data)
{
    int32 hfile_id;
    int32 vgroup_id;
    int32 vgroup_ref;
    int32 numtagref;
    int32 status = SUCCEED;
    char *group_name=NULL;
    char *group_name2=NULL;
    char vgroup_name[VGNAMELENMAX];

    hfile_id = op_data->hfile_id;

    if ((group_name = get_objectname(group_table, idx)) == NULL ) {
        fprintf(stderr,"Error: get_objectname() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((group_name2 = strrchr(group_name,'/')) == NULL) { /* find last "/" in group_name */
        group_name2 = group_name;                          /* no "/"s were found */
    } else {
        group_name2 = group_name2 + sizeof(char);          /* 1 character past last "/" */
    }

    if ((status = Vgetname(op_data->vgroup_id,vgroup_name)) < 0 ) {
        fprintf (stderr,"Error: Problem with Vfind().\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        return (status);
    }

    if ((vgroup_ref = Vfind(hfile_id,vgroup_name)) <= 0 ) {
        fprintf (stderr,"Error: Problem with Vfind().\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        return (vgroup_ref);
    }

    if ((vgroup_id = Vattach(hfile_id, vgroup_ref, "w")) <= 0 ) {
        fprintf(stderr,"Error: Unable to create new vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        return(vgroup_id);
    }

    if ((vgroup_ref = Vfind(hfile_id,group_name2)) <= 0 ) {
        fprintf (stderr,"Error: Problem with Vfind().\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
  return (vgroup_ref);
    }

    if ((numtagref = Vaddtagref(vgroup_id, DFTAG_VG, vgroup_ref)) < 0 ) {
        fprintf (stderr,"Error: Problem with Vaddtagref().\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        return (numtagref);
    }

    if ((status = Vdetach(vgroup_id)) != SUCCEED ) {
        fprintf(stderr,"Error: Unable to detach the new Vgroup\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_shared_group", __FILE__, __LINE__);
        status = FAIL;
    }

    free(group_name);
    return status;
}


/*-------------------------------------------------------------------------
 * Function:    convert_dataset_string
 *
 * Purpose:     convert a dataset with string elements.
 *
 * Return:      status
 *
 * Programmer:  Paul Harten
 *
 * Modifications: 
 *
 *-----------------------------------------------------------------------*/
herr_t
convert_dataset_string (hid_t did, char *name, op_data_t *op_data)
{
    int32 hfile_id;
    int32 vdata_id;
    hid_t fxdlenstr;
    hid_t space;
    hid_t t_class;
    hid_t mem_type;
    const char* fieldname = {"string"};
    const char* fieldname_list = fieldname;
    char *buffer;
    int32 status;
    int32 h4_type;
    int32 recsize;
    int32 n_records;
    int32 n_values;
    int32 num_of_recs;
    int32  record_pos;
    size_t lenstr;
    H5T_cset_t cset;
    H5T_str_t strpad;
    hsize_t a_index = 0;
  
    if ((fxdlenstr = H5Dget_type(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((t_class = H5Tget_class(fxdlenstr)) != H5T_STRING ) {
        fprintf(stderr,"Error: problem with getting class\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert__dataset_string", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    h4_type = DFNT_CHAR;

    if ((mem_type = H5Tcopy(H5T_C_S1)) == FAIL ) {
        fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = mem_type;
        return status;
    }

    if ((lenstr = H5Tget_size(fxdlenstr)) <= 0 ) {
        fprintf(stderr, "Error: size of fixed length string type should not be %d\n",(int)lenstr);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return lenstr;
    }

    if ((status = H5Tset_size(mem_type,lenstr)) != SUCCEED ) {
        fprintf(stderr, "Error: Problem with H5Tset_size()\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    strpad = H5Tget_strpad(fxdlenstr);

    if ((strpad != H5T_STR_NULLTERM) && (strpad != H5T_STR_NULLPAD) && (strpad != H5T_STR_SPACEPAD)) {
        fprintf(stderr, "Error: Invalid string padding value, %d\n",(int)strpad);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return strpad;
    }

    if ((status = H5Tset_strpad(mem_type, strpad)) != SUCCEED ) {
        fprintf(stderr, "Error: Problem with H5Tset_strpad()\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((cset = H5Tget_cset(fxdlenstr)) != H5T_CSET_ASCII ) {
        fprintf(stderr, "Error: cset value != %d\n",(int)H5T_CSET_ASCII);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return cset;
    }

    if ((status = H5Tset_cset(mem_type,cset)) != SUCCEED ) {
        fprintf(stderr, "Error: Problem with H5Tset_cset()\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    hfile_id = op_data->hfile_id;

    if ((vdata_id = VSattach(hfile_id, -1, "w")) <= 0 ) {
        fprintf(stderr, "Error: Unable to create vdata %s.\n",name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    op_data->vdata_id = vdata_id;

    if ((status = VSsetname(vdata_id, name)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set vdata name %s.\n",name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((status = VSsetclass(vdata_id, "HDF5")) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set class on vdata %s\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((status = VSfdefine(vdata_id, fieldname, h4_type, lenstr)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to VSfdefine() field\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((status = VSsetfields(vdata_id, fieldname_list)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set fieldname list  %s\n", fieldname_list);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((status = VSsetinterlace(vdata_id, FULL_INTERLACE)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set FULL_INTERLACE mode, status %d\n", (int)status);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((recsize = H5Tget_size(mem_type)) <= 0 ) {
        fprintf(stderr, "Error: Unable to get record size %d\n", (int)recsize);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = recsize;
        return status;
    }

    /* Since the space is rank 1, n_records does not depend on maxdims. */
    n_records = n_values;

    if ((buffer = malloc((unsigned)(n_records*recsize))) == NULL) {
        fprintf(stderr, "Error: Problems with malloc of memory space\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((status = H5Dread(did, mem_type, space, space, H5P_DEFAULT, buffer)) != SUCCEED) {
        fprintf(stderr, "Error: Problems with H5Dread\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }

    if ((record_pos = VSseek(vdata_id, 0)) != 0 ) {
        fprintf(stderr, "Error: Could not seek the beginning of the Vdata, %d\n", (int)record_pos);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = record_pos;
        return status;
    }

    if ((num_of_recs = VSwrite(vdata_id, (void *)buffer,
                               n_records, FULL_INTERLACE)) != n_records ) {
        fprintf(stderr, "Error: Only able to write %d of %d records\n", (int)num_of_recs, (int)n_records);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        status = num_of_recs;
        return status;
    }

    /* there are only vdata attributes, no field attributes */
    if ((status = H5AITERATE(did, &a_index, (H5A_operator_t)convert_attr, op_data)) < 0 ) {
        fprintf(stderr,"Error: iterate over attributes\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
        return status;
    }
    if ((status = VSdetach(vdata_id)) != SUCCEED ) {
       fprintf(stderr, "Error: Unable to detach to vdata %s.\n",name);
       DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_dataset_string", __FILE__, __LINE__);
       return status;
    }

    free(buffer);
    return status;
}


/*-------------------------------------------------------------------------
 * Function:    h5atomic_type_to_h4type
 *
 * Purpose:     Match an H5 atomic type to an appropriate H4 type.
 *              Assign an appropirate H5 memory type that matches the H4 type.
 *              Return the H5 memory type, H4 type and sizeof H4 via pointers.
 *
 * Return:      SUCCEED on suceed, FAIL on failure.
 *              When fail, pointer values of h5memtype, h5memsize and h4_type
 *              may have changed and are undefined.
 *
 * Programmer:  Albert Cheng, March 2000
 *
 * Modifications: Add the support of converting HDF5 fixed-size string to HDF4 char.
 *                
 * Programmer:  Kent Yang, July 2012
 *
 *-----------------------------------------------------------------------*/
static herr_t h5atomic_type_to_h4type(const hid_t h5type, hid_t* h5memtype,
                                      size_t* h5memsize, int32* h4type)
{
    H5T_class_t t_class;
    size_t h5typesize;
    size_t h4typesize;
    H5T_sign_t sign;
    hid_t mem_datatype = FAIL;

    if ((t_class = H5Tget_class(h5type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting type class\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "h5atomic_type_to_h4type", __FILE__, __LINE__);
        return FAIL;
    }
    
    switch (t_class) {
    case H5T_INTEGER:
        if ((h5typesize = H5Tget_size(h5type)) == 0 ) {
            fprintf(stderr,"Error: problem with getting type size\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        if ((sign = H5Tget_sign(h5type)) == H5T_SGN_ERROR) {
            fprintf(stderr,"Error: problem with getting type sign\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        /* Deduce the proper HDF4 integer type to use according to the
         * size of the HDF5 type. Current HDF4 types can be 8, 16, 32 bits
         * (1, 2, 4 bytes). */
        switch (h5typesize) {
        case 1:
            *h4type = (sign == H5T_SGN_2 ? DFNT_INT8 : DFNT_UINT8);
            h4typesize = sizeof(int8);

            if (h4typesize == H5Tget_size(H5T_NATIVE_CHAR)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SCHAR : H5T_NATIVE_UCHAR);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_SHORT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SHORT : H5T_NATIVE_USHORT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_INT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_INT : H5T_NATIVE_UINT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_LONG)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_LONG : H5T_NATIVE_ULONG);
            } else {
                return FAIL;
            }

            break;

        case 2:
            *h4type = (sign == H5T_SGN_2 ? DFNT_INT16 : DFNT_UINT16);
            h4typesize = sizeof(int16);

            if (h4typesize == H5Tget_size(H5T_NATIVE_CHAR)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SCHAR : H5T_NATIVE_UCHAR);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_SHORT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SHORT : H5T_NATIVE_USHORT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_INT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_INT : H5T_NATIVE_UINT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_LONG)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_LONG : H5T_NATIVE_ULONG);
            } else {
                return FAIL;
            }

            break;
        case 4:
            *h4type = (sign == H5T_SGN_2 ? DFNT_INT32 : DFNT_UINT32);
            h4typesize = sizeof(int32);

            if (h4typesize == H5Tget_size(H5T_NATIVE_CHAR)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SCHAR : H5T_NATIVE_UCHAR);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_SHORT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_SHORT : H5T_NATIVE_USHORT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_INT)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_INT : H5T_NATIVE_UINT);
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_LONG)) {
                mem_datatype = (sign == H5T_SGN_2 ? H5T_NATIVE_LONG : H5T_NATIVE_ULONG);
            } else {
                return FAIL;
            }

            break;

        default:
            fprintf(stderr, "Error: unmatchable integer type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        break;
        /* end of case H5T_INTEGER */

    case H5T_FLOAT:
        if ((h5typesize = H5Tget_size(h5type)) == 0 ) {
            fprintf(stderr, "Error: problem with getting type size\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        /* Deduce the proper HDF4 floating point type to use according to
         * the size of the HDF5 type. Current HDF4 types can be 32 or 64
         * bits (4 or 8 bytes). */
        switch (h5typesize) {
        case 4:
            *h4type = DFNT_FLOAT32;
            h4typesize = sizeof(float32);

            if (h4typesize == H5Tget_size(H5T_NATIVE_FLOAT)) {
                mem_datatype = H5T_NATIVE_FLOAT;
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_DOUBLE)) {
                mem_datatype = H5T_NATIVE_DOUBLE;
            } else {
                return FAIL;
            }

            break;

        case 8:
            *h4type = DFNT_FLOAT64;
            h4typesize = sizeof(float64);

            if (h4typesize == H5Tget_size(H5T_NATIVE_FLOAT)) {
                mem_datatype = H5T_NATIVE_FLOAT;
            } else if (h4typesize == H5Tget_size(H5T_NATIVE_DOUBLE)) {
                mem_datatype = H5T_NATIVE_DOUBLE;
            } else {
                return FAIL;
            }

            break;

        default:
            fprintf(stderr,"Error: unmatchable H5 float type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        break;
        /* end of case H5T_FLOAT */

    case H5T_STRING:

        if (H5Tis_variable_str(h5type) != 0) {
            fprintf(stderr,"Error: HDF5 variable length datatype is not supported\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }

        if ((h5typesize = H5Tget_size(h5type)) == 0 ) {
            fprintf(stderr, "Error: problem with getting type size\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "h5atomic_type_to_h4type", __FILE__, __LINE__);
            return FAIL;
        }
    
        
        mem_datatype = H5Tget_native_type(h5type,H5T_DIR_ASCEND);

        /* Here the h4typesize is the HDF5 string size */
        h4typesize = h5typesize;
        *h4type    = DFNT_CHAR;

        break;

        /* end of case H5T_STRING */


    default:
        fprintf(stderr,"Error: unmatchable H5 type and class \n");
        return FAIL;
    }

    *h5memsize = h4typesize;
    *h5memtype = mem_datatype;
    return SUCCEED;
}

#ifndef NEWWAY
/*****************************************************************************

  Routine: h5type_to_h4type(h5type)
 
  Description: Translate h5 datatype into h4 datatype

  Input: h5 datatype
 
  Output: function return, h4 datatype

*****************************************************************************/

int32 h5type_to_h4type(hid_t h5_datatype)
{
    int32 h4_datatype;

    if (H5Tequal(h5_datatype,H5T_STD_I8BE)) {
        h4_datatype = DFNT_INT8;
    } else if (H5Tequal(h5_datatype,H5T_STD_I16BE)) {
        h4_datatype = DFNT_INT16;
    } else if (H5Tequal(h5_datatype,H5T_STD_I32BE)) {
        h4_datatype = DFNT_INT32;
#if 0
    /* This is not supported by HDF4 */
    } else if (H5Tequal(h5_datatype,H5T_STD_I64BE)) {
        h4_datatype = DFNT_INT64;
#endif  /* 0 */
    } else if (H5Tequal(h5_datatype,H5T_STD_U8BE)) {
        h4_datatype = DFNT_UINT8;
    } else if (H5Tequal(h5_datatype,H5T_STD_U16BE)) {
        h4_datatype = DFNT_UINT16;
    } else if (H5Tequal(h5_datatype,H5T_STD_U32BE)) {
        h4_datatype = DFNT_UINT32;
    } else if (H5Tequal(h5_datatype,H5T_STD_U64BE)) {
        h4_datatype = DFNT_UINT64;
    } else if (H5Tequal(h5_datatype,H5T_IEEE_F32BE)) {
        h4_datatype = DFNT_FLOAT32;
    } else if (H5Tequal(h5_datatype,H5T_IEEE_F64BE)) {
        h4_datatype = DFNT_FLOAT64;
    } else if (H5Tequal(h5_datatype,H5T_STD_I8LE)) {
        h4_datatype = DFNT_INT8;
    } else if (H5Tequal(h5_datatype,H5T_STD_I16LE)) {
        h4_datatype = DFNT_INT16;
    } else if (H5Tequal(h5_datatype,H5T_STD_I32LE)) {
        h4_datatype = DFNT_INT32;
#if 0
    /* This is not supported by HDF4 */
    } else if (H5Tequal(h5_datatype,H5T_STD_I64LE)) {
        h4_datatype = DFNT_INT64;
#endif  /* 0 */
    } else if (H5Tequal(h5_datatype,H5T_STD_U8LE)) {
        h4_datatype = DFNT_UINT8;
    } else if (H5Tequal(h5_datatype,H5T_STD_U16LE)) {
        h4_datatype = DFNT_UINT16;
    } else if (H5Tequal(h5_datatype,H5T_STD_U32LE)) {
        h4_datatype = DFNT_UINT32;
    } else if (H5Tequal(h5_datatype,H5T_STD_U64LE)) {
        h4_datatype = DFNT_UINT64;
    } else if (H5Tequal(h5_datatype,H5T_IEEE_F32LE)) {
        h4_datatype = DFNT_FLOAT32;
    } else if (H5Tequal(h5_datatype,H5T_IEEE_F64LE)) {
        h4_datatype = DFNT_FLOAT64;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_SCHAR)) {
        h4_datatype = DFNT_INT8;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_UCHAR)) {
        h4_datatype = DFNT_UINT8;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_SHORT)) {
        h4_datatype = DFNT_INT16;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_USHORT)) {
        h4_datatype = DFNT_UINT16;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_INT)) {
        h4_datatype = DFNT_INT32;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_UINT)) {
        h4_datatype = DFNT_UINT32;
#if 0
    /* This is not supported by HDF4 */
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_LONG)) {
        h4_datatype = DFNT_INT64;
#endif  /* 0 */
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_ULONG)) {
        h4_datatype = DFNT_UINT64;
#if 0
    /* This is not supported by HDF4 */
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_LLONG)) {
        h4_datatype = DFNT_INT128;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_ULLONG)) {
        h4_datatype = DFNT_UINT128;
#endif  /* 0 */
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_FLOAT)) {
        h4_datatype = DFNT_FLOAT32;
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_DOUBLE)) {
        h4_datatype = DFNT_FLOAT64;
#if 0
    /* This is not supported by HDF4 */
    } else if (H5Tequal(h5_datatype,H5T_NATIVE_LDOUBLE)) {
        h4_datatype = DFNT_FLOAT128;
#endif  /* 0 */
    } else {
        h4_datatype = FAIL;
    }

    return h4_datatype;
}


/*****************************************************************************

  Routine: h4type_to_memtype(h4type)
 
  Description: Translate h4 datatype into mem datatype

  Input: h4 datatype
 
  Output: function return, mem datatype

*****************************************************************************/

hid_t h4type_to_memtype(int32 h4_datatype)
{
    hid_t mem_datatype;

    switch (h4_datatype) {
    case DFNT_INT8:
    case DFNT_NINT8:
    case DFNT_LINT8:
        mem_datatype = H5T_NATIVE_SCHAR; break;
    case DFNT_UINT8:
    case DFNT_NUINT8:
    case DFNT_LUINT8:
        mem_datatype = H5T_NATIVE_UCHAR; break;
    case DFNT_INT16:
    case DFNT_NINT16:
    case DFNT_LINT16:
        mem_datatype = H5T_NATIVE_SHORT; break;
    case DFNT_UINT16:
    case DFNT_NUINT16:
    case DFNT_LUINT16:
        mem_datatype = H5T_NATIVE_USHORT; break;
    case DFNT_INT32:
    case DFNT_NINT32:
    case DFNT_LINT32:
        mem_datatype = H5T_NATIVE_INT; break;
    case DFNT_UINT32:
    case DFNT_NUINT32:
    case DFNT_LUINT32:
        mem_datatype = H5T_NATIVE_UINT; break;
    case DFNT_INT64:
    case DFNT_NINT64:
    case DFNT_LINT64:
        mem_datatype = H5T_NATIVE_LONG; break;
    case DFNT_UINT64:
    case DFNT_NUINT64:
    case DFNT_LUINT64:
        mem_datatype = H5T_NATIVE_ULONG; break;
    case DFNT_INT128:
    case DFNT_NINT128:
    case DFNT_LINT128:
        mem_datatype = H5T_NATIVE_LLONG; break;
    case DFNT_UINT128:
    case DFNT_NUINT128:
    case DFNT_LUINT128:
        mem_datatype = H5T_NATIVE_ULLONG; break;
    case DFNT_FLOAT32:
    case DFNT_NFLOAT32:
    case DFNT_LFLOAT32:
        mem_datatype = H5T_NATIVE_FLOAT; break;
    case DFNT_FLOAT64:
    case DFNT_NFLOAT64:
    case DFNT_LFLOAT64:
        mem_datatype = H5T_NATIVE_DOUBLE; break;
    case DFNT_FLOAT128:
    case DFNT_NFLOAT128:
    case DFNT_LFLOAT128:
        mem_datatype = H5T_NATIVE_LDOUBLE; break;
    default:
        mem_datatype = FAIL;
    }

    return mem_datatype;
}
#endif  /* NEWWAY */


/*****************************************************************************

  Routine: test_file
 
  Description: Test a file for read/write - ability.
 
  Input: filename  - Unix filename
 
  Output: function return,  global variable - errno

*****************************************************************************/

int test_file(char *filename,int oflag,mode_t mode)
{
    int  fid;

    errno = 0;
    fid = open(filename, oflag, mode);

    if (fid < 0)
        perror(filename);

    close(fid);
    return errno;
}


/*****************************************************************************

  Routine: test_dir
 
  Description: Test pathway to determine if it is a directory
 
  Input: path  - pathname given
 
  Output:  function return TRUE/FALSE

*****************************************************************************/

int test_dir(char *path)
{
    struct stat buf;
    struct stat *buf_ptr;
    int idir;

    buf_ptr = &buf;
    idir = stat(path, buf_ptr);

    if (idir < 0) {
        if (errno == 2) {
            return 0;
        } else {
            perror(path);
        }
   }

    return S_ISDIR(buf_ptr->st_mode);
}

/*****************************************************************************

  Routine: BuildFilename()
 
  Description: Build a filename with new extension
 
  Input: filename  - present filename
  ext- extension to root of filename
 
  Output: (filename:r).ext

*****************************************************************************/

char *BuildFilename(char *filename, char *ext)
{
    /* build outgoing filename */

    char *filename_out;
    char *lastper_ptr;
    char *lastdir_ptr;
    int root_len;

    lastper_ptr = strrchr(filename,'.');
    lastdir_ptr = strrchr(filename,'/');

    if ( lastper_ptr <= lastdir_ptr )
        /* no extension */
        root_len = strlen(filename);
    else
        /* existing extension */
        root_len = (int)(lastper_ptr - filename); 

    filename_out = (char *)malloc(root_len + strlen(ext) + 2);
    filename_out = strncpy(filename_out, filename, (size_t)root_len);
    filename_out[root_len] = '\0';
    filename_out = strcat(filename_out,".");
    filename_out = strcat(filename_out,ext);

    return filename_out;
}

/*-------------------------------------------------------------------------
 * Function:    init_table
 *
 * Purpose:     allocate and initialize tables for shared groups, datasets, 
 *              and committed types
 *
 * Return:      void
 *
 * Programmer:  Ruey-Hsia Li
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static 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;
        table->objs[i].objname = NULL;
    }

    *tbl = table;
}


/*-------------------------------------------------------------------------
 * Function:    init_prefix
 *
 * Purpose:     allocate and initialize prefix
 *
 * Return:      void
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static void
init_prefix(char **prefx, int prefx_len)
{
    if (prefx_len <= 0) {
        fprintf(stderr, "Prefix length not a positive integer.\n");
        exit(EXIT_FAILURE);
    }

    *prefx = 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:
 *
 *-------------------------------------------------------------------------
 */
static void
free_table(table_t **table)
{

    int i = 0;
    for(i =0;i<(*table)->size;i++)
        free((*table)->objs[i].objname);
       
    free((*table)->objs);

    free(*table);
}


/*-------------------------------------------------------------------------
 * 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:
 *
 *-------------------------------------------------------------------------
 */
static 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:
 *
 *-------------------------------------------------------------------------
 */
static 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 = 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 {
                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;
    }

    free(tmp);
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * 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
 *
 *-------------------------------------------------------------------------
 */
static 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
 *
 *-------------------------------------------------------------------------
 */
static 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
 *
 *-------------------------------------------------------------------------
 */
static 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:    HDstrdup() of object name character string
 *
 *              Failure:    NULL and sets errno to ENOMEM
 *
 * Programmer:  Paul Harten
 *
 *-------------------------------------------------------------------------
 */
static 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 = 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;
            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);
}

/* pkamat. Everything in this file below this point has been ADDED by pkamat. */

#define GLO_SDS     0
#define GLO_GR       1
#define FILE_LABEL    2
#define FILE_DESCRIPTION  3
#define H5_ATTR     4
#define ERR      5
/* pkamat [MOD5] Processes root group attributes. */

static herr_t
process_rootgroup_attr(int32 file_id, int32 sd_id, int32 gr_id, int32 an_id)
{
  intn num_attrs;
  intn i;
  char attr_name[256];
  int32 data_type;
  int32 count;
  int32 ncount;
  int32 size;
  int32 type;
  char  *attr_values=NULL;
  int32 status;
  int32 rootgroup_id;
  int32 ann_id;
  char *temp = NULL;
  char *atemp = NULL;
  int32 idx;

  if ((rootgroup_id = Vattach(file_id, rootgroup_ref, "r")) <= 0 ) {
    fprintf(stderr, "Error: Unable to access root group\n");
    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                   "process_rootgroup_attr", __FILE__, __LINE__);
    return FAIL;        
  }

  if ((num_attrs = Vnattrs(rootgroup_id)) == FAIL ) {
    fprintf(stderr, "Error: Vnattrs() did not work\n");
    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
    Vdetach(rootgroup_id);
    return FAIL;
  }

  for (i=0; i < num_attrs; i++)
  {
    if ((status = Vattrinfo(rootgroup_id, i, attr_name, &data_type, &count, &size)) == FAIL)
    {
      fprintf(stderr, "Error: Vattrinfo() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
      Vdetach(rootgroup_id);
      return status;
    }

    attr_values = NULL;
    if ((attr_values = HDmalloc(size)) == NULL) {
      fprintf(stderr, "Error: Problems with malloc of memory space\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
      Vdetach(rootgroup_id);
      return FAIL;
    }

    if ((status = Vgetattr(rootgroup_id, i, attr_values)) == FAIL)
    {
      fprintf(stderr, "Error: Vgetattr() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
      free (attr_values);
      Vdetach(rootgroup_id);
      return status;
    }
    type = getAttrType(attr_name);

    switch(type)
    {
    case GLO_SDS:
      idx = HDstrlen(attr_name) - HDstrlen("_GLO_SDS");
      attr_name[idx] = '\0'; 
      if ((status = SDsetattr(sd_id, attr_name, data_type, count, attr_values)) == FAIL)
      {
        fprintf(stderr, "Error: SDsetattr() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        Vdetach(rootgroup_id);
        return status;
      }
      break;

    case GLO_GR:
      idx = HDstrlen(attr_name) - HDstrlen("_GLO_GR");
      attr_name[idx] = '\0'; 
      if ((status = GRsetattr(gr_id, attr_name, data_type, count, attr_values)) == FAIL)
      {
        fprintf(stderr, "Error: GRsetattr() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        Vdetach(rootgroup_id);
        return status;
      }
      break;

    case FILE_LABEL:
    case FILE_DESCRIPTION:

      if ((ann_id = ANcreatef(an_id, type)) == FAIL)
      {
        fprintf(stderr, "Error: ANcreatef() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        Vdetach(rootgroup_id);
        return FAIL;
      }
      if ((status = ANwriteann(ann_id, attr_values, size)) == FAIL)
      {
        fprintf(stderr, "Error: ANwriteann() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        ANendaccess(ann_id);
        Vdetach(rootgroup_id);
        return status;
      }
      if ((status = ANendaccess(ann_id)) == FAIL)
      {
        fprintf(stderr, "Error: ANendaccess() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        Vdetach(rootgroup_id);
        return status;
      }
      break;
  
    case H5_ATTR:      
      if ((ann_id = ANcreatef(an_id, AN_FILE_DESC)) == FAIL)
      {
        fprintf(stderr, "Error: ANcreatef() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        Vdetach(rootgroup_id);
        return FAIL;
      }
      atemp = stringify((void *)attr_values,(int)count,data_type);
      ncount = HDstrlen(atemp) + HDstrlen("HDF5_") 
               + HDstrlen(attr_name) + HDstrlen(" = ")  +1 ;
      temp = HDmalloc (ncount);
      HDstrcpy(temp, "HDF5_");
      HDstrcat(temp, attr_name);
      HDstrcat(temp, " = ");
      HDstrcat(temp, (char *)atemp);
      temp[ncount-1] = 0;
      free(atemp);

      if ((status = ANwriteann(ann_id, temp, ncount)) == FAIL)
      {
        fprintf(stderr, "Error: ANwriteann() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        free (temp);
        Vdetach(rootgroup_id);
        return status;
      }

      if ((status = ANendaccess(ann_id)) == FAIL)
      {
        fprintf(stderr, "Error: ANendaccess() did not work\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
        free (attr_values);
        free (temp);
        Vdetach(rootgroup_id);
        return status;
      }
      free (temp);
      break;

    case ERR:
    default:
      fprintf(stderr, "Error: Invalid attribute\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "process_rootgroup_attr", __FILE__, __LINE__);
      free (attr_values);
      Vdetach(rootgroup_id);
      return FAIL;
    }
    free (attr_values);
  }

  if ((status = Vdetach(rootgroup_id)) == FAIL)
  {
     fprintf(stderr, "Error: Vdetach() did not work\n");
     DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                 "process_rootgroup_attr", __FILE__, __LINE__);
  }
  return status;  
}

static int 
getAttrType(char *attr_name)
{

 if (NULL == attr_name) 
   return ERR;
  
 if (isSuffix(attr_name, "_GLO_SDS") == SUCCEED)
   return GLO_SDS;
       /* the h4h5lib is wrong, but let's recognize this as V2 */
 if (isSuffix(attr_name, "_GLOSDS") == SUCCEED)
   return GLO_SDS;

 if (isSuffix(attr_name, "_GLO_GR") == SUCCEED)
   return GLO_GR;

       /* the h4h5lib is wrong, but let's recognize this as V2 */
 if (isSuffix(attr_name, "_GLOGR") == SUCCEED)
   return GLO_GR;

 if (isPrefix(attr_name, "HDF4_FILE_LABEL") == SUCCEED)
   return FILE_LABEL;

 if (isPrefix(attr_name, "HDF4_FILE_DESC") == SUCCEED)
   return FILE_DESCRIPTION;

 return H5_ATTR;
}

static herr_t
isSuffix(char *attrname, const char * suffix)
{
  char *temp1;
  int suff_len;
  int attr_len;
  int i;
  int count;

  if (NULL == attrname || NULL == suffix)
    return FAIL;

  temp1 = attrname;

  suff_len = HDstrlen(suffix);
  attr_len = HDstrlen(temp1);
  
  if (suff_len > attr_len)
    return FAIL;

  if (suff_len == 0 || attr_len == 0)
    return FAIL;

  count = attr_len - suff_len;
  for (i=0; i<count; i++)
  {
    temp1++;
  }
  
  while (1)
  {
    if (*temp1++ == *suffix++)
      suff_len--;
    else
      return FAIL;

    if (suff_len == 0) 
      return SUCCEED;
  }
}

static herr_t
isPrefix(char *attrname, const char *pref)
{
  char *temp1;
  int pref_len;
  int attr_len;

  if (NULL == attrname || NULL == pref)
    return FAIL;

  temp1 = attrname;

  pref_len = HDstrlen(pref);
  attr_len = HDstrlen(temp1);
  
  if (pref_len > attr_len)
    return FAIL;

  if (pref_len == 0 || attr_len == 0)
    return FAIL;

  while (1)
  {
    if (*temp1++ == *pref++)
      pref_len--;
    else
      return FAIL;

    if (pref_len == 0)
      { 
/*        if (HDstrcmp(pref, "HDF4_FILE_LABEL") == 0 || HDstrcmp(prefix, "HDF4_FILE_DESC") == 0 )
          *idx = HDstrtol(temp1, NULL, 10);
*/        return SUCCEED;
      }
  }
}

static int32
valueOfAttr(hid_t did, const char* attr_name, void* attr_value)
{
  hid_t attr_type;
  hid_t attr_id;
  int32 status;
  H5E_auto_t func;
  void *client_data;

  /* disable error reporting */
  H5EGET_AUTO(&func, &client_data);
  H5ESET_AUTO(NULL, NULL);

  if ((attr_id = H5Aopen_name (did, attr_name))>= 0) {
    if ((attr_type = H5Aget_type(attr_id)) <= 0) {
      fprintf(stderr, "Error: H5Aget_type() didn't return appropriate value.\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "valueOfAttr", __FILE__, __LINE__);
      return FAIL;
    }

    if ((status = H5Aread(attr_id, attr_type, attr_value)) != SUCCEED) {
      fprintf(stderr, "Error: Problems with H5Aread\n");
         DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "valueOfAttr", __FILE__, __LINE__);
      return status;
    }

    if ((status = H5Aclose(attr_id)) != SUCCEED) {
       fprintf(stderr, "Error: Problems with H5Aclose\n");
         DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "valueOfAttr", __FILE__, __LINE__);
      return status;
    }
    return SUCCEED;
  }
  /*enable error reporting */
  H5ESET_AUTO(func, client_data);
    
  return ATTR_ABSENT;
}
  
/*-------------------------------------------------------------------------
 * Function:    convert_image_attr
 *
 * Purpose:     dump the image attribute
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 *
 *-----------------------------------------------------------------------*/

static herr_t
convert_image_attr (hid_t attr, char *attr_name, op_data_t *op_data)
{
    hid_t  attr_id;
    hid_t type;
    hid_t space;
    hid_t mem_type;
    hid_t t_class;
    size_t typesize;
    char   *attr_values=NULL;
    int32  status;
    int32  h4_type;
    int32  vgroup_id;
    int32 grimage_id;
    int32  n_values;
    int32  order;
    hid_t fxdlenstr;
    size_t lenstr;
    H5T_cset_t cset;
    H5T_str_t strpad;
    char* attr_newname = NULL;
    int len;

    if (debug)
      printf("converting image attr\n");
    vgroup_id = op_data->vgroup_id;
    grimage_id = op_data->grimage_id;

    if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) {
        if (inImageAttrSkipList(attr_name) == SUCCEED) {
           if ((status = H5Aclose(attr_id)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Aclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image_attr", __FILE__, __LINE__);
          }
          return status;
        }

        len = HDstrlen(attr_name);
        if (inHDF5ImageSpecAttrList(attr_name) == SUCCEED) {
          len = len + HDstrlen ("HDF5_");
          attr_newname = (char *) malloc ((len + 1) * sizeof(char));                    
          HDstrcpy(attr_newname, "HDF5_");
          HDstrcat(attr_newname, attr_name);
          attr_newname[len] = '\0';
        }
        else {
          attr_newname = (char *) malloc ((len + 1) * sizeof(char));
          HDstrcpy(attr_newname, attr_name);
          attr_newname[len] = '\0';
        }

        if ((type = H5Aget_type(attr_id)) <= 0) {
            fprintf(stderr, "Error: H5Aget_type() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }

        if ((t_class = H5Tget_class(type)) < 0 ) {
            fprintf(stderr,"Error: problem with getting class\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }

        switch (t_class) {
        case H5T_INTEGER:
        case H5T_FLOAT:
            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

#ifdef NEWWAY
            if (FAIL==h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                //break;
                return status;
            }
#else
            if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((typesize = H5Tget_size(mem_type)) <= 0) {
                fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }
#endif  /* NEWWAY */

            if ((attr_values = malloc(n_values*typesize)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }
        
            if (grimage_id != 0) {
                if ((status = GRsetattr(grimage_id, attr_newname, h4_type,
                                        n_values, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_image_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free(attr_newname);
                    return status;
                }
            } else if ((status = Vsetattr(vgroup_id, attr_newname, h4_type,
                                          n_values, attr_values)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            status = SUCCEED;
            free(attr_values);
            break;

        case H5T_TIME:
            fprintf(stderr,"Warning: H5T_TIME attribute not yet implemented.\n");
            break;

        case H5T_STRING:
            fxdlenstr = type;
            h4_type = DFNT_CHAR;

            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((mem_type = H5Tcopy(H5T_C_S1)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                status = mem_type;
                free(attr_newname);
                return status;
            }

            if ((lenstr = H5Tget_size(fxdlenstr)) <= 0 ) {
                fprintf(stderr, "Error: size of fixed length string type should not be %d\n",(int)lenstr);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return FAIL;
            }

            if ((status = H5Tset_size(mem_type,lenstr)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_size()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            strpad = H5Tget_strpad(fxdlenstr);

            if ((strpad != H5T_STR_NULLTERM) && (strpad != H5T_STR_NULLPAD)
                        && (strpad != H5T_STR_SPACEPAD)) {
                fprintf(stderr, "Error: Invalid string padding value, %d\n",(int)strpad);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return FAIL;
            }

            if ((status = H5Tset_strpad(mem_type, H5T_STR_SPACEPAD)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_strpad()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            if ((cset = H5Tget_cset(fxdlenstr)) != H5T_CSET_ASCII ) {
                fprintf(stderr, "Error: cset value != %d\n",(int)H5T_CSET_ASCII);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return cset;
            }

            if ((status = H5Tset_cset(mem_type,cset)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_cset()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            order = n_values * lenstr;

            if ((attr_values = malloc((unsigned)order)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }
    
            if (grimage_id != 0) {
                if ((status = GRsetattr(grimage_id, attr_newname, h4_type,
                                        order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_image_attr", __FILE__, __LINE__);
                    free(attr_newname);
                    status = FAIL;
                    return status;
                }
            } else {
                if ((status = Vsetattr(vgroup_id, attr_newname, h4_type,
                                       order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_image_attr", __FILE__, __LINE__);
                    free(attr_newname);
                    status = FAIL;
                    return status;
                }
            }

            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            status = SUCCEED;
            free(attr_values);
            break;

        case H5T_BITFIELD:
            fprintf(stderr,"Warning: H5T_BITFIELD attribute not yet implemented.\n");
            break;

        case H5T_OPAQUE:
            fprintf(stderr,"Warning: H5T_OPAQUE attribute not yet implemented.\n");
            break;

        case H5T_COMPOUND:
            fprintf(stderr,"Warning: H5T_COMPOUND attribute not implemented.\n");
            break;

        default:
            fprintf(stderr,"Error: class not found for attribute %s\n",attr_newname);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image_attr", __FILE__, __LINE__);
            status = FAIL;
        }

        if ((status = H5Tclose(type)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Tclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }
    } else {
        status = FAIL;
    }

    if(attr_newname!=NULL)
        free(attr_newname);
    return status;
}

static herr_t
inImageAttrSkipList(char *name)
{
    int i;
#define ISKIP_COUNT 3
    char attr_name_list[ISKIP_COUNT][25] = {
      "CLASS",
      "INTERLACE_MODE", 
      "PALETTE"   
    };

    for (i=0; i<ISKIP_COUNT; i++) {
        if (HDstrcmp(name, attr_name_list[i]) == SUCCEED) {
            return SUCCEED;
        }
    }
    return FAIL;
}

static herr_t
inHDF5ImageSpecAttrList(char *name)
{
  int i;
#define ILIST_COUNT 10
  char attr_name_list[ILIST_COUNT][25] = {
    "IMAGE_SUBCLASS",
    "DISPLAY_ORIGIN", 
    "IMAGE_WHITE_IS_ZERO",
    "IMAGE_MINMAXRANGE",
    "IMAGE_BACKGROUNDINDEX",
    "IMAGE_TRANSPARENCY",
    "IMAGE_ASPECTRATIO",
    "IMAGE_COLORMODEL",
    "IMAGE_GAMMACORRECTION",
    "IMAGE_VERSION"       
    };

  for (i=0; i<ILIST_COUNT; i++) {
    if (HDstrcmp(name, attr_name_list[i]) == SUCCEED) {
      return SUCCEED;
    }
  }
  return FAIL;
}

static herr_t
inTableAttrSkipList(char *name)
{
  int i;
#define SKIP_COUNT 1
  char attr_name_list[SKIP_COUNT][25] = {
    "CLASS"
  };

  for (i=0; i<SKIP_COUNT; i++) {
    if (HDstrcmp(name, attr_name_list[i]) == SUCCEED) {
      return SUCCEED;
    }
  }
  return FAIL;
}

static herr_t
inHDF5TableSpecAttrList(char *name)
{
int i;
#define LIST_COUNT 2
char attr_name_list[LIST_COUNT][25] = {
    "VERSION",
    "TITLE"
 };

  for (i=0; i<LIST_COUNT; i++) {
    if (HDstrcmp(name, attr_name_list[i]) == SUCCEED) {
      return SUCCEED;
    }
    if (HDstrncmp(name, "FIELD", 5) == SUCCEED) {
      return SUCCEED;
    }
  }
  return FAIL;
}

/*-------------------------------------------------------------------------
 * Function:    convert_image
 *
 * Purpose:     Convert the specified image
 *
 * Return:      status
 *
 *-----------------------------------------------------------------------*/
static herr_t
convert_image (hid_t did, char *name, op_data_t *op_data)
{
    hid_t  type;
    hid_t space;
    hid_t t_class;
    hid_t mem_type;
    /* H5G_stat_t statbuf; */
    size_t typesize;
    int i;
    int32 dim_sizes[3];
    int ndims;
    hsize_t dims[32];
    hsize_t maxdims[32];
    int32 n_values;
    int32 status;
    int32 h4_type;

    hsize_t a_index = 0;
    char *buffer=NULL; /* read/write buffer*/
    char attr_value[256];
    int32 imdim_sizes[2];
    int32  imstart[2];
    int32 interlace_mode;
    int32 ncomp;
    int32 gr_id;
    int32 grimage_id;
    hobj_ref_t pal_ref;
    hid_t pal_dsetid;
    
    if (debug)
       printf("converting image\n");

    if ((type = H5Dget_type(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((ndims = H5Sget_simple_extent_dims(space,dims,maxdims)) < 0 ) {
        fprintf(stderr, "Error: Problems getting ndims, dims, and maxdims of dataset\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        status = ndims;
        return status;
    }

    if (ndims != 2 && ndims != 3) {
       fprintf(stderr,"Error: Invalid H5 Image. Number of dimensions can only be 2 or 3.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        return FAIL;      
    }
    
    if ((t_class = H5Tget_class(type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting class\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    switch (t_class) {
    case H5T_INTEGER:
    case H5T_FLOAT:
        gr_id = op_data->gr_id;

#define NEWWAY
#ifdef NEWWAY
        if (FAIL == h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
#else
        if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }  

        if ((typesize = H5Tget_size(mem_type)) <= 0) {
            fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
#endif  /* NEWWAY */

        if ((buffer = malloc(n_values*typesize)) == NULL) {
            fprintf(stderr, "Error: Problems with malloc of memory space\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        if ((status = H5Dread(did, mem_type, space, space, H5P_DEFAULT, buffer)) != SUCCEED) {
            fprintf(stderr, "Error: Problems with H5Dread\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        for (i = 0; i < ndims; ++i) {
            if (maxdims[i] == H5S_UNLIMITED) {
                if ( i == 0 ) {
                    /* this is how HDF4 communicates unlimited dimension */
                    dim_sizes[0] = 0;
                } else {
                    dim_sizes[i] = (int32)dims[i];
                }
            } else {
                dim_sizes[i] = (int32)maxdims[i];
            }
        }

        HDstrcpy(attr_value, " ");
        if ((status = valueOfAttr(did, "INTERLACE_MODE", attr_value)) == FAIL ) {
          fprintf(stderr,"Error: problem with getting value of attribute\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
          status =  FAIL;
          break;
        }

        if ((status == ATTR_ABSENT) || (HDstrncmp(attr_value, "INTERLACE_PIXEL", 15) == SUCCEED)) {
          interlace_mode = MFGR_INTERLACE_PIXEL;
          imdim_sizes[0] = dim_sizes[1];
          imdim_sizes[1] = dim_sizes[0];
          if (ndims == 2) 
            ncomp = 1;
          else
            ncomp = dim_sizes[2];
        }
        else {
          if (HDstrncmp(attr_value, "INTERLACE_PLANE", 15) == SUCCEED) {
            interlace_mode = MFGR_INTERLACE_COMPONENT; /* MFGR_INTERLACE_LINE ?? */
            if (ndims == 2) {
              ncomp = 1;
              imdim_sizes[0] = dim_sizes[1];
              imdim_sizes[1] = dim_sizes[0];
            }
            else {
              ncomp = dim_sizes[0];
              imdim_sizes[0] = dim_sizes[2];
              imdim_sizes[1] = dim_sizes[1];
            }
          }  
          else {
            fprintf(stderr,"Error: Invalid value for interlace mode\n");
              DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
          }
        }

        if ((grimage_id = GRcreate(gr_id, name, ncomp, h4_type, interlace_mode, imdim_sizes)) <= 0 ) {
            fprintf(stderr, "Error: Unable to create SDS %s.\n", name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
        op_data->grimage_id = grimage_id;

        /* PHERE */

        if ((status = valueOfAttr(did, "PALETTE", &pal_ref)) == FAIL ) {
          fprintf(stderr,"Error: problem with getting value of attribute\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
          status =  FAIL;
          break;
        }
        
        if (status != ATTR_ABSENT)
        {
          if ((pal_dsetid = H5RDEREFERENCE(did, H5R_OBJECT, &pal_ref)) <= 0) {
           fprintf(stderr, "Error: Problems with H5Rdereference\n");
           DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
           status =  FAIL;
           break;
          }
          
          if ((status = valueOfAttr(pal_dsetid, "CLASS", attr_value)) == FAIL ) {
            fprintf(stderr,"Error: problem with getting value of attribute\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
            status =  FAIL;
            break;
          }
          
          if (HDstrncmp(attr_value, "PALETTE", 7) != 0) {
            fprintf(stderr,"Palette reference points to a dataset not containing an attribute CLASS=PALETTE\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
            status =  FAIL;
            break;
          }

          if ((status = convert_palette(pal_dsetid, grimage_id, op_data))  == FAIL ) {
            fprintf(stderr,"Error: problem with converting palette\n");
              DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
            status =  FAIL;
            break;
          }
        }

/*        if ((status = valueOfAttr(pal_dsetid, "CLASS", attr_value)) == FAIL ) {
          fprintf(stderr,"Error: problem with getting value of attribute\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_image", __FILE__, __LINE__);
          status =  FAIL;
          break;
        }
      if (debug) {
        if (HDstrcmp(attr_value, "PALETTE") == 0)
          printf("correct dataset\n");
        else
          printf("incorrect dataset\n");
      }
*/

        imstart[0] = 0;
        imstart[1] = 0;
        if (debug) printf("writing image\n");
        if ((status = GRwriteimage(grimage_id, imstart, NULL, imdim_sizes, buffer)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to write SDS %s.\n", name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
        }
        
        if (debug) printf("calling convert_image_attr\n");
        if ((status = H5AITERATE(did, &a_index, (H5A_operator_t)convert_image_attr, op_data)) < 0 ) {
            fprintf(stderr,"Error: iterate over attributes\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
        }
        if ((status = GRendaccess(grimage_id)) != SUCCEED ) {
            fprintf(stderr, "Error: Unable to end access to GR image %s.\n",name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_image", __FILE__, __LINE__);
        }    
       break;

       default:
         fprintf(stderr, "Error: Invalid data type for an Image. The values should be INT or FLOAT\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_image", __FILE__, __LINE__);
         status = FAIL;
         return status;
    }

    if ((status = H5Tclose(type)) < 0 ) {
        fprintf(stderr, "Error: closing type\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_image", __FILE__, __LINE__);
    }

    if ((status = H5Sclose(space)) < 0 ) {
        fprintf(stderr, "Error: closing space\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_image", __FILE__, __LINE__);
    }

    free(buffer);
    return DSET_IMAGE;
}

/*-------------------------------------------------------------------------
 * Function:    convert_palette
 *
 * Purpose:     Convert the specified palette
 *
 * Return:      status
 *
 *-----------------------------------------------------------------------*/
static herr_t
convert_palette (hid_t did, int32 grimage_id, op_data_t* op_data)
{
    hid_t  type;
    hid_t  space;
    hid_t t_class;
    hid_t mem_type;
    /* H5G_stat_t statbuf; */
    size_t typesize;
    int i;
    int32 dim_sizes[2];
    int ndims;
    hsize_t dims[32];
    hsize_t maxdims[32];
    int32 n_values;
    int32 status;
    int32 h4_type;
    char *buffer=NULL; /* read/write buffer*/
    int32 pal_id;
    int32 ncomps;
    int32 nentries;

    if (debug)
      printf("converting palette\n");
    if ((type = H5Dget_type(did)) <= 0) {
      fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((ndims = H5Sget_simple_extent_dims(space,dims,maxdims)) < 0 ) {
        fprintf(stderr, "Error: Problems getting ndims, dims, and maxdims of dataset\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        status = ndims;
        return status;
    }

    if (ndims != 2) {
       fprintf(stderr,"Error: Invalid Palette. Number of dimensions can only be 2.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        return FAIL;      
    }
    
    if ((t_class = H5Tget_class(type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting class\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_palette", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    if (debug) printf("valid palette\n");

    switch (t_class) {
    case H5T_INTEGER:
    case H5T_FLOAT:

#define NEWWAY
#ifdef NEWWAY
        if (FAIL == h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
#else
        if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
            fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }  

        if ((typesize = H5Tget_size(mem_type)) <= 0) {
            fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
#endif  /* NEWWAY */

        if ((buffer = malloc(n_values*typesize)) == NULL) {
            fprintf(stderr, "Error: Problems with malloc of memory space\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        if ((status = H5Dread(did, mem_type, space, space, H5P_DEFAULT, buffer)) != SUCCEED) {
            fprintf(stderr, "Error: Problems with H5Dread\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }

        for (i = 0; i < ndims; ++i) {
            if (maxdims[i] == H5S_UNLIMITED) {
                if ( i == 0 ) {
                    /* this is how HDF4 communicates unlimited dimension */
                    dim_sizes[0] = 0;
                } else {
                    dim_sizes[i] = (int32)dims[i];
                }
            } else {
                dim_sizes[i] = (int32)maxdims[i];
            }
        }
        if ((pal_id = GRgetlutid(grimage_id, 0)) < 0) {
            fprintf(stderr, "Error: Problems with GRgetlutid\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break; 
        }
      
        /* pkamat. [FIX2] According to HDF5 Palette Spec dataset should be nentries x ncomps. Found not to be true for some images.
           The HDFViewer still displays them correctly.
           Hence this section does not flag an error even if its the other way around Needs to be fixed.*/

        /* according to specification. Found to be not true for some sample images */
        ncomps = dim_sizes[1];
        nentries = dim_sizes[0];

        /* sanity check */
        if (dim_sizes[1] != 3 && dim_sizes[1] != 4) {
          if (dim_sizes[0] == 3 || dim_sizes[0] == 4) {  
            ncomps = dim_sizes[0];
            nentries = dim_sizes[1];
          }
        }

        if (debug) printf("Writing palette\n");
        if ((status = GRwritelut(pal_id, ncomps, h4_type, 0, nentries, buffer)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems with GRwritelutid\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
            status = FAIL;
            break;
        }
/* pkamat [FIX1] Memory leak in the function convert_palette_attr() Commented out for now*/
/*        if (debug) printf("writing palette attr\n");

        if ((status = H5Aiterate(did, NULL, (H5A_operator_t)convert_palette_attr, op_data)) < 0 ) {
            fprintf(stderr,"Error: iterate over attributes\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette", __FILE__, __LINE__);
        }
*/
       break;

       default:
         fprintf(stderr, "Error: Invalid data type for a palette. The datatype has to be an H5 atomic numeric type.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette", __FILE__, __LINE__);
         status = FAIL;
    }

    if (H5Tclose(type) < 0 ) {
        fprintf(stderr, "Error: closing type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette", __FILE__, __LINE__);
    }

    if (H5Sclose(space) < 0 ) {
        fprintf(stderr, "Error: closing space\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette", __FILE__, __LINE__);
    }
    if (debug)
       printf("returning from convert palette\n");
    free(buffer);
    return status;
}

/*-------------------------------------------------------------------------
 * Function:    convert_palette_attr
 *
 * Purpose:     dump the palette attribute
 *
 * Return:      Success:        SUCCEED
 *
 *              Failure:        FAIL
 *
 * Note: This function is not used. 2019-07-16
 *-----------------------------------------------------------------------*/

static herr_t
convert_palette_attr (hid_t attr, char *attr_name, op_data_t *op_data)
{
    hid_t  attr_id;
    hid_t type;
    hid_t  space;
    hid_t mem_type;
    hid_t t_class;
    size_t typesize;
    char   *attr_values=NULL;
    int32  status=SUCCEED;
    int32  h4_type;
    int32 grimage_id;
    int32  n_values;
    int32  order;
    hid_t fxdlenstr;
    size_t lenstr;
    H5T_cset_t cset;
    H5T_str_t strpad;
    char *temp = NULL;
    uint16 tag;
    uint16 ref;
    int count;    
    int32 an_id;
    int32 ann_id;

    if (debug1) printf("converting palette attr %s\n", attr_name);
    grimage_id = op_data->grimage_id;
    an_id = op_data->an_id;
    tag = DFTAG_LUT;
    ref = GRidtoref(grimage_id);
    if (debug)  printf("accessing attr\n");

    if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) {
        if (debug) printf("opened attr\n");
        if ((type = H5Aget_type(attr_id)) <= 0) {
            fprintf(stderr, "Error: H5Aget_type() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
        }
        if (debug) printf("type obtained\n");
        if ((t_class = H5Tget_class(type)) < 0 ) {
            fprintf(stderr,"Error: problem with getting class\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
        }
        if (debug) printf("class obtained\n");
        if (debug) printf("taking action according to class\n");        
        switch (t_class) {
        case H5T_INTEGER:
        case H5T_FLOAT:
            if (debug)
              printf("class = int or float\n");
            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;              
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

#ifdef NEWWAY
            if (FAIL==h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
#else
            if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((typesize = H5Tget_size(mem_type)) <= 0) {
                fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
#endif  /* NEWWAY */

            if ((attr_values = HDmalloc(n_values*typesize)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((ann_id = ANcreate(an_id, tag, ref, AN_FILE_DESC)) == FAIL)
            {
                fprintf(stderr, "Error: ANcreate() did not work\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                 "convert_palette_attr", __FILE__, __LINE__);
                free(attr_values);
                status = FAIL;
                return status;
            }
            if (debug) printf("size of attr = %d\n", (int)(n_values*typesize));
            if (debug) printf("attr_values = %s\n", attr_values);
            count = n_values * typesize + HDstrlen("HDF5_") + HDstrlen(attr_name) + HDstrlen(" = ") + 1;
            temp = HDmalloc (count);
            HDstrcpy(temp, "HDF5_");
            HDstrcat(temp, attr_name);
            HDstrcat(temp, " = ");
            HDstrcat(temp, (char *)attr_values);
            //temp[count] = '\0';
            temp[count-1] = '\0';

            if ((status = ANwriteann(ann_id, temp, count)) == FAIL)
            {
                fprintf(stderr, "Error: ANwriteann() did not work\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                free(temp);
                free(attr_values);
                return status;
            }

            free (temp);
            free (attr_values);
            if ((status = ANendaccess(ann_id)) == FAIL)
            {
                fprintf(stderr, "Error: ANendaccess() did not work\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
 
            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
             }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }
            status = SUCCEED;
            break;

        case H5T_TIME:
            fprintf(stderr,"Warning: H5T_TIME attribute not yet implemented.\n");
            break;

        case H5T_STRING:
            fxdlenstr = type;
            h4_type = DFNT_CHAR;

            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((mem_type = H5Tcopy(H5T_C_S1)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = mem_type;
                return status;
            }

            if ((lenstr = H5Tget_size(fxdlenstr)) <= 0 ) {
                fprintf(stderr, "Error: size of fixed length string type should not be %d\n",(int)lenstr);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Tset_size(mem_type,lenstr)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_size()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                return status;
            }

            strpad = H5Tget_strpad(fxdlenstr);

            if ((strpad != H5T_STR_NULLTERM) && (strpad != H5T_STR_NULLPAD)
                        && (strpad != H5T_STR_SPACEPAD)) {
                fprintf(stderr, "Error: Invalid string padding value, %d\n",(int)strpad);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Tset_strpad(mem_type, H5T_STR_SPACEPAD)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_strpad()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((cset = H5Tget_cset(fxdlenstr)) != H5T_CSET_ASCII ) {
                fprintf(stderr, "Error: cset value != %d\n",(int)H5T_CSET_ASCII);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                return cset;
            }

            if ((status = H5Tset_cset(mem_type,cset)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_cset()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            order = n_values * lenstr;

            if ((attr_values = malloc((unsigned)(order+1))) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                free(attr_values);
                return status;
            }
    
            if ((ann_id = ANcreate(an_id, tag, ref, AN_FILE_DESC)) == FAIL)
            {
                fprintf(stderr, "Error: ANcreate() did not work\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_values);
                return status;
            }
            
            count = order + HDstrlen("HDF5_") + HDstrlen(attr_name) + HDstrlen(" = ") + 1;
            temp = HDmalloc (count);
            HDstrcpy(temp, "HDF5_");
            HDstrcat(temp, attr_name);
            HDstrcat(temp, " = ");
            HDstrcat(temp, (char *)attr_values);
            temp[count] = '\0';

            if ((status = ANwriteann(ann_id, temp, count)) == FAIL)
            {
                fprintf(stderr, "Error: ANwriteann() did not work\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette_attr", __FILE__, __LINE__);
                free(attr_values);
                free(temp);
                return status;
            }

            free(attr_values);
            free(temp);

            if ((status = ANendaccess(ann_id)) == FAIL)
            {
              fprintf(stderr, "Error: ANendaccess() did not work\n");
              DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                  "convert_palette_attr", __FILE__, __LINE__);
                return status;
            }

            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                return status;
            }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_palette_attr", __FILE__, __LINE__);
                return status;
            }
            status = SUCCEED;
            if (debug1) printf("string attr written\n");
         break;

         case H5T_BITFIELD:
           fprintf(stderr,"Warning: H5T_BITFIELD attribute not yet implemented.\n");
         break;

         case H5T_OPAQUE:
           fprintf(stderr,"Warning: H5T_OPAQUE attribute not yet implemented.\n");
         break;

         case H5T_COMPOUND:
           fprintf(stderr,"Warning: H5T_COMPOUND attribute not implemented.\n");
         break;

         default:
            fprintf(stderr,"Error: class not found for attribute %s\n",attr_name);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                          "convert_palette_attr", __FILE__, __LINE__);
            status = FAIL;
            return status;
      }

      if (H5Tclose(type) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Tclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_palette_attr", __FILE__, __LINE__);
            return FAIL;
      }
   } else {
          status = FAIL;
   }
   if (debug1) 
        printf("returning from palette attr\n");
   return status;
}

herr_t
convert_table (hid_t did, char *name, op_data_t *op_data)
{
    hid_t  type;
    hid_t space;
    hid_t t_class;
    hid_t mem_type;
    hid_t type2;
    /* H5G_stat_t statbuf; */
    size_t typesize;
    int idx;
    int ndims;
    int ndimf;
    hsize_t dims[32];
    hsize_t maxdims[32];
    hsize_t dimf[4];
    int32 hfile_id;
    int32 vdata_id;
    int32 n_values;
    int32 status;
    int32 h4_type;
    int32 recsize;
    int32 n_records;
    int32 num_of_recs;
    int32 record_pos;
    int nmembers;
    char *buffer=NULL; /* read/write buffer*/
    char fieldname_list[4096] = "\0";
    char *fieldname=NULL;
    hid_t fieldtype;
    int32 order;
    size_t offset;
    size_t offset_array[512];
    hid_t h4type_array[512];
    hid_t memtype_array[512];
    int32 order_array[512];
    
    hsize_t a_index = 0;
    /* hard link */
#if 0
    /* COMMENTED OUT FOR NOW */
    if ((status = H5Gget_objinfo(did, ".", TRUE, &statbuf)) != SUCCEED ) {
      fprintf(stderr, "Error: H5Gget_objinfo() did not work\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
      return (status);
    }
#endif  /* 0 */

    if ((type = H5Dget_type(did)) <= 0) {
      fprintf(stderr, "Error: H5Dget_type() didn't return appropriate value.\n");
      DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
      status = FAIL;
       return status;
    }

    if ((space = H5Dget_space(did)) <= 0) {
        fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
        fprintf(stderr, "Error: H5Sget_simple_extent_npoints() returned inappropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
        status = FAIL;
        return status;
    }

    if ((ndims = H5Sget_simple_extent_dims(space,dims,maxdims)) < 0 ) {
        fprintf(stderr, "Error: Problems getting ndims, dims, and maxdims of dataset\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
        status = ndims;
        return status;
    }

    if ((t_class = H5Tget_class(type)) < 0 ) {
        fprintf(stderr,"Error: problem with getting class\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    if (t_class != H5T_COMPOUND || ndims != 1 ) {
        fprintf(stderr,"Error: Invalid type for a table. It can only be 1-D array of compound data type\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
        status = t_class;
        return status;
    }

    if ((nmembers = H5Tget_nmembers(type)) <= 0 ) {
        fprintf(stderr, "Error: Unable to get the number of base types of this compound datatype \n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
    }

    offset = 0;

    for (idx = 0; idx < nmembers; ++idx) {
        if ((fieldtype = H5Tget_member_type(type, idx)) < 0 ) {
          fprintf(stderr,
                      "Error: H5 datasets of H5T_COMPOUND type with fieldtype, idx %d.\n",
                            idx);
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        /* Special case for array fields */
        if (H5Tget_class(fieldtype) == H5T_ARRAY) {
          hid_t   arr_base_type;

          /* Get the number of dimensions */
          if ((ndimf = H5Tget_array_ndims(fieldtype)) < 0 || ndimf > H5S_MAX_RANK ) {
            fprintf(stderr, "Error: rank of members of compound type should not be %d\n",
                               ndimf);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }

          /* Get the dimensions and dimension permutations */
          /* The permutation parameter is obsolete; it should always be set to NULL;
             this caused a bug when converting array type to vdata. KY 2007-3-7 */
          if (H5TGET_ARRAY_DIMS(fieldtype,dimf,NULL) < 0) {
            fprintf(stderr, "Error: cannot retrieve dimensions for array\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
           }

          /* Get the 'real' field type */
          if ((arr_base_type=H5Tget_super(fieldtype)) < 0) {
            fprintf(stderr, "Error: cannot retrieve base type for array\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }  

          if (H5Tclose(fieldtype) < 0 ) {
            fprintf(stderr,"Error: closing type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
           }

          /* Assign the array's base type as the field type for future use */
          fieldtype = arr_base_type;
        } 
        else {
                    ndimf = 0;
        }

#ifdef NEWWAY
        if (FAIL==h5atomic_type_to_h4type(fieldtype, &mem_type, &typesize, &h4_type)){
          fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
              "convert_table", __FILE__, __LINE__);
          return FAIL;
        }
#else
        if ((h4_type = h5type_to_h4type(fieldtype)) < 0 ) {
          fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
          fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                               "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        if ((typesize = H5Tget_size(mem_type)) <= 0) {
          fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }
#endif  /* NEWWAY */

        order = 1;
       {
        int temp_i;
        
        for (temp_i=0;temp_i <ndimf;temp_i++)
            order *=dimf[temp_i];
       }


        h4type_array[idx] = h4_type;  /* used for VSfdefine */
        memtype_array[idx] = mem_type;  /* used during the build of the memory compound type */
        offset_array[idx] = offset;  /* used during the build of the memory compound type */
        order_array[idx] = order;  /* used for VSfdefine */

        offset += order * typesize;  /* calculating packed size of memory compound type */
      } /* end of for */

      hfile_id = op_data->hfile_id;

      if ((vdata_id = VSattach(hfile_id, -1, "w")) <= 0 ) {
        fprintf(stderr, "Error: Unable to create vdata %s.\n",name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                           "convert_table", __FILE__, __LINE__);
        return FAIL;       
      }

#if 0
/*
 * This step is done during the convert_shared_dataset() call instead of here.
 */
      if (debug) printf("calling vinsert\n");
      if ((idx = Vinsert(vgroup_id, vdata_id)) < 0 ) {
        fprintf(stderr, "Error: Unable to insert vdata %s.\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL; 
      }
#endif  /* 0 */

      op_data->vdata_id = vdata_id;

      if ((status = VSsetname(vdata_id, name)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set vdata name %s.\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL; 
      }

      if ((status = VSsetclass(vdata_id, "HDF5")) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set class on vdata %s\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL; 
      }

      if ((type2 = H5Tcreate(H5T_COMPOUND, (size_t)offset)) <= 0 ) {
        fprintf(stderr, "Error: unable to execute H5Tcreate()\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL; 
      }

      for (idx = 0; idx < nmembers; ++idx) {
        /* Special case for array fields */
        if(H5Tget_member_class(type,idx)==H5T_ARRAY) {
          hid_t   arr_type;

          if ((arr_type = H5Tget_member_type(type, idx)) < 0 ) {
            fprintf(stderr,"Error: H5 datasets of H5T_COMPOUND type with the field type as  the array type at the index %d.\n",idx);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL; 
          }

          /* Get the number of dimensions */
          if ((ndimf = H5Tget_array_ndims(arr_type)) < 0 || ndimf > H5S_MAX_RANK ) {
            fprintf(stderr, "Error: rank of members of compound type should not be %d\n",ndimf);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }

          /* Get the dimensions and dimension permutations */
          if (H5TGET_ARRAY_DIMS(arr_type,dimf,NULL) < 0) {
            fprintf(stderr, "Error: cannot retrieve dimensions for array\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }

          if (H5Tclose(arr_type) < 0 ) {
            fprintf(stderr, "Error: closing type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }
        } 
        else {
          ndimf = 0;
        }

        if ((fieldname = H5Tget_member_name(type, idx)) == NULL ) {
          fprintf(stderr, "Error: Unable to get fieldname for compound type, idx %d\n", idx);
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        if ((int)(offset = H5Tget_offset(memtype_array[idx])) < 0 || offset >= 128 ) {
          fprintf(stderr, "Error: H5Tget_offset() is returning a bad value %d\n",(int)offset);
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        if (ndimf == 0 ) {
          if ((status = H5Tinsert(type2, fieldname,
                                  offset_array[idx] + offset,
                                  memtype_array[idx])) != SUCCEED ) {
            fprintf(stderr, "Error: Problems inserting field into compound datatype\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }
        } 
        else {
          hid_t   arr_type;

          /* Create the array datatype */
          if ((arr_type = H5TARRAY_CREATE(memtype_array[idx], ndimf, dimf, NULL)) < 0 ) {
            fprintf(stderr,"Error: cannot create array datatype\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }

          if ((status = H5Tinsert(type2,fieldname,offset_array[idx]+offset,arr_type)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems inserting field into compound datatype\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }

          if (H5Tclose(arr_type) < 0 ) {
            fprintf(stderr,"Error: closing type\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                    "convert_table", __FILE__, __LINE__);
            return FAIL;
          }
        }

        if ((status = VSfdefine(vdata_id, fieldname,
                                        h4type_array[idx],
                                        order_array[idx])) != SUCCEED ) {
          fprintf(stderr, "Error: Unable to set field %d\n", idx);
          DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table", __FILE__, __LINE__);
          return FAIL;
        }

        strcat(fieldname_list,fieldname);

        if (idx<nmembers-1)
                    strcat(fieldname_list,", ");

#if H5_VERSION_GE(1,8,13)
        /* use library free function for 1.8.13 and above */
            H5free_memory(fieldname);
#else
            free(fieldname);
#endif
      } /* end of for */

      if ((status = VSsetfields(vdata_id, fieldname_list)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to set fieldname list  %s\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      if ((status = VSsetinterlace(vdata_id, FULL_INTERLACE)) != SUCCEED ) {
        fprintf(stderr,
                        "Error: Unable to set FULL_INTERLACE mode, status %d\n",
                        (int)status);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      if ((recsize = H5Tget_size(type2)) <= 0 ) {
        fprintf(stderr, "Error: Unable to get record size %d\n", (int)recsize);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      /* Since the space is rank 1, n_records does not
       * depend on maxdims. */
      n_records = n_values;

      if ((buffer = malloc((unsigned)(n_records*recsize))) == NULL) {
        fprintf(stderr, "Error: Problems with malloc of memory space\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      if ((status = H5Dread(did, type2, space, space,
                                  H5P_DEFAULT, buffer)) != SUCCEED) {
        fprintf(stderr, "Error: Problems with H5Dread\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      if ((status = H5Tclose(type2)) < 0 ) {
        fprintf(stderr,"Error: closing type\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

      if ((record_pos = VSseek(vdata_id, 0)) != 0 ) {
        fprintf(stderr,
                   "Error: Could not seek the beginning of the Vdata, %d\n",
                        (int)record_pos);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        status = record_pos;
        return status;
      }

      if ((num_of_recs = VSwrite(vdata_id, (void *)buffer,
                                       n_records, FULL_INTERLACE)) != n_records ) {
        fprintf(stderr, "Error: Only able to write %d of %d records\n",
                        (int)num_of_recs, (int)n_records);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        status = num_of_recs;
        return status;
      }

      /* there are only vdata attributes, no field attributes */
      if ((status = H5AITERATE(did, &a_index, (H5A_operator_t)convert_table_attr,
                                     op_data)) < 0 ) {
        fprintf(stderr,"Error: iterate over attributes\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
                return FAIL;
      }
      if ((status = VSdetach(vdata_id)) != SUCCEED ) {
        fprintf(stderr, "Error: Unable to detach to vdata %s.\n", name);
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table", __FILE__, __LINE__);
        return FAIL;
      }

    if (H5Tclose(type) < 0 ) {
        fprintf(stderr, "Error: closing type\n");
  DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
    }

    if (H5Sclose(space) < 0 ) {
        fprintf(stderr, "Error: closing space\n");
        DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                    "convert_table", __FILE__, __LINE__);
    }
      
    free(buffer);
    status = DSET_TABLE;
    return status;
}

static herr_t
convert_table_attr (hid_t attr, char *attr_name, op_data_t *op_data)
{
    hid_t  attr_id;
    hid_t type;
    hid_t space;
    hid_t mem_type;
    hid_t t_class;
    size_t typesize;
    char   *attr_values=NULL;
    int32  status;
    int32  h4_type;
    int32  vgroup_id;
    int32 vdata_id;
    int32  n_values;
    int32  order;
    hid_t fxdlenstr;
    size_t lenstr;
    H5T_cset_t cset;
    H5T_str_t strpad;
    char* attr_newname=NULL;
    int len;

    if (debug1)
      printf("converting table attr\n");

    vgroup_id = op_data->vgroup_id;
    vdata_id = op_data->vdata_id;

    if ((attr_id = H5Aopen_name (attr, attr_name))>= 0) {
        if (inTableAttrSkipList(attr_name) == SUCCEED) {
           if ((status = H5Aclose(attr_id)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Aclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_table_attr", __FILE__, __LINE__);
          }
          return status;
        }

        len = HDstrlen(attr_name);
        if (inHDF5TableSpecAttrList(attr_name) == SUCCEED) {
          len = len + HDstrlen ("HDF5_");
          attr_newname = (char *) malloc ((len + 1) * sizeof(char));                    
          HDstrcpy(attr_newname, "HDF5_");
          HDstrcat(attr_newname, attr_name);
          attr_newname[len] = '\0';
        }
        else {
          attr_newname = (char *) malloc ((len + 1) * sizeof(char));
          HDstrcpy(attr_newname, attr_name);
          attr_newname[len] = '\0';
        }

        if ((type = H5Aget_type(attr_id)) <= 0) {
            fprintf(stderr, "Error: H5Aget_type() didn't return appropriate value.\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_table_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }

        if ((t_class = H5Tget_class(type)) < 0 ) {
            fprintf(stderr,"Error: problem with getting class\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_table_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }

        switch (t_class) {
        case H5T_INTEGER:
        case H5T_FLOAT:
            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

#ifdef NEWWAY
            if (FAIL==h5atomic_type_to_h4type(type, &mem_type, &typesize, &h4_type)){
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                break;
            }
#else
            if ((h4_type = h5type_to_h4type(type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h5 type to h4 type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((mem_type = h4type_to_memtype(h4_type)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((typesize = H5Tget_size(mem_type)) <= 0) {
                fprintf(stderr, "Error: H5Tget_size() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }
#endif  /* NEWWAY */

            if ((attr_values = malloc(n_values*typesize)) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                free(attr_values);
                return status;
            }
        
            if (vdata_id != 0) {
                if ((status = VSsetattr(vdata_id, -1, attr_newname, h4_type,
                                        n_values, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free(attr_newname);
                    free(attr_values);
                    return status;
                }
            } else if ((status = Vsetattr(vgroup_id, attr_newname, h4_type,
                                          n_values, attr_values)) != SUCCEED ) {
                fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                free(attr_values);
                return status;
            }

            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                free(attr_values);
                return status;
            }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                free(attr_values);
                return status;
            }

            status = SUCCEED;
            free(attr_values);
            break;

        case H5T_TIME:
            fprintf(stderr,"Warning: H5T_TIME attribute not yet implemented.\n");
            break;

        case H5T_STRING:
            fxdlenstr = type;
            h4_type = DFNT_CHAR;

            if ((space = H5Aget_space(attr_id)) <= 0) {
                fprintf(stderr, "Error: H5Dget_space() didn't return appropriate value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((n_values = H5Sget_simple_extent_npoints(space)) <= 0) {
                fprintf(stderr, "Error: H5sget_simple_extent_npoints() didn't return correct value.\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((mem_type = H5Tcopy(H5T_C_S1)) == FAIL ) {
                fprintf(stderr, "Error: Problems translating h4 type to mem type\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = mem_type;
                return status;
            }

            if ((lenstr = H5Tget_size(fxdlenstr)) <= 0 ) {
                fprintf(stderr, "Error: size of fixed length string type should not be %d\n",(int)lenstr);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return lenstr;
            }

            if ((status = H5Tset_size(mem_type,lenstr)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_size()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            strpad = H5Tget_strpad(fxdlenstr);

            if ((strpad != H5T_STR_NULLTERM) && (strpad != H5T_STR_NULLPAD)
                        && (strpad != H5T_STR_SPACEPAD)) {
                fprintf(stderr, "Error: Invalid string padding value, %d\n",(int)strpad);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return strpad;
            }

            if ((status = H5Tset_strpad(mem_type, H5T_STR_SPACEPAD)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_strpad()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            if ((cset = H5Tget_cset(fxdlenstr)) != H5T_CSET_ASCII ) {
                fprintf(stderr, "Error: cset value != %d\n",(int)H5T_CSET_ASCII);
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return cset;
            }

            if ((status = H5Tset_cset(mem_type,cset)) != SUCCEED ) {
                fprintf(stderr, "Error: Problem with H5Tset_cset()\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                return status;
            }

            order = n_values * lenstr;

            if ((attr_values = malloc((unsigned)(order))) == NULL) {
                fprintf(stderr, "Error: Problems with malloc of memory space\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((status = H5Aread(attr_id, mem_type, attr_values)) != SUCCEED) {
                fprintf(stderr, "Error: Problems with H5Aread\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                status = FAIL;
                free(attr_newname);
                free(attr_values);
                return status;
            }
    
            if (vdata_id != 0) {
                if ((status = VSsetattr(vdata_id, -1, attr_newname, h4_type,
                                        order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free(attr_newname);
                    free(attr_values);
                    return status;
                }
            } else {
                if ((status = Vsetattr(vgroup_id, attr_newname, h4_type,
                                       order, attr_values)) != SUCCEED ) {
                    fprintf(stderr, "Error: Unable to set %s attribute.\n",attr_newname);
                    DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                                "convert_table_attr", __FILE__, __LINE__);
                    status = FAIL;
                    free(attr_newname);
                    free(attr_values);
                    return status;
                }
            }

            free(attr_values);
            if ((status = H5Sclose(space)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Sclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            if ((status = H5Aclose(attr_id)) != SUCCEED ) {
                fprintf(stderr, "Error: Problems closing H5Aclose\n");
                DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                            "convert_table_attr", __FILE__, __LINE__);
                free(attr_newname);
                status = FAIL;
                return status;
            }

            status = SUCCEED;
            break;

        case H5T_BITFIELD:
            fprintf(stderr,"Warning: H5T_BITFIELD attribute not yet implemented.\n");
            break;

        case H5T_OPAQUE:
            fprintf(stderr,"Warning: H5T_OPAQUE attribute not yet implemented.\n");
            break;

        case H5T_COMPOUND:
            fprintf(stderr,"Warning: H5T_COMPOUND attribute not implemented.\n");
            break;

        default:
            fprintf(stderr,"Error: class not found for the attribute %s\n",attr_newname);
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_table_attr", __FILE__, __LINE__);
            status = FAIL;
        }

        if ((status = H5Tclose(type)) != SUCCEED ) {
            fprintf(stderr, "Error: Problems closing H5Tclose\n");
            DEBUG_PRINT("Error detected in %s() [%s line %d]\n",
                        "convert_table_attr", __FILE__, __LINE__);
            status = FAIL;
            free(attr_newname);
            return status;
        }
    } else {
        status = FAIL;
    }

    if(attr_newname != NULL)
        free(attr_newname);
    return status;
}

char * stringify( void * value, int count, int32 nt ) {
  char * thing;
  char * tmp;
/*
  char *cp;
*/
  int32 *ip;
  int16 *sp;
  int8 *i8p;
  uint32 *uip;
  uint16 *usp;
  uint8 *ui8p;
  float64 *dp;
  float32 *fp;
/*
  uint64 *ulp;
  int64 *lp;
*/
  int i;

  if (count < 1) return NULL;

  thing = malloc((unsigned)(count*20));
  thing[0] = '\0';
  tmp = malloc(100);
  switch(nt) {
    case DFNT_FLOAT:
      fp =  (float32 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%f,",fp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_DOUBLE:
      dp =  (float64 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%f,",dp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
/*
    case DFNT_INT64:
      lp =  (int64 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%ld,",lp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
      break;
*/
    case DFNT_INT32:
      ip =  (int32 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%d,",ip[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_INT16:
      sp =  (int16 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%d,",sp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_INT8:
      i8p =  (int8 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%d,",i8p[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
/*
    case DFNT_UINT64:
      ulp =  (uint64 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%ld,",ulp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
      break;
*/
    case DFNT_UINT32:
      uip =  (uint32 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%u,",uip[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_UINT16:
      usp =  (uint16 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%d,",usp[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_UINT8:
      ui8p =  (uint8 *)value;
      for (i = 0; i < count; i++) {
          sprintf(tmp,"%d,",ui8p[i]);
          thing = strcat(thing,tmp);
      }
      free(tmp);
      if (strlen(thing) > 1) {
        thing[strlen(thing)-1] = '\0';
      }
      return thing;
    case DFNT_CHAR:
    case DFNT_UCHAR:
    default:
            free(tmp);
      strncpy(thing,(char *)value,(unsigned)count);
                        thing[count] = 0;
      return (char *)thing;
  }
/* not reached
  return NULL;
*/
}
