/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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: 

1. converter library

See HDF4 to HDF5 mapping specification at
(https://support.hdfgroup.org/products/hdf5_tools/h4toh5/) for the default mapping 
from HDF4 object to HDF5 object.
 
The whole converter library includes 14 files, 

five header files:

     h4toh5.h 
     (all public h4toh5 APIs, needed for user who used h4toh5 library)

     h4toh5util.h(constants, utility and internal functions)

     h4toh5main.h(semi-public functions for all .c files)

     H4TOH5Ipublic.h(public header file copied and modified from HDF5 ID functions,users donot need to use this header file)

     H4TOH5Iprivate.h(private header file copied and modified from HDF5 ID functions,users should *NOT* use this header file)

nine C files:

     h4toh5util.c(utility and internal functions)
     h4toh5main.c(H4toH5open and H4toH5close functions)
     h4toh5sds.c(H4toH5sds,H4toH5all_dimscale and H4toH5one_dimscale functions)
     h4toh5image.c(H4toH5image function)
     H4toH5vdata.c(H4toH5vdata function)
     h4toh5vgroup.c(H4toH5bas_vgroup and H4toH5adv_group functions)
     h4toh5pal.c(H4toH5pal functions)
     h4toh5anno.c(H4toH5anno functions)
     H4TOH5I.c(ID handling fuction)

2. this file 

H4toH5vdata 
Converting an HDF4 independent vdata object into an HDF5 dataset of
compound dataset.

Author:  Kent Yang(myang6@hdfgroup.org)
 

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

#include "h4toh5main.h"

/*-------------------------------------------------------------------------
 * Function:        H4toH5vdata
 *
 * Purpose:         translate Vdata object into hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5_id: h4toh5 identifier
                vdata_id: RI identifier
                h5filename: hdf5 file name
                h5groupname: hdf5 group name
                h5dsetname: hdf5 dataset name
                group_id: hdf5 group id
                attr_flag: flag for attribute
                
     Out:

     Modification:
 *-------------------------------------------------------------------------
 */ 

int H4toH5vdata(hid_t h4toh5_id,
                int32 vdata_id, 
                char* h5groupname, 
                char* h5dsetname,
                int attr_flag)
{

    /* define variables for HDF4. */
    int32           istat; /* the temporary variable to check the return status of
                            HDF4 interfaces. */
    int32           n_records; /* number of records */
    int32           vdata_ref; /* Vdata reference number */
    int32           vdata_tag; /* Vdata tag */
    int32           interlace_mode; /* interlace mode of Vdata */
    int32           vdata_size; /* size of vdata "struct" in disk */
    int32           vdatamem_size; /* size of vdata "struct" in memory */
    int32           field_index; /* the index of the field */
    int32           fieldorder; /* the order of the field */
    int32           fieldtype; /* the data type of the field */
    int             i,temp; /* temporary variables */
    int32           nfields; /* number of field */
    int             num_vd_attrs; /* number of Vdata attributes */
    int             num_vd_field_attrs; /* number of Vdata field attributes */

    VOIDP           vd_data; /* data buffer to store Vdata */

    char            vdlabel[10]; /* the label of Vdata */
    char            vdata_name[H4H5_MAX_NC_NAME]; /* the name of Vdata */
    char            fieldname[H4H5_MAX_NC_NAME]; /* The name of Vdata field */
    char            vdata_class[VSNAMELENMAX]; /* The name of Vdata class */
    char            field_name_list[VSFIELDMAX*FIELDNAMELENMAX];
    /* the name list of field */

    /* define varibles for hdf5. */

    hid_t           h5d_sid; /* The data space id of HDF5 */
    hid_t           h5dset; /* The HDF5 dataset id */
    hid_t           h5_type_alias; /* this will be the compound datatype h5_ctype
                                      if this vdata is not one field and the -sv
                                      (simple vdata option) is not used. 
                                      Otherwise, it will be h5_sv_type*/
    hid_t           h5_memtype_alias; /* this will be the compound datatype h5_cmemtype
                                      if this vdata is not one field and the -sv
                                      (simple vdata option) is not used. 
                                      Otherwise, it will be h5_sv_memtype.*/
    hid_t           h5_ctype; /* The HDF5 file compound data type converted from
                         Vdata data type */
    hid_t           h5_cmemtype; /* The HDF5 memory compound data type converted from
                                Vdata data type */
    hid_t           h5_sv_type; /*HDF5 datatype for -sv option and 1 field vdata.*/
    hid_t           h5_sv_memtype; /*HDF5 datatype for -sv option and 1 field vdata.*/
    size_t          dummy_h4memsize;
    size_t          dummy_h4size;
    hid_t*       h5memtype = NULL; /* The atomic HDF5 memory data type */
    hid_t*       h5type = NULL; /* The atomic HDF5 file data type */
    size_t*      h4memsize = NULL; /* The memory size of HDF4 data type */
    size_t*      h4size = NULL; /* The file size of HDF4 data type */
    hsize_t     h5_vddims[1]; /* The size of the dimension of the HDF5 dataset
                                 converted from Vdata record */
    hsize_t     h5_maxvddims[1]; /* The maximum size of the dimension of the 
                                HDF5 dataset converted from Vdata record */
    hsize_t     h5_chunkdims[1]; /* The chunking size of the the dimension of the 
                                HDF5 dataset converted from Vdata record */
    hid_t           create_plist; /* the creation property list of HDF5 dataset */
    char*           h5cvdata_name; /* The absolute path of HDF5 dataset converted from
                                    Vdata */
    char*           ori_h5cvdata_name; /* The absolute path of the first touched HDF5 
                                    dataset converted from Vdata with this 
                                    reference number */
    int             check_vdata; /* a flag to check the status of the Vdata */
    int*            check_lookupptr; /* the pointer that passes the value of the status
                                of the Vdata */
    hid_t           h5_group; /* HDF5 group id */
    herr_t      ret; /* the flag to check the "return" status of HDF5 APIs. */

    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */
    int             empty_vdata;    /* whether or not vdata ie empty */
    short      conv_1fvd_h5atom = 0;

    char* h5tablefieldname;
    char* h5tablefield="FIELD_";
    char* h5tablename="_NAME";
    char    findex_str[MAXREF_LENGTH];

    temp = -1;
    check_lookupptr=&temp;

    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /* Zeroing out memory for vdlabel,vdata_class,vdata_name */
    h4toh5_ZeroMemory(vdata_name,H4H5_MAX_NC_NAME);
    h4toh5_ZeroMemory(fieldname,H4H5_MAX_NC_NAME);
    h4toh5_ZeroMemory(vdata_class,VSNAMELENMAX);
    h4toh5_ZeroMemory(field_name_list,VSFIELDMAX*FIELDNAMELENMAX);
    h4toh5_ZeroMemory(vdlabel,10);
    if (VSQueryvsize(vdata_id,&vdata_size)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to query vdata size",
                __FILE__,__LINE__);
        return FAIL;
    }

    if(vdata_size == 0) return SUCCEED;
    
    /* obtain number of records, field name list, vdata name. */
    if(VSinquire(vdata_id,&n_records,&interlace_mode,
                     field_name_list,&vdata_size,vdata_name) == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "unable to obtain Vdata imformation",
                     __FILE__,__LINE__);
        return FAIL;
    }

    empty_vdata = n_records == 0;

    /* get absolute path of hdf5 vdata name. */

    vdata_ref =  VSQueryref(vdata_id);
    if (vdata_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "unable to obtain Vdata reference number",
                     __FILE__,__LINE__);
        return FAIL;
    }

#ifdef HAVE_LIBHDFEOS
    if (H4toH5config_use_eos2_conversion())  {
        int handled = 0;
        /* HDF-EOS2 stores an attribute as an HDF4 vdata.
             If HDF-EOS2 handled this, do not fall through the general routine because it will
             create an HDF5 dataset, which is not correct for this special case.
         */
        if (H4toH5vdata_eos_attribute(h4toh5_id, h5groupname, vdata_name, vdata_id, &handled) == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                 "unable to detect whether or not this vdata is attribute",
                 __FILE__,__LINE__);
            return FAIL;
        }
        if (handled) {
            return SUCCEED;
        }

        /* HDF-EOS2 stores a field as an HDF4 vdata if the rank is 1.
             If HDF-EOS2 routine says this vdata was handled, do not fall through the general routine
             because values and attributes were already handled.
         */
        if (H4toH5vdata_eosgrid_dimscale(h4toh5_id, h5groupname, vdata_id, &handled) == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                 "unable to detect whether or not this vdata is an EOS field",
                 __FILE__,__LINE__);
            return FAIL;
        }
        if (handled) {
            return SUCCEED;
        }
        if (H4toH5vdata_eosswath_dimscale(h4toh5_id, h5groupname, vdata_id, &handled) == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                 "unable to detect whether or not this vdata is an EOS field",
                 __FILE__,__LINE__);
            return FAIL;
        }
        if (handled) {
            return SUCCEED;
        }

        if (H4toH5config_use_netcdf4_fakedim()) {
            /* This case may be handled by creating fake dimensions.
             * If it turns out that this can be handled, errors will be generated later. */
        }
        else if (H4toH5config_use_netcdf4_strict()) {
            /* If -nc4strict is given and vdata cannot be recognized as an HDF-EOS2 attribute or
         HDF-EOS2 data, this file should be rejected because general routine below this will
         create an HDF5 dataset that does not refer to any dimensional maps. NetCDF4 will not
         be able to read this HDF5 dataset.
             */
            char buff[100]; /* this is gonna be safe */
            sprintf(buff, "HDF4 vdata '%s' is neither an HDF-EOS2 attribute nor an HDF-EOS 1-d field.", vdata_name);
            H4toH5error_set(temph4toh5id,2,buff,__FILE__,__LINE__);
            return FAIL;
        }
    }
#endif

    /* obtain HDF5 group id */

    h5_group        =  get_h5groupid(h5groupname,h4toh5_id,attr_flag);
    if(h5_group < 0) {
        H4toH5error_set(temph4toh5id,5,
                     "unable to obtain HDF5 group id",
                     __FILE__,__LINE__);
        return FAIL;
    }

    /* check whether this vdata is converted. */

    check_vdata = lookup(h4toh5_id,vdata_ref,VD_HASHSIZE,
                             temph4toh5id->vd_hashtab,&temp);

    if(h5dsetname == NULL) {
        /* Here we have to be careful:
             1) We assume the user will not use the string
             "HDF4_VD_<ref>" where <ref> is the reference number
             of the Vdata as their own Vdata name. 
             2) We will check whether this Vdata has been visited
             or not. If this Vdata has been visited, it must be assigned a
             name "HDF4_VD_<ref>". We should check whether "HDF4_VD_<ref>"
             has been used. 
                3) So the procedure we are using is:
             i) obtain the Vdata name by using get_h5datasetname.
             ii) check whether this name has been visited,
                     due to the possible name clashing among Vdatas(two Vdatas may
             share the same name), we will use routine "lookup_name" to assure
             the non-confliction use of this Vdata name.
        */

        h5cvdata_name = get_h5datasetname(h4toh5_id,h5groupname,vdata_name,
                                            vdata_ref,HDF4_VDATA,OBJECT_HASHSIZE,check_lookupptr);
        
        if(lookup_name(h4toh5_id,h5cvdata_name,OBJECT_HASHSIZE,
                     temph4toh5id->name_hashtab)==1) {
            H4toH5error_set(temph4toh5id,4,
                 "this object name has been used",
                 __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            return FAIL;
        }
    }
    else {
        h5cvdata_name = get_h5datasetname(h4toh5_id,h5groupname,h5dsetname,
                                            vdata_ref,HDF4_VDATA,OBJECT_HASHSIZE,check_lookupptr);
        if(*check_lookupptr == 1) {/* the user-input vdata name is used.*/
            free(h5cvdata_name);
            H5Gclose(h5_group);
            H4toH5error_set(temph4toh5id,4,
                 "this dataset name is used by another object",
                 __FILE__,__LINE__);
            return FAIL;
        }
    }
    /*Update the HDF5 dataset table.*/
    if(lookup_updatename(h4toh5_id,h5cvdata_name,OBJECT_HASHSIZE,temph4toh5id->name_hashtab)==-1) {
        H5Gclose(h5_group);
        H4toH5error_set(temph4toh5id,4,
                     "this vdata name has been used",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        return FAIL;
    }
    /* check whether this vdata is touched, if not; put this vdata name into 
         the vdata table; this will be used to create hardlink when multiple 
         groups include one vdata object.*/
 
    if(check_vdata == 0) {
        /* put the absolute path of vdata into "hashing table".*/
        if(set_name(h4toh5_id,vdata_ref,VD_HASHSIZE,temph4toh5id->vd_hashtab,
                h5cvdata_name,-1)==FAIL) {
            H4toH5error_set(temph4toh5id,4,
                 "cannot set object name",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    else {/* create a hard link and return back.*/
        ori_h5cvdata_name = get_name(h4toh5_id,vdata_ref,VD_HASHSIZE,
                                 temph4toh5id->vd_hashtab,&temp);
        if(ori_h5cvdata_name == NULL) {
            H4toH5error_set(temph4toh5id,4,
                 "cannot obtain the name of HDF5 dataset converted from Vdata",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        if(H5Glink(h5_group,H5G_LINK_HARD,ori_h5cvdata_name,h5cvdata_name) <0) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot set up hard link to original dataset name ",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            free(ori_h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        free(ori_h5cvdata_name);
        free(h5cvdata_name);
        ret = H5Gclose(h5_group);
        if (ret < 0) {
         H4toH5error_set(temph4toh5id,3,"cannot set up hard link to original dataset name ",__FILE__,__LINE__);         
                 return FAIL;
        }
        return SUCCEED;
    }
    
    vdata_tag = VSQuerytag(vdata_id);
    if (vdata_tag == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "fail to obtain Vdata tag ",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* get the class name */

    if(VSgetclass(vdata_id,vdata_class) == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "cannot obtain Vdata class name",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* get number of record,field_name,Size of a record and
         Name of the vdata*/ 

    if(VSQueryvsize(vdata_id,&vdata_size)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "cannot query Vdata size ",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(vdata_size == 0) {/* empty vdata set. */
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return SUCCEED;
    }
    
    vdatamem_size = 0;
    vdata_size = 0;
    nfields = VFnfields(vdata_id);

    if (nfields == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "cannot obtain number of Vdata fields",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    h5memtype = calloc((size_t)nfields,sizeof(hid_t));
    h5type      = calloc((size_t)nfields,sizeof(hid_t));
    h4memsize = calloc((size_t)nfields,sizeof(size_t));
    h4size      = calloc((size_t)nfields,sizeof(size_t));


    if(h5type == NULL) {
        H4toH5error_set(temph4toh5id,1,
                     "cannot allocate HDF5  type",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        free(h5memtype);
        free(h4memsize);
        free(h4size);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(h5memtype == NULL) {
        H4toH5error_set(temph4toh5id,1,
                     "cannot allocate HDF5 memory type",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        free(h5type);
        free(h4memsize);
        free(h4size);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(h4memsize == NULL) {
        H4toH5error_set(temph4toh5id,1,
                     "cannot allocate HDF5 memory size",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        free(h5memtype);
        free(h5type);
        free(h4size);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(h4size == NULL) {
        H4toH5error_set(temph4toh5id,1,
                     "cannot allocate HDF5  size",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        H5Gclose(h5_group);
        return FAIL;
    }

    for (i=0;i<nfields;i++) {
         
        /* obtain field type. */
        fieldtype = VFfieldtype(vdata_id,i);
        if(fieldtype == FAIL){
            H4toH5error_set(temph4toh5id,2,
                 "cannot obtain Vdata field type",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        /* obtain field order.*/
        fieldorder = VFfieldorder(vdata_id,i);  

        if(fieldorder == FAIL){
            H4toH5error_set(temph4toh5id,1,
                 "cannot obtain Vdata field order",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        /* datatype conversion from hdf4 to hdf5.
             the corresponding memory data type is also converted.*/
        if(h4type_to_h5type(h4toh5_id,fieldtype,&h5memtype[i],&h4memsize[i],
                        &h4size[i],&h5type[i])== FAIL){
            H4toH5error_set(temph4toh5id,5,
                 "cannot convert HDF4 data type to HDF5 data type",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        vdatamem_size +=fieldorder*h4memsize[i];
        vdata_size +=fieldorder*h4size[i];
         
    }
 
    vd_data = malloc(vdatamem_size*n_records);   

    if(vd_data == NULL) {
        H4toH5error_set(temph4toh5id,1,
                     "cannot allocate memory for Vdata",
                     __FILE__,__LINE__);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        free(h4size);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }
        
    if (!empty_vdata) {
        /* The following function should not be called when the vdata is empty; otherwise, this function returns FAIL */
        istat       = VSsetfields(vdata_id,field_name_list); 
        
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot set Vdata fields",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        istat = VSread(vdata_id,(uint8*)vd_data,n_records,FULL_INTERLACE);

        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,3,"cannot read Vdata",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    for (i=0;i<nfields;i++) {

        /* obtain field order.*/
        fieldorder = VFfieldorder(vdata_id,i);  
        if(fieldorder == FAIL){
            H4toH5error_set(temph4toh5id,3,
                 "cannot obtain field order",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    if(nfields == 1 && attr_flag == H425_SV) 
        conv_1fvd_h5atom = 1;
    if(conv_1fvd_h5atom ==1) {
        fieldtype = VFfieldtype(vdata_id,0);
        if(h4type_to_h5type(h4toh5_id,fieldtype,&h5_sv_memtype,&dummy_h4memsize,
                                    &dummy_h4size,&h5_sv_type)== FAIL){
            H4toH5error_set(temph4toh5id,3,
                 "cannot obtain field order",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        h5_type_alias = h5_sv_type;
        h5_memtype_alias = h5_sv_memtype;
    }
    else {
        /*  create HDF5 compound datatype for both memory and file.*/
    
        h5_ctype             = H5Tcreate(H5T_COMPOUND,(size_t)vdata_size);
        h5_cmemtype      = H5Tcreate(H5T_COMPOUND,(size_t)vdatamem_size);
    
        if(gen_h5comptype(h4toh5_id,vdata_id,nfields,h4size,h4memsize,h5type,
                            h5memtype,h5_ctype,h5_cmemtype)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                         "cannot obtain hdf5 compound data type",
                         __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        
        h5_type_alias = h5_ctype;
        h5_memtype_alias = h5_cmemtype;
    }

    /* this block was added while implementing netCDF4 hack,
     * but it seems that it was actually an unintentional bug fix.
     */
    if (1) {
        char *h5cvdata_type_name = malloc(strlen(h5cvdata_name) + 2 + 1);
        if (h5cvdata_type_name == NULL) {
            H4toH5error_set(temph4toh5id,5,
                 "cannot allocate memory for type name",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        sprintf(h5cvdata_type_name, "%s_t", h5cvdata_name);
        if(conv_1fvd_h5atom !=1) {
            if (H5TCOMMIT(h5_group, h5cvdata_type_name, h5_ctype) < 0) {
                H4toH5error_set(temph4toh5id,5,
                     "cannot commit hdf5 named type",
                     __FILE__,__LINE__);
                free(h5cvdata_type_name);
                free(h5memtype);
                free(h5type);
                free(h4memsize);
                free(h4size);
                free(vd_data);
                free(h5cvdata_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        free(h5cvdata_type_name);

        char *h5cvdata_memtype_name = malloc(strlen(h5cvdata_name) + 3 + 1);
        if (h5cvdata_type_name == NULL) {
            H4toH5error_set(temph4toh5id,5,
                 "cannot allocate memory for type name",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        sprintf(h5cvdata_memtype_name, "%s_mt", h5cvdata_name);
#if 0
        if (H5TCOMMIT(h5_group, h5cvdata_memtype_name, h5_cmemtype) < 0) {
            H4toH5error_set(temph4toh5id,5,
                 "cannot commit hdf5 named type",
                 __FILE__,__LINE__);
            free(h5cvdata_type_name);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Gclose(h5_group);
            return FAIL;
        }
#endif
        free(h5cvdata_memtype_name);

    }

    h5_vddims[0] = n_records;
    h5_maxvddims[0] = H5S_UNLIMITED;
    if(conv_1fvd_h5atom == 1)
        h5d_sid = H5Screate_simple(1,h5_vddims,NULL);
    else 
        h5d_sid = H5Screate_simple(1,h5_vddims,h5_maxvddims);
    if(h5d_sid <0){
        H4toH5error_set(temph4toh5id,3,
                     "cannot create hdf5 data space",
                     __FILE__,__LINE__);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        free(h4size);
        free(vd_data);
        free(h5cvdata_name);
        H5Gclose(h5_group);
        return FAIL;
    }
    
    h5_chunkdims[0] = h5_vddims[0];
    if (h5_chunkdims[0] == 0)
        h5_chunkdims[0] = H4H5_DEFAULT_NUMELEM_IN_CHUNK;
    create_plist = H5Pcreate(H5P_DATASET_CREATE);
    if(create_plist < 0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create property list",
                __FILE__,__LINE__);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        free(h4size);
        free(vd_data);           
        free(h5cvdata_name);
        H5Gclose(h5_group);
        H5Sclose(h5d_sid);
        return FAIL;        
    }
    if (H5Pset_chunk(create_plist,1,h5_chunkdims)<0){
        H4toH5error_set(temph4toh5id,3,
                "failed to set up chunking property list",
                __FILE__,__LINE__);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        free(h4size);
        free(vd_data);           
        free(h5cvdata_name);
        H5Gclose(h5_group);
        H5Pclose(create_plist);
        H5Sclose(h5d_sid);
        return FAIL;        
    }
    if(conv_1fvd_h5atom == 1) 
        h5dset = H5DCREATE(h5_group,h5cvdata_name,h5_type_alias,h5d_sid,H5P_DEFAULT);
    else
        h5dset = H5DCREATE(h5_group,h5cvdata_name,h5_type_alias,h5d_sid,create_plist);

    if(h5dset <0) {
        H4toH5error_set(temph4toh5id,3,
                     "cannot create HDF5 dataset",
                     __FILE__,__LINE__);
        free(h5memtype);
        free(h5type);
        free(h4memsize);
        free(h4size);
        free(vd_data);           
        free(h5cvdata_name);
        H5Sclose(h5d_sid);
        H5Gclose(h5_group);
        H5Pclose(create_plist);
        return FAIL;
    }

    if (!empty_vdata) {
        if(H5Dwrite(h5dset,h5_memtype_alias,H5S_ALL,H5S_ALL,H5P_DEFAULT,vd_data)<0){
            H4toH5error_set(temph4toh5id,3,
                 "cannot write HDF5 dataset converted from Vdata",
                 __FILE__,__LINE__);
            free(h5memtype);
            free(h5type);
            free(h4memsize);
            free(h4size);
            free(vd_data);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            H5Pclose(create_plist);
            return FAIL;
        }
    }

    free(h5memtype);
    free(h5type);
    free(h4memsize);
    free(h4size);
    free(vd_data);

    /* handle vdata attributes and vdata field attributes. */

    num_vd_attrs = VSfnattrs(vdata_id,_HDF_VDATA);

    if (num_vd_attrs == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "cannot obtain number of attributes of Vdata",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
        
    /* when field_index = -1, only transfer vdata attribute.*/

    field_index = -1;
    if(is_valid_attr_flag(attr_flag)==0) {
        H4toH5error_set(temph4toh5id,5,
                     "attribute flag is set wrong",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;        
    }

#ifdef HAVE_LIBHDFEOS
    /* This is another chance optionally activated. Even if this dataset is not part of EOS2 Grid or Swath,
     * try to create fake dimensions. Actually, those created fake dimensions have nothing to do with EOS2,
     * but I put those code not here because they are never activated without EOS2 related options. */
    if (H4toH5config_use_netcdf4_fakedim()) {
        hobj_ref_t h5dsetref;
        int handled = 0;
        if (H5Rcreate(&h5dsetref, h5_group, h5cvdata_name, H5R_OBJECT, -1) < 0) {
            H4toH5error_set(temph4toh5id, 2, "fail to create reference", __FILE__, __LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        if (H4toH5vdata_noneos_fake_dimscale(h4toh5_id, h5groupname, vdata_id, n_records, h5dset, h5dsetref, &handled) == FAIL) {
            H4toH5error_set(temph4toh5id, 2, "fail to create fake dimensions", __FILE__, __LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        if (H4toH5config_use_netcdf4_strict() && !handled) {
            H4toH5error_set(temph4toh5id, 2, "Fake dimension couldn't be handled.", __FILE__, __LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
#endif

    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        if(vdata_transattrs(h4toh5_id,vdata_id,h5dset,num_vd_attrs,field_index,
                        NULL)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                 "cannot convert vdata attributes",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        /* The following three attributes are required by HDF5 table specification,
             They HDF5 table title, HDF5 table class and HDF5 table version.*/
        if(vdata_name[0] != '\0') {


            if(h4_transpredattrs(h4toh5_id,h5dset,HDF5_TABLE_TITLE,vdata_name)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                             "unable to convert Vdata name to HDF5 table title",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }

        if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_VDATA_CLASS,VDATA_CLASS)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                         "unable to convert generate to HDF5 table class",
                         __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
         
        if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_VDATA_VERSION_ATTR,HDF5TABLE_SPE_VERSION)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                         "unable to generate HDF5 table version attribute",
                         __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        for (i =0;i< nfields;i++) {

            if(conv_int_str(h4toh5_id,(uint32)i,findex_str)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                             "cannot convert int to string",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            h5tablefieldname=malloc(strlen(h5tablefield)+strlen(h5tablename)+
                                    strlen(findex_str)+1);
            strcpy(h5tablefieldname,h5tablefield);
            strcat(h5tablefieldname,findex_str);
            strcat(h5tablefieldname,h5tablename);
            if(VFfieldname(vdata_id,i)== NULL) {
                H4toH5error_set(temph4toh5id,2,
                             "cannot obtain Vdata field name",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                free(h5tablefieldname);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            
            strcpy(fieldname,VFfieldname(vdata_id,i));
            
            if(h4_transpredattrs(h4toh5_id,h5dset,h5tablefieldname,fieldname)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                             "unable to convert generate to HDF5 table field name attribute",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                free(h5tablefieldname);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            
            free(h5tablefieldname);
            num_vd_field_attrs = VSfnattrs(vdata_id,i);
            if(num_vd_field_attrs == FAIL){
                H4toH5error_set(temph4toh5id,2,
                             "cannot obtain number of Vdata field attribute",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
             
            if(vdata_transattrs(h4toh5_id,vdata_id,h5dset,num_vd_field_attrs,i,
                            fieldname)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                             "cannot convert Vdata field attribute",
                             __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        
        /* converting annotations of vdata into corresponding hdf5 attribute.*/
            
        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5cvdata_name,(uint16)vdata_ref,
                                    vdata_tag,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                 "Vdata annotation object label conversion is wrong ",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5cvdata_name,(uint16)vdata_ref,
                                    vdata_tag,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                 "Vdata annotation object description conversion is wrong ",
                 __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        /* converting predefined attributes. */

        if(attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_ALLATTRS) {
            strcpy(vdlabel,VDATALABEL);
            if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_TYPE,vdlabel)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                     "unable to generate HDF4 OBJECT TYPE attribute",
                     __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            
    
            if(vdata_name[0] != '\0') {
                if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_NAME,vdata_name)==FAIL){
                    H4toH5error_set(temph4toh5id,5,
                                 "unable to convert Vdata name to an attribute",
                                 __FILE__,__LINE__);
                    free(h5cvdata_name);
                    H5Sclose(h5d_sid);
                    H5Dclose(h5dset);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }
                    
            if(h4_transnumattr(h4toh5_id,h5dset,HDF4_REF_NUM,(uint16)vdata_ref)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                     "unable to convert Vdata reference to an attribute",
                     __FILE__,__LINE__);
                free(h5cvdata_name);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
    }

    if(conv_1fvd_h5atom !=1) {
        H5Tclose(h5_ctype);
        H5Tclose(h5_cmemtype);
    }
    ret = H5Sclose(h5d_sid);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                 "unable to close HDF5 data space",
                 __FILE__,__LINE__);
        free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
         return FAIL;
    }
    ret = H5Dclose(h5dset);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                 "unable to close HDF5 dataset interface ",
                 __FILE__,__LINE__);
        free(h5cvdata_name);
             H5Gclose(h5_group);
        return FAIL;
    }
    ret = H5Gclose(h5_group);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                 "unable to close HDF5 group interface ",
                 __FILE__,__LINE__);
        free(h5cvdata_name);
        return FAIL;
    }
    free(h5cvdata_name);
    return SUCCEED;
}
     
/*-------------------------------------------------------------------------
 * Function:        H4toH5vdata_attr_name
 *
 * Purpose:         translate one Vdata attribute into an attribute of the
                                corresponding hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5_id:           h4toh5 identifier
                vdata_id:                vdata identifier
                h5groupfullpath: HDF5 group absolute path(must be provided)
                h5dsetname:          hdf5 dataset(can be set to NULL.If set to NULL,
                                                 HDF4 default vdata name will be used.)
                attr_name:           name of vata attribute
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int     H4toH5vdata_attr_name(hid_t h4toh5_id,
                            int32 vdata_id,
                            char* h5groupfullpath,
                            char* h5dsetname,
                            char*       attr_name)
{
     
    int attr_index; /* index of H4toH5 vdata attribute */
    h4toh5id_t* temph4toh5id; /* pointer to h4toh5 id struct for 
                                     passing parameters of error handlings */
    
    temph4toh5id = H4TOH5I_object(h4toh5_id);
    if((attr_index=VSfindattr(vdata_id,_HDF_VDATA,attr_name))==FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot allocate memory for vdata name",
                             __FILE__,__LINE__);
                return FAIL;
    }
    if(H4toH5vdata_attr_index(h4toh5_id,vdata_id,h5groupfullpath,h5dsetname,attr_index)==FAIL){
        H4toH5error_set(temph4toh5id,5,"cannot convert vdata attribute",
                             __FILE__,__LINE__);
                return FAIL;
    }
    return SUCCEED;
}
            
/*-------------------------------------------------------------------------
 * Function:        H4toH5vdata_attr_index
 *
 * Purpose:         translate one Vdata attribute into an attribute of the
                                corresponding hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5_id: h4toh5 identifier
                vdata_id: vdata identifier
                h5groupfullpath: HDF5 group absolute path(must be provided)
                h5dsetname: hdf5 dataset(can be set to NULL.If set to NULL,
                                        HDF4 default vdata name will be used.)
                attr_index: index of vata attribute
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int  H4toH5vdata_attr_index(hid_t h4toh5_id,
                            int32 vdata_id,
                            char* h5groupfullpath,
                            char* h5dsetname,
                            int     attr_index)
{
     
    char            vdata_name[H4H5_MAX_NC_NAME]; /* Vdata name */
    char*           cor_vdata_name;
    char            svdattr_name[2*H4H5_MAX_NC_NAME]; /* Vdata attribute name */
    char*           svdrepattr_name; /* temporary string to store Vdata attribute name */
    char            refstr[MAXREF_LENGTH]; /* reference number of Vdata interface with
                                        string format */
    char*           h5crepvdata_name; /* temporary string to store the absolute path of
                                 HDF5 dataset name converted from Vdata */
    char*           h5cvdata_name; /* The absolute path of HDF5 dataset name converted
                                    from Vdata */

    int32           count_svdadata; /* number of elements of the Vdata attribute */
    uint32      temp_countadata; /* temporary count of the number of elements of
                                Vdata attribute */
    int32           svd_atype; /* Vdata attribute type */
    int             istat; /* check the "return" status  of HDF4 APIs */
    int32           vdata_ref; /* Vdata reference number */

    size_t      sh4_amemsize; /* The memory size of Vdata attribute data type */
    size_t      sh4_asize; /* The file size of Vdata attribute data type */

    hid_t           sh5a_sid; /* The data space id of HDF5 attribute */
    hid_t           sh5a_id; /* The HDF5 attribute id */
    hid_t           sh5_atype; /* The file data type id of HDF5 attribute */
    hid_t           sh5_amemtype;/* The memory data type id of HDF5 attribute */
    hid_t           sh5str_type; /* The file data type id of HDF5 attribute with string
                                format */
    hid_t           sh5str_memtype; /* The memory data type id of HDF5 attribute with 
                                     string format */

    hid_t           h5_group; /* The HDF5 group id */
    hid_t           h5dset; /* The HDF5 dataset id */
    hsize_t     sh5dims[1]; /* The size of the dimension of the HDF5 attribute
                                 converted from Vdata attribute */
    void*           svd_adata; /* Vdata buffer */
    herr_t      sret; /* the flag to check the "return" status of HDF5 APIs. */
    char* cor_h5dsetname;

    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */

    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /* zeroing out memory for svdattr_name and refstr */                                                 
    h4toh5_ZeroMemory(svdattr_name,2*H4H5_MAX_NC_NAME); 
    h4toh5_ZeroMemory(refstr,MAXREF_LENGTH);                    

     /* The following block obtains group name and dataset name. */
    /* obtain h5_group id */
    h5_group        =  get_h5groupid(h5groupfullpath,h4toh5_id,H425_OSPEC_ALLATTRS);
    if(h5_group < 0) {
        H4toH5error_set(temph4toh5id,5,
                     "cannot obtain HDF5 group ID",
                     __FILE__,__LINE__);
        return FAIL;
    }

    /*obtain default vdata name */
    istat = VSQueryname(vdata_id,vdata_name);
    if(istat == FAIL) {
         H4toH5error_set(temph4toh5id,2,"cannot obtain the Vdata name",
                     __FILE__,__LINE__);
         H5Gclose(h5_group);
         return FAIL;
    }
         
    vdata_ref = VSQueryref(vdata_id);
    if(vdata_ref < 0) {
        H4toH5error_set(temph4toh5id,2,"cannot obtain the reference number of Vdata",
                     __FILE__,__LINE__);
         H5Gclose(h5_group);
         return FAIL;
    }

    if(h5dsetname == NULL) {
         /* change format of reference number. */
        if(conv_int_str(h4toh5_id,(uint32)vdata_ref,refstr)== FAIL) {
            H4toH5error_set(temph4toh5id,5,"cannot convert reference number into string type",
                     __FILE__,__LINE__);
             H5Gclose(h5_group);
            return FAIL;
        }
        h5crepvdata_name=make_objname_no(h4toh5_id,refstr,h5groupfullpath,
                                             HDF4_VDATA);
        
        if(lookup_name(h4toh5_id,h5crepvdata_name,VD_HASHSIZE,
                             temph4toh5id->name_hashtab)==1){
            h5cvdata_name = malloc(strlen(h5crepvdata_name)+1);
            if(h5cvdata_name == NULL) {
                H4toH5error_set(temph4toh5id,1,"cannot allocate memory for vdata name",
                             __FILE__,__LINE__);
                 H5Gclose(h5_group);
                return FAIL;
            }
            strncpy(h5cvdata_name,h5crepvdata_name,strlen(h5crepvdata_name));
        }
         else {
             cor_vdata_name=correct_name(h4toh5_id,vdata_name);
             if(cor_vdata_name== NULL) {
                 H4toH5error_set(temph4toh5id,1,"cannot allocate memory for corrected vdata name",
                                  __FILE__,__LINE__);
                 H5Gclose(h5_group);
                return FAIL;
             }
             h5cvdata_name = make_objname_yes(h4toh5_id,cor_vdata_name,h5groupfullpath);
             free(cor_vdata_name);
         }  
         free(h5crepvdata_name);
    }
    else {
        cor_h5dsetname= correct_name(h4toh5_id,h5dsetname);
        if(cor_h5dsetname== NULL) {
            H4toH5error_set(temph4toh5id,1,"cannot allocate memory for corrected vdata name",
                             __FILE__,__LINE__);
                 H5Gclose(h5_group);
                return FAIL;
        }
        h5cvdata_name = make_objname_yes(h4toh5_id,cor_h5dsetname,h5groupfullpath);
        free(cor_h5dsetname);
    }

    h5dset = H5DOPEN(h5_group,h5cvdata_name);
    if(h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,"cannot open HDF5 data set",
                             __FILE__,__LINE__);
        H5Gclose(h5_group);
                 free(h5cvdata_name);
                return FAIL;
    }
    
    /* if the field_index is -1, no field attribute exists, only
         VDATA attributes are converted.*/
    if (VSattrinfo(vdata_id,_HDF_VDATA,attr_index,svdattr_name,&svd_atype,
                 &count_svdadata,NULL)== FAIL){  
        H4toH5error_set(temph4toh5id,2,
             "unable to obtain Vdata attribute information",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
             free(h5cvdata_name);
        return FAIL;
    }
             
    if(svdattr_name[0] == '\0') {
        svdrepattr_name = trans_obj_name(h4toh5_id,DFTAG_VG,attr_index);
        strcpy(svdattr_name,svdrepattr_name);
        free(svdrepattr_name);
    }

    /* converting attribute data type into the corresponding HDF5 data type */
    if(h4type_to_h5type(h4toh5_id,svd_atype,&sh5_amemtype,&sh4_amemsize,
                    &sh4_asize,&sh5_atype)==FAIL){
        H4toH5error_set(temph4toh5id,5,
             "unable to convert HDF4 data type into HDF5 data type",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
             free(h5cvdata_name);
        return FAIL;
    }

    svd_adata = malloc(sh4_amemsize * count_svdadata);
    if(svd_adata == NULL) {
        H4toH5error_set(temph4toh5id,1,
             "unable to allocate memory for vdata attribute data",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
             free(h5cvdata_name);
        return FAIL;
    }

    if(VSgetattr(vdata_id,_HDF_VDATA,attr_index,(VOIDP)svd_adata)==FAIL){
        H4toH5error_set(temph4toh5id,2,
             "unable to obtain Vdata attribute",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
        free(svd_adata);
             free(h5cvdata_name);
        return FAIL;
    }
    
    /* now do attribute-transferring:
         1. deal with string data type
         2. set attribute space
         3. get attribute name  */
                 
    if (sh5_atype == H5T_STRING) {

        temp_countadata = count_svdadata*sh4_asize;
        H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5_id,(size_t)count_svdadata,
                                 H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to make HDF5 string data type",
                         __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }

        if ((sh5str_memtype = mkstr(h4toh5_id,(size_t)(count_svdadata*sh4_amemsize),
                                H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,5,
                         "unable to make HDF5 string data type for memory",
                         __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }

        sh5a_sid = H5Screate(H5S_SCALAR);

        if (sh5a_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to create HDF5 data space",
                         __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }

        sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5str_type,
                        sh5a_sid,H5P_DEFAULT);
        if (sh5a_id <0) {
            if (transattrs_split(h4toh5_id, h5dset, svdattr_name, sh5a_sid, svd_adata, count_svdadata) < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to CREATE HDF5 attribute",
                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                 H5Gclose(h5_group);
                         free(h5cvdata_name);
                free(svd_adata);
                return FAIL;
            }
        }
        else if (H5Awrite(sh5a_id,sh5str_memtype,(void *)svd_adata) < 0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to write attribute",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }
    }
     
    else {
        
        if(count_svdadata == 1) {
            sh5a_sid = H5Screate(H5S_SCALAR);
            if (sh5a_sid < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 space id for attribute",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                free(h5cvdata_name);
                free(svd_adata);
                return FAIL;
            }
        }
        else {
            sh5dims[0] = count_svdadata;
            sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);
                
            if (sh5a_sid < 0)  {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 space id for attribute",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                free(h5cvdata_name);
                free(svd_adata);
                return FAIL;
            }
        }

        sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5_atype,
                        sh5a_sid,H5P_DEFAULT);
    
        if(sh5a_id <0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to create HDF5 attribute ID",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }

        sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)svd_adata);

        if(sret <0) {

            H4toH5error_set(temph4toh5id,3,
                         "unable to write HDF5 attribute data",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }
    }
    free(h5cvdata_name);
    free(svd_adata);
    sret = H5Sclose(sh5a_sid);
    if( sret < 0) {
        H4toH5error_set(temph4toh5id,3,
                     "unable to close HDF5 attribute data space",
                     __FILE__,__LINE__);
        H5Aclose(sh5a_id);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
    if (sh5a_id >= 0) {
        sret = H5Aclose(sh5a_id);
        if( sret < 0) {
            H4toH5error_set(temph4toh5id,3,
                 "unable to close HDF5 attribute interface",
                 __FILE__,__LINE__);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    sret = H5Dclose(h5dset);
    if(sret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "unable to close HDF5 dataset",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
    }
    sret = H5Gclose(h5_group);
    if(sret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "unable to close HDF5 attribute interface",
             __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:        H4toH5vdata_field_attr_index
 *
 * Purpose:         translate one Vdata field attribute into an attribute of the
                                corresponding hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5_id: h4toh5 identifier
                vdata_id: vdata identifier
                h5groupfullpath: HDF5 group absolute path(must be provided)
                h5dsetname: hdf5 dataset(can be set to NULL.If set to NULL,
                                        HDF4 default vdata name will be used.)
                field_index: index of vata field
                field_attrindex: index of vdata field attribute
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int  H4toH5vdata_field_attr_index(hid_t h4toh5_id,
                                     int32 vdata_id,
                                     char* h5groupfullpath,
                                     char* h5dsetname,
                                     int     field_index,
                                     int     field_attrindex)
{
     
    char            vdata_name[H4H5_MAX_NC_NAME]; /* Vdata name */
    char*           cor_vdata_name;
    char            svdattr_name[2*H4H5_MAX_NC_NAME]; /* Vdata attribute name */
    char            fieldname[H4H5_MAX_NC_NAME]; /* Vdata field name */
    char            refstr[MAXREF_LENGTH]; /* reference number of Vdata interface with
                                        string format */
    char*           h5crepvdata_name; /* temporary string to store the absolute path of
                                 HDF5 dataset name converted from Vdata */
    char*           h5cvdata_name; /* The absolute path of HDF5 dataset name converted
                                    from Vdata */

    int32           count_svdadata; /* number of elements of the Vdata attribute */
    uint32      temp_countadata; /* temporary count of the number of elements of
                                Vdata attribute */
    int32           svd_atype;  /* Vdata attribute type */
    int             istat;  /* check the "return" status    of HDF4 APIs */
    int32           vdata_ref;  /* Vdata reference number */

    size_t      sh4_amemsize; /* The memory size of Vdata attribute data type */
    size_t      sh4_asize; /* The file size of Vdata attribute data type */

    hid_t           sh5a_sid; /* The data space id of HDF5 attribute */
    hid_t           sh5a_id; /* The HDF5 attribute id */
    hid_t           sh5_atype; /* The file data type id of HDF5 attribute */
    hid_t           sh5_amemtype; /* The memory data type id of HDF5 attribute */
    hid_t           sh5str_type; /* The file data type id of HDF5 attribute with string
                                format */
    hid_t           sh5str_memtype; /* The memory data type id of HDF5 attribute with 
                                     string format */

    hid_t           h5_group; /* The HDF5 group id */
    hid_t           h5dset; /* The HDF5 dataset id */
    hsize_t     sh5dims[1]; /* The size of the dimension of the HDF5 attribute
                                 converted from Vdata attribute */
    void*           svd_adata; /* Vdata buffer */
    herr_t      sret; /* the flag to check the "return" status of HDF5 APIs. */
    char*        cor_h5dsetname;
    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */

    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /* zeroing out memory for svdattr_name and refstr */                                                    
    h4toh5_ZeroMemory(svdattr_name,2*H4H5_MAX_NC_NAME); 
    svdattr_name[0]='\0';
    h4toh5_ZeroMemory(refstr,MAXREF_LENGTH);                    

     /* The following block obtains group name and dataset name. */
    /* obtain h5_group id */
    h5_group        =  get_h5groupid(h5groupfullpath,h4toh5_id,H425_OSPEC_ALLATTRS);
    if(h5_group < 0) {
        H4toH5error_set(temph4toh5id,5,
                     "cannot obtain HDF5 group ID",
                     __FILE__,__LINE__);
        return FAIL;
    }

    
    /*obtain default vdata name */
    istat = VSQueryname(vdata_id,vdata_name);
    if(istat == FAIL) {
         H4toH5error_set(temph4toh5id,2,"cannot obtain the Vdata name",
                     __FILE__,__LINE__);
         H5Gclose(h5_group);
         return FAIL;
    }

    vdata_ref = VSQueryref(vdata_id);
    if(vdata_ref < 0) {
        H4toH5error_set(temph4toh5id,2,"cannot obtain the reference number of Vdata",
                     __FILE__,__LINE__);
         H5Gclose(h5_group);
         return FAIL;
    }

    if(h5dsetname == NULL) {
         /* change format of reference number. */
        if(conv_int_str(h4toh5_id,(uint32)vdata_ref,refstr)== FAIL) {
            H4toH5error_set(temph4toh5id,5,"cannot convert reference number into string type",
                     __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
        h5crepvdata_name=make_objname_no(h4toh5_id,refstr,h5groupfullpath,
                                             HDF4_VDATA);
        
        if(lookup_name(h4toh5_id,h5crepvdata_name,VD_HASHSIZE,
                             temph4toh5id->name_hashtab)==1){
            h5cvdata_name = malloc(strlen(h5crepvdata_name)+1);
            if(h5cvdata_name == NULL) {
                H4toH5error_set(temph4toh5id,1,"cannot allocate memory for vdata name",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                return FAIL;
            }
            strncpy(h5cvdata_name,h5crepvdata_name,strlen(h5crepvdata_name));
        }
        else {
            cor_vdata_name= correct_name(h4toh5_id,vdata_name);
            if(cor_vdata_name == NULL) {
                H4toH5error_set(temph4toh5id,1,"cannot allocate memory for corrected vdata name",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                return FAIL;
            }
            h5cvdata_name = make_objname_yes(h4toh5_id,cor_vdata_name,h5groupfullpath);
            free(cor_vdata_name);
        }
        free(h5crepvdata_name);
    }
    else {
        cor_h5dsetname = correct_name(h4toh5_id,h5dsetname);
        if(cor_h5dsetname == NULL) {
            H4toH5error_set(temph4toh5id,1,"cannot allocate memory for corrected vdata name",
                             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
        h5cvdata_name = make_objname_yes(h4toh5_id,cor_h5dsetname,h5groupfullpath);
        free(cor_h5dsetname);
    } 
    h5dset = H5DOPEN(h5_group,h5cvdata_name);
    if(h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,"cannot open HDF5 data set",
                             __FILE__,__LINE__);
        H5Gclose(h5_group);
        free(h5cvdata_name);
        return FAIL;
    }

    if(VFfieldname(vdata_id,field_index)== NULL) {
        H4toH5error_set(temph4toh5id,2,
                     "cannot obtain Vdata field name",
                     __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    strcpy(fieldname,VFfieldname(vdata_id,field_index));

    /* if the field_index is -1, no field attribute exists, only
         VDATA attributes are converted.*/
    if (VSattrinfo(vdata_id,field_index,field_attrindex,svdattr_name,&svd_atype,
                 &count_svdadata,NULL)== FAIL){  
        H4toH5error_set(temph4toh5id,2,
             "unable to obtain Vdata attribute information",
             __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
    if (field_index != -1 && svdattr_name[0] != '\0') {
        strcat(svdattr_name,":");
        strcat(svdattr_name,fieldname);
    }

    else {
        strcat(svdattr_name,":");
        strcat(svdattr_name,"HDF4_VDATA_ATTR_");
        if(conv_int_str(h4toh5_id,(uint32)field_index,refstr)==FAIL) {
            H4toH5error_set(temph4toh5id,5,
                         "unable to convert vdata field index to string",
                         __FILE__,__LINE__);
            free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        strcat(svdattr_name,refstr);
        
    }

    /* converting attribute data type into the corresponding HDF5 data type */

    if(h4type_to_h5type(h4toh5_id,svd_atype,&sh5_amemtype,&sh4_amemsize,
                    &sh4_asize,&sh5_atype)==FAIL){
        H4toH5error_set(temph4toh5id,5,
             "unable to convert HDF4 data type into HDF5 data type",
             __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    svd_adata = malloc(sh4_amemsize * count_svdadata);
    if(svd_adata == NULL) {
        H4toH5error_set(temph4toh5id,1,
             "unable to allocate memory for vdata attribute data",
             __FILE__,__LINE__);
        free(h5cvdata_name);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(VSgetattr(vdata_id,field_index,field_attrindex,(VOIDP)svd_adata)==FAIL){
        H4toH5error_set(temph4toh5id,2,
             "unable to obtain Vdata attribute",
             __FILE__,__LINE__);
        free(svd_adata);
        free(h5cvdata_name);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
    
    /* now do attribute-transferring:
         1. deal with string data type
         2. set attribute space
         3. get attribute name  */
                 
    if (sh5_atype == H5T_STRING) {

        temp_countadata = count_svdadata*sh4_asize;
        H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_countadata,
                                 H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to make HDF5 string data type",
                         __FILE__,__LINE__);
            free(svd_adata);
            free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if ((sh5str_memtype = mkstr(h4toh5_id,count_svdadata*sh4_amemsize,
                                H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,5,
                         "unable to make HDF5 string data type for memory",
                         __FILE__,__LINE__);
            free(svd_adata);
            free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        sh5a_sid = H5Screate(H5S_SCALAR);

        if (sh5a_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to create HDF5 data space",
                         __FILE__,__LINE__);
            free(svd_adata);
            free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5str_type,
                        sh5a_sid,H5P_DEFAULT);
        if (sh5a_id <0) {
            if (transattrs_split(h4toh5_id, h5dset, svdattr_name, sh5a_sid, svd_adata, count_svdadata) < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to CREATE HDF5 attribute",
                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                free(svd_adata);
                free(h5cvdata_name);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        else if (H5Awrite(sh5a_id,sh5str_memtype,(void *)svd_adata) < 0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to write attribute",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            free(h5cvdata_name);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            free(svd_adata);
            return FAIL;
        }
    }
    else {
        
        if(count_svdadata == 1) {
            sh5a_sid = H5Screate(H5S_SCALAR);

            if (sh5a_sid < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 space id for attribute",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                free(h5cvdata_name);
                free(svd_adata);
                return FAIL;
            }
        }
        else {
            sh5dims[0] = count_svdadata;
            sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);
                
            if (sh5a_sid < 0)  {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 space id for attribute",
                             __FILE__,__LINE__);
                H5Gclose(h5_group);
                free(h5cvdata_name);
                free(svd_adata);
                return FAIL;
            }
        }

        sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5_atype,
                        sh5a_sid,H5P_DEFAULT);
    
        if(sh5a_id <0) {
            H4toH5error_set(temph4toh5id,3,
                         "unable to create HDF5 attribute ID",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }

        sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)svd_adata);

        if(sret <0) {

            H4toH5error_set(temph4toh5id,3,
                         "unable to write HDF5 attribute data",
                         __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            H5Gclose(h5_group);
            free(h5cvdata_name);
            free(svd_adata);
            return FAIL;
        }
    }

    free(h5cvdata_name);
    free(svd_adata);
    sret = H5Sclose(sh5a_sid);
    if( sret < 0) {
        H4toH5error_set(temph4toh5id,3,
                     "unable to close HDF5 attribute data space",
                     __FILE__,__LINE__);
        H5Aclose(sh5a_id);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    if (sh5a_id >= 0) {
        sret = H5Aclose(sh5a_id);
        if( sret < 0) {
            H4toH5error_set(temph4toh5id,3,
                        "unable to close HDF5 attribute interface",
                        __FILE__,__LINE__);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    sret = H5Dclose(h5dset);
    if( sret <0) {
         H4toH5error_set(temph4toh5id,3,
                                     "unable to close HDF5 dataset interface",
                                    __FILE__,__LINE__);         
         H5Gclose(h5_group);
    }
    sret = H5Gclose(h5_group);
    if(sret < 0) {
        H4toH5error_set(temph4toh5id,3,
                     "unable to close HDF5 attribute interface",
                     __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}


/*-------------------------------------------------------------------------
 * Function:        H4toH5vdata_field_attr_name
 *
 * Purpose:         translate one Vdata field attribute into an attribute of the
                                corresponding hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5_id: h4toh5 identifier
                vdata_id: vdata identifier
                h5groupfullpath: HDF5 group absolute path(must be provided)
                h5dsetname: hdf5 dataset(can be set to NULL.If set to NULL,
                                        HDF4 default vdata name will be used.)
                field_index: index of vata field
                field_attrindex: index of vdata field attribute
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int  H4toH5vdata_field_attr_name (hid_t h4toh5_id,
                                     int32 vdata_id,
                                     char* h5groupfullpath,
                                     char* h5dsetname,
                                     char* fieldname,
                                     char* field_attrname)
{
    
    int32 field_attrindex; /* field attribute index */
    int32 field_index; /* field index */
    
    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */


    field_index = -1;

    
    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /* obtain field and field attribute index */
    if(VSfindex(vdata_id,fieldname,&field_index)==FAIL){
        H4toH5error_set(temph4toh5id,2,"cannot retrieve field attribute index",
                     __FILE__,__LINE__);
        return FAIL;
    }

    field_attrindex = VSfindattr(vdata_id,field_index,field_attrname);
    if(field_attrindex == FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot retrieve field attribute index",
                     __FILE__,__LINE__);
        return FAIL;
    }
         
    if(H4toH5vdata_field_attr_index(h4toh5_id,vdata_id,h5groupfullpath,h5dsetname,field_index,field_attrindex) == FAIL) {
        H4toH5error_set(temph4toh5id,5,"cannot convert VDATA field attribute",
                     __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:        vdata_transattrs
 *
 * Purpose:         translate Vdata attributes into attributes of the
                                corresponding hdf5 dataset 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                vdata_id: vdata identifier
                h5dset: hdf5 dataset
                snum_vdattrs: number of vd attributes
                field_index:    index of vdata fields
                attr_name: vdata(or vdata field) attribute name
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int  vdata_transattrs(hid_t h4toh5_id,
                            int32 vdata_id,
                            hid_t h5dset,
                            int snum_vdattrs,
                            int field_index,
                            char* attr_name)
{
     
    char            svdattr_name[2*H4H5_MAX_NC_NAME]; /* Vdata attribute name */
    char*           svdrepattr_name; /* temporary string to store Vdata attribute
                                name */
    char            refstr[MAXREF_LENGTH]; /* reference number of Vdata interface with
                                        string format */
    int32           count_svdadata; /* number of elements of the Vdata attribute */
    uint32      temp_countadata; /* temporary count of the number of elements of
                                Vdata attribute */
    int32           svd_atype; /* Vdata attribute type */

    size_t      sh4_amemsize; /* The memory size of Vdata attribute data type */
    size_t      sh4_asize; /* The file size of Vdata attribute data type */

    hid_t           sh5a_sid; /* The data space id of HDF5 attribute */
    hid_t           sh5a_id; /* The HDF5 attribute id */
    hid_t           sh5_atype; /* The file data type id of HDF5 attribute */
    hid_t           sh5_amemtype; /* The memory data type id of HDF5 attribute */
    hid_t           sh5str_type; /* The file data type id of HDF5 attribute with string
                                format */
    hid_t           sh5str_memtype;  /* The memory data type id of HDF5 attribute with 
                                     string format */

    hsize_t     sh5dims[1]; /* The size of the dimension of the HDF5 attribute
                                 converted from Vdata attribute */
    void*           svd_adata; /* Vdata buffer */
    herr_t      sret; /* the flag to check the "return" status of HDF5 APIs. */
    int             i;
    
    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */


    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /* zeroing out memory for svdattr_name and refstr */                                                                    
    h4toh5_ZeroMemory(svdattr_name,2*H4H5_MAX_NC_NAME); 
    h4toh5_ZeroMemory(refstr,MAXREF_LENGTH);                    

    /* separate vdata attribute from vdata field attributes. */

    if (field_index < -1) {
        H4toH5error_set(temph4toh5id,2,
                     "Vdata field index should not be less than -1",
                     __FILE__,__LINE__);
        return FAIL;
    }

    for (i = 0;i < snum_vdattrs; i++) {

        /* if the field_index is 0, no field attribute exists, only
             VDATA attributes are converted.*/

        if (VSattrinfo(vdata_id,field_index,i,svdattr_name,&svd_atype,
                     &count_svdadata,NULL)== FAIL){  
            H4toH5error_set(temph4toh5id,2,
                 "unable to obtain Vdata attribute information",
                 __FILE__,__LINE__);
            return FAIL;
        }
                 
        if(svdattr_name[0] == '\0') {
            svdrepattr_name = trans_obj_name(h4toh5_id,DFTAG_VG,i);
            strcpy(svdattr_name,svdrepattr_name);
            free(svdrepattr_name);
        }

        if (field_index == -1);

        else if (field_index != -1 && attr_name != NULL) {
            strcat(svdattr_name,":");
            strcat(svdattr_name,attr_name);
        }

        else {
            strcat(svdattr_name,":");
            strcat(svdattr_name,"HDF4_VDATA_ATTR_");
            if(conv_int_str(h4toh5_id,(uint32)field_index,refstr)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                             "unable to convert vdata field index to string",
                             __FILE__,__LINE__);
                return FAIL;
            }
            strcat(svdattr_name,refstr);
        }

        /* converting attribute data type into the corresponding HDF5 data type */

        if(h4type_to_h5type(h4toh5_id,svd_atype,&sh5_amemtype,&sh4_amemsize,
                        &sh4_asize,&sh5_atype)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                 "unable to convert HDF4 data type into HDF5 data type",
                 __FILE__,__LINE__);
            return FAIL;
        }

        svd_adata = malloc(sh4_amemsize * count_svdadata);

        if(svd_adata == NULL) {
            H4toH5error_set(temph4toh5id,1,
                 "unable to allocate memory for vdata attribute data",
                 __FILE__,__LINE__);
            return FAIL;
        }

        if(VSgetattr(vdata_id,field_index,i,(VOIDP)svd_adata)==FAIL){
            H4toH5error_set(temph4toh5id,2,
                 "unable to obtain Vdata attribute",
                 __FILE__,__LINE__);
            free(svd_adata);
            return FAIL;
        }
        
        /* now do attribute-transferring:
             1. deal with string data type
             2. set attribute space
             3. get attribute name  */
                     
        if (sh5_atype == H5T_STRING) {

            temp_countadata = count_svdadata*sh4_asize;
            H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
            if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_countadata,
                                     H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to make HDF5 string data type",
                             __FILE__,__LINE__);
                free(svd_adata);
                return FAIL;
            }

            if ((sh5str_memtype = mkstr(h4toh5_id,count_svdadata*sh4_amemsize,
                                    H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,5,
                             "unable to make HDF5 string data type for memory",
                             __FILE__,__LINE__);
                free(svd_adata);
                return FAIL;
            }

            sh5a_sid = H5Screate(H5S_SCALAR);

            if (sh5a_sid < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 data space",
                             __FILE__,__LINE__);
                free(svd_adata);
                return FAIL;
            }

            sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5str_type,
                            sh5a_sid,H5P_DEFAULT);
            if (sh5a_id <0) {
                if (transattrs_split(h4toh5_id, h5dset, svdattr_name, sh5a_sid, svd_adata, count_svdadata) < 0) {
                    H4toH5error_set(temph4toh5id,3,
                                 "unable to CREATE HDF5 attribute",
                                 __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    free(svd_adata);
                    return FAIL;
                }
            }
            else if (H5Awrite(sh5a_id,sh5str_memtype,(void *)svd_adata) < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to write attribute",
                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Aclose(sh5a_id);
                free(svd_adata);
                return FAIL;
            }
        }
         
        else {
            /* netCDF4 cannot read numeric values of scalar space.
             * Force to use Simple type even if count_svdadata == 1
             */
            if(!H4toH5config_use_netcdf4_hack() && count_svdadata == 1) {
                sh5a_sid = H5Screate(H5S_SCALAR);
                if (sh5a_sid < 0) {
                    H4toH5error_set(temph4toh5id,3,
                                 "unable to create HDF5 space id for attribute",
                                 __FILE__,__LINE__);
                    free(svd_adata);
                    return FAIL;
                }
            }
            else {
                sh5dims[0] = count_svdadata;
                sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);
                    
                if (sh5a_sid < 0)  {
                    H4toH5error_set(temph4toh5id,3,
                                 "unable to create HDF5 space id for attribute",
                                 __FILE__,__LINE__);
                    free(svd_adata);
                    return FAIL;
                }
            }

            sh5a_id = H5Acreate_safe(h4toh5_id,h5dset,svdattr_name,sh5_atype,
                            sh5a_sid,H5P_DEFAULT);
        
            if(sh5a_id <0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 attribute ID",
                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                free(svd_adata);
                return FAIL;
            }

            sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)svd_adata);

            if(sret <0) {

                H4toH5error_set(temph4toh5id,3,
                             "unable to write HDF5 attribute data",
                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Aclose(sh5a_id);
                free(svd_adata);
                return FAIL;
            }
        }
        sret = H5Sclose(sh5a_sid);
        if(sret < 0) {
            H4toH5error_set(temph4toh5id,3,
                     "unable to close HDF5 data space",
                     __FILE__,__LINE__);
            H5Aclose(sh5a_id);
            free(svd_adata);
            return FAIL;
        }
        if (sh5a_id >= 0) {
            sret = H5Aclose(sh5a_id);
            if(sret < 0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to close HDF5 attribute id",
                             __FILE__,__LINE__);
                free(svd_adata);
                return FAIL;
            }
        }
        free(svd_adata);
    }
    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:        gen_h5comptype
 *
 * Purpose:         generate hdf5 compound data type
                                 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                vdata_id: vdata identifier
                nfields: number of fields
                sh4size: pointer to datatype size in memory
                sh4memsize: pointer to datatype size in memory
                sh5type: pointer to hdf5 datatype
                sh5memtype: pointer to actual hdf5 datatype in memory
                h5_ctype:  hdf5 compound datatype
                h5_cmemtype: hdf5 compound datatype in memory
     Out:
     Modifications:

 *-------------------------------------------------------------------------
 */ 

int gen_h5comptype(hid_t h4toh5_id,
                     int32 vdata_id,
                     int32 nfields,
                     size_t* sh4size,
                     size_t* sh4memsize,
                     hid_t* sh5type,
                     hid_t* sh5memtype,
                     hid_t h5_ctype,
                     hid_t h5_cmemtype)
{

    char*       fieldname; /* Vdata field name */
    int32       fieldorder; /* Vdata field order */
    size_t  fil_offset; /* offset of atomic data type in a file compound data type */
    size_t  mem_offset; /* offset of atomic data type in a memory compound data type */
    hsize_t fielddim[1]; /* size of the dimension of the field */
    hid_t       h5str_type; /* HDF5 string data type */
    int         check_ifstr;/* flag to check if the h5 type is string.*/
    int         i;
    h4toh5id_t* temph4toh5id; /*    pointer to h4toh5 id struct for 
                                passing parameters of error handlings */

    /* obtain global table*/

    temph4toh5id = H4TOH5I_object(h4toh5_id);

    check_ifstr      = 0;
    fil_offset       = 0;
    mem_offset       = 0;

    for (i =0;i< nfields;i++) {
     
        fieldname = NULL;
        fieldorder = VFfieldorder(vdata_id,i);
     
        if(fieldorder == FAIL){
            H4toH5error_set(temph4toh5id,2,
                 "unable to obtain Vdata field order",
                 __FILE__,__LINE__);
            return FAIL;
        }

        fieldname = VFfieldname(vdata_id,i);
        if(fieldname == NULL){
            H4toH5error_set(temph4toh5id,2,
                 "unable to obtain Vdata field name",
                 __FILE__,__LINE__);
            return FAIL;
        }
     

        /* when vdata is a character array, we will write the whole
             array as one hdf5 type string. */

        if(sh5type[i] == H5T_STRING) {

            if ((h5str_type = mkstr(h4toh5_id,sh4size[i]*fieldorder,H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to make HDF5 string",
                             __FILE__,__LINE__);
                return FAIL;
            }
            sh5type[i] = h5str_type;
            check_ifstr  = 1;
        }

        if (sh5memtype[i] == H5T_STRING) {

            if((h5str_type = mkstr(h4toh5_id,sh4memsize[i]*fieldorder,H5T_STR_NULLTERM))<0){ 
                H4toH5error_set(temph4toh5id,3,
                             "unable to make HDF5 string for memeory",
                             __FILE__,__LINE__);
                return FAIL;
            }
            sh5memtype[i] = h5str_type;

        }

        fielddim[0] = fieldorder;
                
        /* if field type is an array, use H5Tinsert_array. 
             When the data type is H5T_STRING, 
             we will treat the the vdata    as a HDF5 scalar type.*/

        if (fielddim[0] == 1 || check_ifstr == 1) {

            if(H5Tinsert(h5_ctype,fieldname,fil_offset,sh5type[i])<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to insert HDF5 compound data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            if(H5Tinsert(h5_cmemtype,fieldname,mem_offset,sh5memtype[i])<0){
                H4toH5error_set(temph4toh5id,3,
                             "unable to insert HDF5 memory compound data type",
                             __FILE__,__LINE__);
                return FAIL;
            }
        }
            
        else {
            hid_t arr_type;      /* Array datatype for inserting fields */

            /* Create array datatype */
            if((arr_type=H5TARRAY_CREATE(sh5type[i],1,fielddim,NULL))<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 array data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            if(H5Tinsert(h5_ctype,fieldname,fil_offset,arr_type)<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to insert HDF5 array data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            /* Close array datatype */
            if(H5Tclose(arr_type)<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to close HDF5 data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            /* Create array datatype */
            if((arr_type=H5TARRAY_CREATE(sh5memtype[i],1,fielddim,NULL))<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to create HDF5 array data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            if(H5Tinsert(h5_cmemtype,fieldname,mem_offset,arr_type)<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to insert HDF5 array data type",
                             __FILE__,__LINE__);
                return FAIL;
            }

            /* Close array datatype */
            if(H5Tclose(arr_type)<0) {
                H4toH5error_set(temph4toh5id,3,
                             "unable to close HDF5 array data type",
                             __FILE__,__LINE__);
                return FAIL;
            }
        }

        if( check_ifstr == 1) {
            fil_offset = fil_offset + sh4size[i]*fieldorder;
            mem_offset = mem_offset + sh4memsize[i]*fieldorder;
            check_ifstr = 0;
        }
        else { 
            fil_offset = fil_offset + sh4size[i]*fieldorder;
            mem_offset = mem_offset + sh4memsize[i]*fieldorder;
        }

    }

    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:        H4toH5all_lone_vdata
 *
 * Purpose:         convert all independent Vdata objects to HDF5 datasets
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                h4toh5id: h4toh5 identifier
                h5groupname: absolute path of HDF5 group
                attr_flag: attribute flag
 *-------------------------------------------------------------------------     
*/
int H4toH5all_lone_vdata(hid_t h4toh5id,char* h5groupname,
                             int attr_flag)
{

    int32  file_id; /* HDF4 file id */
    int32  vdata_id; /* HDF4 Vdata id */
    int32  *ref_vdata_array; /* array to store Vdata reference number */
    int32  istat; /* check the "return" status  of HDF4 APIs */
    char     vdata_class[VGNAMELENMAX]; /* Vdata class name */
    char     vdata_name[VGNAMELENMAX];
    int      lone_vd_index; /* index of lone Vdata */
    int      num_lonevd; /* number of lone Vdata */
    h4toh5id_t * temph4toh5id;

    temph4toh5id = H4TOH5I_object(h4toh5id);

    file_id = temph4toh5id->file_id;
    num_lonevd = VSlone(file_id,NULL,0);

    if (num_lonevd == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                     "unable to obtain amount of Vdata ",
                     __FILE__,__LINE__);
        return FAIL;
    }

    if (num_lonevd > 0) {

        ref_vdata_array = (int32 *)malloc(sizeof(int32) *(num_lonevd));

        num_lonevd = VSlone(file_id,ref_vdata_array,num_lonevd);

        if(num_lonevd == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                    "unable to obtain amount of Vdata ",
                    __FILE__,__LINE__);
            free(ref_vdata_array);
            return FAIL;
        }
        /* walk through all lone vdatas. */

        for(lone_vd_index = 0; lone_vd_index < num_lonevd;lone_vd_index++) 
        {
            vdata_id = VSattach(file_id,ref_vdata_array[lone_vd_index],"r");
           
            if(vdata_id == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                        "unable to obtain Vdata id",
                        __FILE__,__LINE__);
                free(ref_vdata_array);
                return FAIL;
            }
            h4toh5_ZeroMemory(vdata_name,VGNAMELENMAX);
            VSQueryname(vdata_id,vdata_name);
            /* Make sure this vdata is not an attribute of other hdf4 objects.*/
    
            if(!VSisattr(vdata_id)) {
                        
                h4toh5_ZeroMemory(vdata_class,VGNAMELENMAX);
                istat = VSgetclass(vdata_id,vdata_class);
                if(istat == FAIL) {
                    H4toH5error_set(temph4toh5id,2,
                           "unable to get Vdata class name",
                           __FILE__,__LINE__);
                    free(ref_vdata_array);
                    VSdetach(vdata_id);
                    return FAIL;
                }
                                    
                if(!strncmp(vdata_class,_HDF_CHK_TBL_CLASS,strlen(_HDF_CHK_TBL_CLASS))){
                           
                    VSdetach(vdata_id);         
                    continue;
                }
                       
                if(H4toH5vdata(h4toh5id,vdata_id,h5groupname,NULL,attr_flag)== FAIL) {
                    H4toH5error_set(temph4toh5id,2,
                           "cannot translate independent vdata to HDF5 datasets.",
                           __FILE__,__LINE__);
                    free(ref_vdata_array);
                    VSdetach(vdata_id);
                    return FAIL;
                }
    
            }
            istat = VSdetach(vdata_id);
            if(istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                           "cannot detach Vdata interface",
                           __FILE__,__LINE__);
                    free(ref_vdata_array);
                    return FAIL;
            }
        }
        free(ref_vdata_array);
    }
    return SUCCEED;     
}
 
