/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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. h4toh5 converter library API

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

2. this file includes three APIs.

         2.1: H4toH5sds
         convert an hdf4 sds object into an hdf5 dataset

         2.2: H4toH5one_dimscale
         convert an hdf4 sds dimensional scale dataset into an hdf5 dataset

         2.3: H4toH5all_dimscale
         convert all hdf5 sds dimensional scale datasets of one hdf4
         object into hdf5 datasets
Author:  Kent Yang(myang6@hdfgroup.org)


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

#include "h4toh5main.h"

    /*-------------------------------------------------------------------
     * Function:    sds_transattrs
     *
     * Purpose:         translate attributes of HDF4 SDS object into
     hdf5 dataset attributes
     *
     * Return:  FAIL if failed, SUCCEED if successful.
     *
     * In :
     ssds_id:                SDS identifier
     sh5_dset:           hdf5 dataset
     snum_sdsattrs:  number of sds attributes
     check_gloflag:
                     a flag to check whether the attribute is
                     a file attribute or an SDS attribute  or a dimensional
                     scale attribute.
     attr_flag:
                     Attribute flag to check if adding GLO predix before the attribute name.

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

int sds_transattrs(hid_t h4toh5id,
                 int32 ssds_id,
                 hid_t sh5_dset,
                 int     snum_sdsattrs,
                 int     check_gloflag,
                 int     attr_flag)
{
    char            ssdsattr_name[2*H4H5_MAX_NC_NAME]; /* SDS attribute name*/
    char            sdsglo[H4H5_MAX_NC_NAME]; /* SD global attribute name */
    char*           sdstempattr_name; /* a temporary variable to store SDS attribute name */

    int32           count_ssdsadata; /* number of elements of SDS attributes.*/
    uint32      temp_countadata; /* temporary variable to describe the number of
                                                                SDS attributes */
    int32           ssds_atype; /* SDS attribute datatype */

    size_t      sh4_amemsize;/* size of attribute data type in memory. */
    size_t      sh4_asize;  /* size of attribute data type in disk. */

    hid_t           sh5a_sid; /* HDF5 attribute space id */
    hid_t           sh5a_id; /* HDF5 attribute id */
    hid_t           sh5_atype; /* HDF5 attribute data type in disk */
    hid_t           sh5_amemtype; /* HDF5 attribute data type in memory */
    hid_t           sh5str_type; /* HDF5 attribute data type in disk when the data type                                                      is string. */
    hid_t           sh5str_memtype; /* HDF5 attribute data type in memory when the data                                                             type is string. */

    hsize_t     sh5dims[1]; /* HDF5 attribute dimension */
    void*           ssds_adata; /* attribute data*/
    herr_t      sret;               /* the temporary variable to check the "return" status  of
                                                     HDF5 APIs */
    int             i;               /* temporary variable. */
    h4toh5id_t *dt; /*pointer to h4toh5 id */


    dt = H4TOH5I_object(h4toh5id);

    for (i = 0;i < snum_sdsattrs; i++) {
        ssds_adata = NULL;

        if (SDattrinfo(ssds_id,i,ssdsattr_name,&ssds_atype,
             &count_ssdsadata)==FAIL){
            H4toH5error_set(dt,2,"cannot start SD attribute information",
                    __FILE__,__LINE__);
            return FAIL;
        }

        /* convert HDF4 attribute data type to HDF5 attribute data type. */
        if(h4type_to_h5type(h4toh5id,ssds_atype,&sh5_amemtype,&sh4_amemsize,
            &sh4_asize,&sh5_atype)== FAIL) {
            H4toH5error_set(dt,2,"cannot convert SDS attribute data type from H4 to H5",
                    __FILE__,__LINE__);
            return FAIL;
        }

        if(count_ssdsadata != 0) {
            /* allocating memory for SDS attribute data. */
            ssds_adata = malloc(sh4_amemsize * count_ssdsadata);
            if(ssds_adata == NULL) {
                H4toH5error_set(dt,1,"cannot allocate memory for SDS attribute data",
                                    __FILE__,__LINE__);
                return FAIL;
            }

            if(SDreadattr(ssds_id,i,(VOIDP)ssds_adata)== FAIL) {
                H4toH5error_set(dt,2,"cannot read SDS attribute",
                                    __FILE__,__LINE__);
                free(ssds_adata);
                return FAIL;
            }
        }
        /* if an attribute doesn't have a name, a default name is set. */
        if(ssdsattr_name[0] == '\0') {
            sdstempattr_name = trans_obj_name(h4toh5id,DFTAG_NDG,i);
            strncpy(ssdsattr_name,sdstempattr_name,sizeof(ssdsattr_name));
            free(sdstempattr_name);
        }

        /* if the SDS attribute is a file attribute. */
        if(check_gloflag == 1 && (attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_OSPEC_NO_PREDEF_ATTRS)){

            strcpy(sdsglo,GLOSDS);
            strcat(ssdsattr_name,"_");
            strcat(ssdsattr_name,sdsglo);

        }

        /* now do attribute-transferring.
             1. deal with string data type
             2. set attribute space.
             3. get attribute name, write attribute data*/

        if (sh5_atype == H5T_STRING) {

            sh5a_sid = H5Screate(H5S_SCALAR);
            if (sh5a_sid < 0) {
                H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                        __FILE__,__LINE__);
                if (ssds_adata) 
                    free(ssds_adata);
                return FAIL;
            }

            if(count_ssdsadata != 0){
                temp_countadata = count_ssdsadata*sh4_asize;
                H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
                if ((sh5str_type = mkstr(h4toh5id,(size_t)temp_countadata,
                             H5T_STR_NULLTERM))<0) {
                    H4toH5error_set(dt,3,"cannot make HDF5 string type",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }

                if ((sh5str_memtype = mkstr(h4toh5id,count_ssdsadata*sh4_amemsize,
                                    H5T_STR_NULLTERM))<0) {
                    H4toH5error_set(dt,3,"cannot make hdf5 memory string type",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }

                sh5a_id = H5Acreate_safe(h4toh5id,sh5_dset,ssdsattr_name,sh5str_type,
                                sh5a_sid,H5P_DEFAULT);
                if (sh5a_id <0) {
                    /* H5Acreate() can fail just because this attribute is too long. This could be rejected,
                     * the following code tries to split it. */
                    if (transattrs_split(h4toh5id, sh5_dset, ssdsattr_name, sh5a_sid, ssds_adata, count_ssdsadata) < 0) {
                        H4toH5error_set(dt,3,"cannot create hdf5 attribute id",
                                __FILE__,__LINE__);
                        H5Sclose(sh5a_sid);
                        if (ssds_adata) 
                            free(ssds_adata);
                        return FAIL;
                    }
                }
                else if (ssds_adata) {
                    sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)ssds_adata);
                    if (sret <0) {
                        H4toH5error_set(dt,3,"cannot write hdf5 attribute",
                                __FILE__,__LINE__);
                        H5Sclose(sh5a_sid);
                        H5Aclose(sh5a_id);
                        if (ssds_adata) 
                            free(ssds_adata);
                        return FAIL;
                    }
                }
            }
            else {/* treat the number of data as 1 for empty attribute*/

                if ((sh5str_type = mkstr(h4toh5id,(size_t)1*sh4_asize,
                             H5T_STR_NULLTERM))<0) {
                    H4toH5error_set(dt,3,"cannot make HDF5 string type",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }

                if ((sh5str_memtype = mkstr(h4toh5id,1*sh4_amemsize,
                                    H5T_STR_NULLTERM))<0) {
                    H4toH5error_set(dt,3,"cannot make hdf5 memory string type",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }

                sh5a_id = H5Acreate_safe(h4toh5id,sh5_dset,ssdsattr_name,sh5str_type,
                                sh5a_sid,H5P_DEFAULT);
                if (sh5a_id <0) {
                    H4toH5error_set(dt,3,"cannot create hdf5 attribute id",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }

                /*   sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)ssds_adata);
                         if (sret <0) {
                         H4toH5error_set(dt,3,"cannot write hdf5 attribute",
                         __FILE__,__LINE__);
                         H5Sclose(sh5a_sid);
                         H5Aclose(sh5a_id);
                         if (ssds_adata) free(ssds_adata);
                         return FAIL;
                         }*/
            }
            H5Sclose(sh5a_sid);
            /* An HDF4 attribute could be converted into an HDF5 attribute. */
            if (sh5a_id >= 0) 
                H5Aclose(sh5a_id);
        }

        else {
            /* netCDF4 cannot read _FillValue that was written by EOS2 API because it makes count_ssdsadata == 1.
             * (There are many other cases similar to this.)
             * Force to use Simple type even if count_ssdsadata == 1
             */
            if(!H4toH5config_use_netcdf4_hack() && count_ssdsadata == 1) {

                sh5a_sid = H5Screate(H5S_SCALAR);
                if (sh5a_sid < 0) {
                    H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                            __FILE__,__LINE__);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }
            }
            else {
                if(count_ssdsadata == 0) {
                    H4toH5error_set(dt,3,"the attribute data must not be none",
                            __FILE__,__LINE__);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }
                sh5dims[0] = count_ssdsadata;
                sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);

                if (sh5a_sid < 0)  {
                    H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                            __FILE__,__LINE__);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }
            }

            sh5a_id = H5Acreate_safe(h4toh5id,sh5_dset,ssdsattr_name,sh5_atype,
                sh5a_sid,H5P_DEFAULT);

            if(sh5a_id <0) {
                H4toH5error_set(dt,3,"cannot create HDF5 attribute id",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                if (ssds_adata) 
                    free(ssds_adata);
                return FAIL;
            }

            if (ssds_adata) {
                sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)ssds_adata);
                if(sret <0) {
                    H4toH5error_set(dt,3,"cannot write HDF5 attribute",
                            __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    H5Aclose(sh5a_id);
                    if (ssds_adata) 
                        free(ssds_adata);
                    return FAIL;
                }
            }
            sret = H5Sclose(sh5a_sid);
            if(sret < 0) {
                H4toH5error_set(dt,3,"cannot close HDF5 space",
                        __FILE__,__LINE__);
                H5Aclose(sh5a_id);
                if (ssds_adata) free(ssds_adata);
                return FAIL;
            }
            sret = H5Aclose(sh5a_id);
            if(sret < 0) {
                H4toH5error_set(dt,3,"cannot close HDF5 attribute interface ",
                        __FILE__,__LINE__);
                if (ssds_adata) 
                    free(ssds_adata);
                return FAIL;
            }
        }
        if(count_ssdsadata !=0) {
            if (ssds_adata) 
                free(ssds_adata);
        }
    }
    return SUCCEED;
}


/*-------------------------------------------------------------------
 * Function:    sds_transattrscdf
 *
 * Purpose:         translate attributes of HDF4 SDS object into
 hdf5 dataset attributes
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 ssds_id:                SDS identifier
 sh5_dset:           hdf5 dataset
 snum_sdsattrs:  number of sds attributes
 check_gloflag:
 a flag to check whether the attribute is
 a file attribute or an SDS attribute  or a dimensional
 scale attribute.

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

int sds_transattrscdf(hid_t h4toh5id,
                    int32 ssds_id,
                    hid_t sh5_dset,
                    int     snum_sdsattrs,
                    int     check_gloflag)
{
    char            ssdsattr_name[2*H4H5_MAX_NC_NAME]; /* SDS attribute name*/
    char            sdsglo[H4H5_MAX_NC_NAME]; /* SD global attribute name */
    char*           sdstempattr_name; /* a temporary variable to store SDS attribute name */

    int32           count_ssdsadata; /* number of elements of SDS attributes.*/
    uint32      temp_countadata; /* temporary variable to describe the number of
                                                                SDS attributes */
    int32           ssds_atype; /* SDS attribute datatype */

    size_t      sh4_amemsize;/* size of attribute data type in memory. */
    size_t      sh4_asize;  /* size of attribute data type in disk. */

    hid_t           sh5a_sid; /* HDF5 attribute space id */
    hid_t           sh5a_id; /* HDF5 attribute id */
    hid_t           sh5_atype; /* HDF5 attribute data type in disk */
    hid_t           sh5_amemtype; /* HDF5 attribute data type in memory */
    hid_t           sh5str_type; /* HDF5 attribute data type in disk when the data type is string. */
    hid_t           sh5str_memtype; /* HDF5 attribute data type in memory when the data type is string. */

    hsize_t     sh5dims[1]; /* HDF5 attribute dimension */
    void*           ssds_adata; /* attribute data*/
    herr_t      sret;               /* the temporary variable to check the "return" status  of
                                                     HDF5 APIs */
    int             i;               /* temporary variable. */
    h4toh5id_t *dt; /*pointer to h4toh5 id */


    dt = H4TOH5I_object(h4toh5id);

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

        if (SDattrinfo(ssds_id,i,ssdsattr_name,&ssds_atype,
             &count_ssdsadata)==FAIL){
            H4toH5error_set(dt,2,"cannot start SD attribute information",
                    __FILE__,__LINE__);
            return FAIL;
        }

        /* convert HDF4 attribute data type to HDF5 attribute data type. */
        if(h4type_to_h5type(h4toh5id,ssds_atype,&sh5_amemtype,&sh4_amemsize,
            &sh4_asize,&sh5_atype)== FAIL) {
            H4toH5error_set(dt,2,"cannot convert SDS attribute data type from H4 to H5",
                    __FILE__,__LINE__);
            return FAIL;
        }

        /* allocating memory for SDS attribute data. */
        ssds_adata = malloc(sh4_amemsize * count_ssdsadata);
        if(ssds_adata == NULL) {
            H4toH5error_set(dt,1,"cannot allocate memory for SDS attribute data",
                    __FILE__,__LINE__);
            return FAIL;
        }

        if(SDreadattr(ssds_id,i,(VOIDP)ssds_adata)== FAIL) {
            H4toH5error_set(dt,2,"cannot read SDS attribute",
                    __FILE__,__LINE__);
            free(ssds_adata);
            return FAIL;
        }

        /* if an attribute doesn't have a name, a default name is set. */
        if(ssdsattr_name[0] == '\0') {
            sdstempattr_name = trans_obj_name(h4toh5id,DFTAG_NDG,i);
            strncpy(ssdsattr_name,sdstempattr_name,sizeof(ssdsattr_name));
            free(sdstempattr_name);
        }

        /* if the SDS attribute is a file attribute. */
        if(check_gloflag == 1){
            strcpy(sdsglo,GLOSDS);
            strcat(ssdsattr_name,"_");
            strcat(ssdsattr_name,sdsglo);
        }

        /* now do attribute-transferring.
             1. deal with string data type
             2. set attribute space.
             3. get attribute name, write attribute data*/

        if (sh5_atype == H5T_STRING) {

            sh5a_sid = H5Screate(H5S_SCALAR);
            if (sh5a_sid < 0) {
                H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                        __FILE__,__LINE__);
                free(ssds_adata);
                return FAIL;
            }

            temp_countadata = count_ssdsadata*sh4_asize;
            H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
            if ((sh5str_type = mkstr(h4toh5id,(size_t)temp_countadata,
                         H5T_STR_NULLTERM))<0) {
               H4toH5error_set(dt,3,"cannot make HDF5 string type",
                       __FILE__,__LINE__);
               H5Sclose(sh5a_sid);
               free(ssds_adata);
               return FAIL;
            }

            if ((sh5str_memtype = mkstr(h4toh5id,count_ssdsadata*sh4_amemsize,
                    H5T_STR_NULLTERM))<0) {
                H4toH5error_set(dt,3,"cannot make hdf5 memory string type",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                free(ssds_adata);
                return FAIL;
            }

            sh5a_id = H5Acreate_safe(h4toh5id,sh5_dset,ssdsattr_name,sh5str_type,
                sh5a_sid,H5P_DEFAULT);
            if (sh5a_id <0) {
                H4toH5error_set(dt,3,"cannot create hdf5 attribute id",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                free(ssds_adata);
                return FAIL;
            }

            sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)ssds_adata);
            if (sret <0) {
                H4toH5error_set(dt,3,"cannot write hdf5 attribute",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Aclose(sh5a_id);
                free(ssds_adata);
                return FAIL;
            }

            sret = H5Sclose(sh5a_sid);
            if (sret <0) {
                H4toH5error_set(dt,3,"cannot close the data space",
                        __FILE__,__LINE__);
                H5Aclose(sh5a_id);
                free(ssds_adata);
                return FAIL;
            }
  
            sret = H5Aclose(sh5a_id);
            if (sret <0) {
                H4toH5error_set(dt,3,"cannot close the hdf5 attribute",
                        __FILE__,__LINE__);
                free(ssds_adata);
                return FAIL;
            }

        }

        else {

            if(count_ssdsadata == 1) {

                sh5a_sid = H5Screate(H5S_SCALAR);
                if (sh5a_sid < 0) {
                    H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                            __FILE__,__LINE__);
                    free(ssds_adata);
                    return FAIL;
                }
            }
            else {
                sh5dims[0] = count_ssdsadata;
                sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);

                if (sh5a_sid < 0)  {
                    H4toH5error_set(dt,3,"cannot create HDF5 attribute space",
                            __FILE__,__LINE__);
                    free(ssds_adata);
                    return FAIL;
                }
            }
            sh5a_id = H5Acreate_safe(h4toh5id,sh5_dset,ssdsattr_name,sh5_atype,
                sh5a_sid,H5P_DEFAULT);

            if(sh5a_id <0) {
                H4toH5error_set(dt,3,"cannot create HDF5 attribute id",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                free(ssds_adata);
                return FAIL;
            }

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

            if(sret <0) {
                H4toH5error_set(dt,3,"cannot write HDF5 attribute",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Aclose(sh5a_id);
                free(ssds_adata);
                return FAIL;
            }
            sret = H5Sclose(sh5a_sid);
            if(sret < 0) {
                H4toH5error_set(dt,3,"cannot close HDF5 space",
                        __FILE__,__LINE__);
                H5Aclose(sh5a_id);
                free(ssds_adata);
                return FAIL;
            }
            sret = H5Aclose(sh5a_id);
            if(sret < 0) {
                H4toH5error_set(dt,3,"cannot close HDF5 attribute interface ",
                        __FILE__,__LINE__);
                free(ssds_adata);
                return FAIL;
            }
        }
        free(ssds_adata);
    }
    return SUCCEED;
}

/****************H4toH5one_dimscale*******************

* Purpose:       translate a dimensional scale dataset to
                                an HDF5 dataset
        *
        * Return:   FAIL if failed, SUCCEED if successful.
        *
        * In :
                h4toh5_id:                  h4toh5 id handler
                sds_id:                         SDS identifier
                sds_rankindex:          the index number of SDS dimension
                sh5_dimgroupname:       HDF5 group name that the dimensional scale
                                        dataset is put under
        sh5_dimdatasetname: HDF5 dimensional scale dataset
                            name list that the user defines
        h5_groupname:       HDF5 group name that SDS
                            (*not SDS dimensional scale*)is put under
        h5_datasetname:         HDF5 dataset name of the SDS
                           (*not SDS dimensional scale*)object.
        ref_flag:          a flag to show whether the object
                           reference and attribute names of the SDS
                           dimensional dataset should be included.
        attr_flag:         a flag to show whether attributes of
                           HDF5 dimensional scale datasets should
                           be converted

     Out:
     Modification:

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

int H4toH5one_dimscale(hid_t h4toh5_id,
                     int32 sds_id,
                     char* h5groupname,
                     char* h5datasetname,
                     char* h5_dimgroupname,
                     char* h5_dimdatasetname,
                     int     attr_flag,
                     int     ref_flag,
                     int     sds_rankindex)
{

    /*varibles for dimensional scale dataset. */
    int32       sdsdim_id; /* SDS dimensional scale id */
    int32       sdsdim_type = 0; /* SDS dimensional scale data type */
    int32       sds_dimscasize[1]; /* the size of SDS dimensional scale */
    int         check_sdsdim; /* a temporary variable to check the existence of
                 SDS dimensional scale */
    int         count_h5objref; /* the counter to check the number of the object
                     references from the converted SDS to SDS dim.
                     scale. */
    int         count_h5attrname; /* the counter to check the number of
                         attributes that stores the attribute name
                         from HDF4 to HDF5. */
    int         check_gloattr; /* a temporary variable to check the global
                    attribute */
    int32       num_sdsdimattrs; /* number of SDS dimensional scale attributes */
    void*       dim_scadata; /* dim. scale data buffer */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    char        refstr[MAXREF_LENGTH]; /* string format of the reference number */
    char*       cor_sdsdimname; /* the "corrected" SDS dimensional scale name */

    char*       h5csds_name; /* the absolute path of HDF5 dataset converted
                from SDS*/
    char*       h5crepsds_name; /* the temporary variable to store absolute path
                     of HDF5 dataset converted from SDS */
    size_t  h4dim_memsize; /*dimensional scale data type size of in memory*/
    size_t  h4dim_size;      /* dimensional scale data type size in disk*/

    /* variables for SDS */

    int32       sds_ref; /* SDS reference number */
    int32       istat; /* temporary variable to check the "return" status  of HDF4 APIs */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* SDS rank */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS];/* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */
    char        sdsname[H4H5_MAX_NC_NAME];/* SDS name */
    char*       cor_sdsname;

    /* define varibles for hdf5. */
    hid_t       sh5_dimgroup; /* the parent HDF5 group of the object converted from
                 the dimensional scale */
    hid_t       h5dim_dset;  /* HDF5 dataset converted from the dimensional scale */
    hid_t       h5dim_sid;   /* HDF5 data space id for "dimensional scale " */
    hid_t       h5dim_tid;  /* HDF5 data type for "dimensional scale " */
    hid_t       h5dim_memtype; /* HDF5 data type for "dimensional scale" in memory */
    hid_t       create_plist; /* property list id for data creation */
    hid_t       h5_group; /* the parent HDF5 group of the "SDS" object */
    hid_t       sh5dset; /* the HDF5 dataset */

    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */

    char*       h5sdsdim_name; /* HDF5 "SDS dimensional scale name " */
    char*       ori_h5sdsdimname; /* If the current dimensional scale has already
                         been converted, the original dimensional scale
                         dataset name */
    char        h5sdsdim_allname[H4H5_MAX_VAR_DIMS * H4H5_MAX_DIM_NAME]; /* The SDS dimensional
                                    scale dataset name list */

    char        h5dimpath_name[H4H5_MAX_DIM_NAME];/* The parent HDF5 group name of the
                        converted "SDS dimensional scale */
    herr_t  ret; /* the temporary variable to check the "return" status  of HDF5 APIs */
#if 0
    int*        check_lookupptr; /* the pointer to check "hashing table" that
                        handles the collisions of SDS object names*/
    int         temp; /* a temporary variable */
#endif
    int         sdsdimempty[1]; /* this array is used to handle the inconsistent
                     situation when the dim. scale name is given but
                                                         the dim. scale data is not. */

    char*       cor_h5dsetname;
    h4toh5id_t* temph4toh5id;/* a pointer to h4toh5 id*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);

    /*zero out memory for h5sdsdim_allname and h5dimpath_name */
    h4toh5_ZeroMemory(h5sdsdim_allname,(H4H5_MAX_VAR_DIMS*H4H5_MAX_DIM_NAME)*sizeof(char));
    h4toh5_ZeroMemory(h5dimpath_name,H4H5_MAX_DIM_NAME*sizeof(char));

#if 0
    /* initialization of some temporary variables */
    temp = 0;
    check_lookupptr =&temp;
#endif

    sdsdimempty[0] = 0;

    /* obtain the object reference of SDS */
    sds_ref = SDidtoref(sds_id);
    if(sds_ref==FAIL) {
        H4toH5error_set(temph4toh5id,2,"fail to obtain SDS reference number",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* using SDS "getinfo" API to get all the information of this SDS object.*/
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,"fail to get SDS information",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* initialize the dimensional number of sds dimensions,
         h5dim_dims is used for grabbing hdf5 dimensional name list
         and object reference list. */

    count_h5objref   = 0;
    count_h5attrname = 0;

    if(sds_rankindex < 0 || sds_rankindex >= sds_rank) {
        H4toH5error_set(temph4toh5id,2,"SDS dimensional rank is not set properly",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* get this SDS dimensional scale id. */
    sdsdim_id        = SDgetdimid(sds_id,sds_rankindex);
    if(sdsdim_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension",
                __FILE__,__LINE__);
        return FAIL;
    }

    /*get the information of this dimensional scale*/
    istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                &sdsdim_type,&num_sdsdimattrs);
    if (istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension information",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* for unlimited SDS dimension, grab the current dimensional size. */
    if(sds_rankindex == 0)
        if(sds_dimscasize[0] == 0) sds_dimscasize[0] = sds_dimsizes[0];

    /* when SDS dimensional scale type is 0, there are no SDS dimensional scale
         data. However, SDS dimensional scale name may still be a valid name when
         dimensional scale name is not fakeDim.
    */
    if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname)==0) {
        if(strncmp(sdsdim_name,fakeDim,strlen(fakeDim))==0){
            return SUCCEED;
        }
    }

/*#ifdef USE_DIMSCALE_APIS
        printf("coming to dimscale APIs\n");



#endif
*/


    /* getting HDF5 dim group;
         when the dimensional scale group name is not set NULL; */
    if(h5_dimgroupname != NULL) {
        strcpy(h5dimpath_name,h5_dimgroupname);
        sh5_dimgroup = get_h5groupid(h5_dimgroupname,h4toh5_id,attr_flag);
    }
    else { /* if the user doesn't define HDF5 dimensional group name */
        strcpy(h5dimpath_name,HDF4_DIMG);
        sh5_dimgroup = get_h5groupid(h5dimpath_name,h4toh5_id,attr_flag);
    }

    if(sh5_dimgroup < 0) {
        H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional group id",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* checking whether SDS dimensional scale name contains ORI_SLASH,
         changing the ORI_SLASH("/") into CHA_SLASH("_").*/

    if(h5_dimdatasetname == NULL) {
        /* no dimensional scale dataset is specified.*/
        cor_sdsdimname = correct_name(h4toh5_id,sdsdim_name);
        if(cor_sdsdimname == NULL) {
            H4toH5error_set(temph4toh5id,4,
                    "cannot obtain corrected dimensional scale name",__FILE__,__LINE__);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        h5sdsdim_name = make_objname_yes(h4toh5_id,cor_sdsdimname,h5dimpath_name);
        if(h5sdsdim_name == NULL) {
            H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional name",
                    __FILE__,__LINE__);
            free(cor_sdsdimname);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        free(cor_sdsdimname);
    }

    else {
        h5sdsdim_name = malloc(strlen(h5_dimdatasetname)+strlen(h5dimpath_name)+2*sizeof(char));
        strcpy(h5sdsdim_name,h5dimpath_name);
        strcat(h5sdsdim_name,"/");
        strcat(h5sdsdim_name,h5_dimdatasetname);
    }

    /* check whether this SDS dimensional scale dataset is touched or not. */
    check_sdsdim = modlookup_updatename(h4toh5_id,sdsdim_name,h5sdsdim_name,DIM_HASHSIZE,temph4toh5id->moddim_hashtab);

    if(check_sdsdim == 1) {/*the name has been looked up. */

        /* 0. check the special case whether this sds dimensional name is shared,
             if yes, just increase the counter.*/

        if(lookup_updatename(h4toh5_id,h5sdsdim_name,OBJECT_HASHSIZE,temph4toh5id->name_hashtab)==1) {
            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname)==0)/* no real dimensional scale data, no object refer.*/
                count_h5attrname++;
            else {
                count_h5objref++;
                count_h5attrname++;
            }

        }
        /*
             1. create a hardlink to the one which is already there.
             2. copy the name to h5sdsdim_allname for dealing with object reference and attribute.
        */

        else {
            /* Obtain the original SDS dimensional scale name of this dim. scale. */

            ori_h5sdsdimname = get_modname2(h4toh5_id,sdsdim_name,DIM_HASHSIZE,temph4toh5id->moddim_hashtab);
            if(ori_h5sdsdimname == NULL) {
                H4toH5error_set(temph4toh5id,4,"cannot obtain the original dimension name ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(H5Glink(sh5_dimgroup,H5G_LINK_HARD,ori_h5sdsdimname,h5sdsdim_name) <0) {
                H4toH5error_set(temph4toh5id,3,"fail to create hardlink",
                       __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(ori_h5sdsdimname);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname)==0)
                count_h5attrname++;
            else {
                count_h5objref++;
                count_h5attrname++;
            }
            free(ori_h5sdsdimname);
        }
    }
    /* do the conversion
         1)here we should add some comments for fakedim0--name.
         It seems that  hdf4(netcdf) will use unique fake dimension name,
         fakedim + unique number, so check_sdsdim will never be 1 if
         the dimension name is fake name. Under this case, count_h5objref
         and count_h5attrname will not increase if this dimension doesnot
         have dimensional scale data. That assures the object reference
         of sds is correct.

         2) **** REMINDER*****
         For the case when the SDS dim. name exists but no data are
         written, count_attrname and count_ref may be different,
         update the seemingly corrected implementation of SDS dim.
         1/10/2002*****/

    else {

        if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname)==0) {
            count_h5attrname = count_h5attrname + 1;
            sdsdimempty[0]   = 1;
        }
        /* get h5 dimensional scale data type. */
        if(h4type_to_h5type(h4toh5_id,sdsdim_type,&h5dim_memtype,&h4dim_memsize,
            &h4dim_size,&h5dim_tid)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "fail to convert HDF4 datatype into HDF5 datatype ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        /* dimensional scale dataset cannot be H5T_STRING data type.
             So transferring back these type to int8 */

        if (h5dim_tid == H5T_STRING) {
            if(h5string_to_int(h4toh5_id,sdsdim_type,&h5dim_memtype,h4dim_memsize,
             &h5dim_tid)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "fail to convert HDF5 string into INT ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
        }
        /* get the dimensional scale data. */
        dim_scadata = malloc(h4dim_memsize*sds_dimscasize[0]);
        if(dim_scadata == NULL) {
            H4toH5error_set(temph4toh5id,2,"cannot allocate memory for dimensional data ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        istat               = SDgetdimscale(sdsdim_id,(VOIDP)dim_scadata);
        if (istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot get SDS dimensional scale data ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        /* set dimensional scale size properly. */
        h5dimscas[0] = sds_dimscasize[0];

        /* only set for the first dimension if SDS is unlimited dimension. */
        if(SDisrecord(sds_id) && sds_rankindex == 0)
            max_h5dimscas[0] = H5S_UNLIMITED;
        else
            max_h5dimscas[0] = h5dimscas[0];

        h5dim_sid        = H5Screate_simple(1,h5dimscas,max_h5dimscas);
        if(h5dim_sid <0) {
            H4toH5error_set(temph4toh5id,3,"cannot create HDF5 space ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        /* create property list, for chunked sds or unlimited dimension cases */
        create_plist = get_dimchunking_plistid(h4toh5_id,sds_id,sdsdim_id,sds_rankindex,sds_dimsizes[0]);
        if(create_plist == -1) {
            H4toH5error_set(temph4toh5id,5,"cannot get property list" ,
                    __FILE__,__LINE__);
            H5Sclose(h5dim_sid);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        /* create h5 dataset under h5 dimensional group*/

        h5dim_dset   = H5DCREATE(sh5_dimgroup,h5sdsdim_name,h5dim_tid,
                     h5dim_sid,create_plist);
        if(h5dim_dset <0) {
            H4toH5error_set(temph4toh5id,3,"cannot create HDF5 dataset",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Pclose(create_plist);
            H5Sclose(h5dim_sid);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
/*
#ifdef USE_DIMSCALE_APIS
        H5DSset_scale(h5dim_dset,h5sdsdim_name);

#endif
*/


        if (H5Dwrite(h5dim_dset,h5dim_memtype,h5dim_sid,h5dim_sid,
         H5P_DEFAULT,(void *)dim_scadata)<0) {
            H4toH5error_set(temph4toh5id,3,"cannot write HDF5 dataset",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Sclose(h5dim_sid);
            H5Pclose(create_plist);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        if(is_valid_attr_flag(attr_flag)==0) {
            H4toH5error_set(temph4toh5id,5,"attribute flag is set wrong ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Sclose(h5dim_sid);
            H5Pclose(create_plist);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        if(ref_flag <0 || ref_flag > 1) {
            H4toH5error_set(temph4toh5id,5,"reference flag is set wrong ",
                    __FILE__,__LINE__);
            free(h5sdsdim_name);
            free(dim_scadata);
            H5Sclose(h5dim_sid);
            H5Pclose(create_plist);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
            check_gloattr = 0;
            if(sds_transattrs(h4toh5_id,sdsdim_id,h5dim_dset,num_sdsdimattrs,check_gloattr,attr_flag)
                == FAIL){
               H4toH5error_set(temph4toh5id,5,"fail to convert SDS dimension attributes ",
                       __FILE__,__LINE__);
               free(h5sdsdim_name);
               free(dim_scadata);
               H5Sclose(h5dim_sid);
               H5Dclose(h5dim_dset);
               H5Pclose(create_plist);
               H5Gclose(sh5_dimgroup);
               return FAIL;
            }
        }

        count_h5objref = count_h5objref + 1;
        count_h5attrname =count_h5attrname  + 1;

        if(ref_flag != 0) {
            if(h5datasetname == NULL) {
                /* generating two names.
                     1. make up name based on HDF4_SDS,h5groupname,sds_ref.
                     call this name h5repsds_name
                     2. using lookup_name to check whether this name is stored already.
                     3. If yes, use this name as the h5datasetname.
                     4. no, obtain name based on groupname + sds name.
                */

                if(conv_int_str(h4toh5_id,(uint16)sds_ref,refstr)== FAIL) {
                    H4toH5error_set(temph4toh5id,5,
                            "fail to convert reference number into HDF5 string ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(dim_scadata);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Pclose(create_plist);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }

                h5crepsds_name = make_objname_no(h4toh5_id,refstr,h5groupname,HDF4_SDS);
                if(lookup_name(h4toh5_id,h5crepsds_name,SDS_HASHSIZE,temph4toh5id->name_hashtab)==1){
                    h5csds_name = malloc(strlen(h5crepsds_name)+1);
                    if(h5csds_name == NULL) {
                        H4toH5error_set(temph4toh5id,1,
                                "unable to allocate memory for hdf5 sds name ",
                                __FILE__,__LINE__);
                        free(h5sdsdim_name);
                        free(dim_scadata);
                        H5Sclose(h5dim_sid);
                        H5Dclose(h5dim_dset);
                        H5Pclose(create_plist);
                        H5Gclose(sh5_dimgroup);
                        return FAIL;
                    }
                    strncpy(h5csds_name,h5crepsds_name,strlen(h5crepsds_name));
                }

                else {
                    cor_sdsname = correct_name(h4toh5_id,sdsname);
                    if(cor_sdsname == NULL) {
                        H4toH5error_set(temph4toh5id,5,"cannot obtain corrected sds name",
                                __FILE__,__LINE__);
                        free(h5sdsdim_name);
                        free(dim_scadata);
                        H5Sclose(h5dim_sid);
                        H5Dclose(h5dim_dset);
                        H5Pclose(create_plist);
                        H5Gclose(sh5_dimgroup);
                        return FAIL;
                    }
                    h5csds_name = make_objname_yes(h4toh5_id,h5groupname,cor_sdsname);
                    free(cor_sdsname);
                    if(h5csds_name == NULL) {
                        H4toH5error_set(temph4toh5id,4,
                                "cannot obtain hdf5 sds name ",
                                __FILE__,__LINE__);
                        free(h5sdsdim_name);
                        free(dim_scadata);
                        H5Sclose(h5dim_sid);
                        H5Dclose(h5dim_dset);
                        H5Pclose(create_plist);
                        H5Gclose(sh5_dimgroup);
                        return FAIL;
                    }
                }
                free(h5crepsds_name);
            }
            else {
                cor_h5dsetname = correct_name(h4toh5_id,h5datasetname);
                if(cor_h5dsetname == NULL) {
                    H4toH5error_set(temph4toh5id,5,"cannot obtain corrected HDF5 dataset name",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(dim_scadata);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Pclose(create_plist);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
                h5csds_name = make_objname_yes(h4toh5_id,cor_h5dsetname,h5groupname);
                if(h5csds_name == NULL) {
                    H4toH5error_set(temph4toh5id,4,
                            "cannot obtain hdf5 sds name ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(cor_h5dsetname);
                    free(dim_scadata);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Pclose(create_plist);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
                free(cor_h5dsetname);
                if(lookup_name(h4toh5_id,h5csds_name,SDS_HASHSIZE,
                                 temph4toh5id->name_hashtab)==0){
                    H4toH5error_set(temph4toh5id,4,
                            "this object name has not been set, results unexpected ",
                            __FILE__,__LINE__);
#if 0
                    free(h5csds_name);
                    free(dim_scadata);
                    free(h5sdsdim_name);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Pclose(create_plist);
                    H5Gclose(sh5_dimgroup);
#endif

                }
            }


            h5_group        =  get_h5groupid(h5groupname,h4toh5_id,attr_flag);

            if(h5_group < 0) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain hdf5 group id ",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            sh5dset = H5DOPEN(h5_group,h5csds_name);

            if (sh5dset < 0) {
                H4toH5error_set(temph4toh5id,3,
                        "cannot open hdf5 dataset ",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Gclose(h5_group);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* store object references and HDF4 dim. names to
                 HDF5 attributes. */
            if(store_objref(h4toh5_id,count_h5objref,h5sdsdim_allname,
                    sh5_dimgroup,sh5dset,sdsdimempty)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "cannot store object reference",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Dclose(sh5dset);
                H5Gclose(h5_group);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            if(store_attrname(h4toh5_id,count_h5attrname,h5sdsdim_allname,
            sh5dset)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "cannot store attribute name",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Dclose(sh5dset);
                H5Gclose(h5_group);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            if (attach_allscales(h4toh5_id,sh5dset,count_h5objref,h5sdsdim_allname,sh5_dimgroup,h5csds_name,h5_group,sdsdimempty) == FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "cannot attach dim scale",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Dclose(sh5dset);
                H5Gclose(h5_group);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            free(h5csds_name);
            ret = H5Dclose(sh5dset);
            if(ret < 0) {
                 H4toH5error_set(temph4toh5id,3,
                         "cannot close HDF5 dataset",
                         __FILE__,__LINE__);
                 free(dim_scadata);
                 free(h5sdsdim_name);
                 H5Sclose(h5dim_sid);
                 H5Dclose(h5dim_dset);
                 H5Pclose(create_plist);
                 H5Gclose(h5_group);
                 H5Gclose(sh5_dimgroup);
                 return FAIL;
            }
            ret = H5Gclose(h5_group);
            if(ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                        "cannot close HDF5 group",
                        __FILE__,__LINE__);
                free(dim_scadata);
                free(h5sdsdim_name);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Pclose(create_plist);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
        }

        free(dim_scadata);
        ret = H5Sclose(h5dim_sid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 data space",
                    __FILE__,__LINE__);

            free(h5sdsdim_name);
            H5Dclose(h5dim_dset);
            H5Pclose(create_plist);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        ret = H5Dclose(h5dim_dset);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 data set",
                    __FILE__,__LINE__);

            free(h5sdsdim_name);
            H5Pclose(create_plist);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        ret = H5Pclose(create_plist);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 property list",
                    __FILE__,__LINE__);

            free(h5sdsdim_name);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
    }

    free(h5sdsdim_name);
    if(H5Gclose(sh5_dimgroup) < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot close HDF5 group interface",
                __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;

}

/**
* @brief get HDF5 dataset id and reference corresponding to the given group name and SDS
* This function came from H4toH5all_dimscale().
* H4toH5all_dimscale() uses the similar routine to open the corresponding HDF5 dataset.
* HDF-EOS2 conversion routines H4toH5sds_eosswath_dimscale and H4toH5sds_eosgrid_dimscale
* need to open the corresponding HDF5 dataset for the same reason. To provide the HDF5
* dataset for HDF-EOS2 conversion routines, this code was extracted from H4toH5all_dimscale().
*
* @param h4toh5id conversion identifier
* @param h5groupname HDF5 group name
* @param h5dsetname HDF5 dataset name
* @param sdsname HDF4 SDS name
* @param sdsref HDF4 SDS reference number
* @param [out] did corresponding HDF5 dataset id
* @param [out] dsref corresponding HDF5 dataset reference
*
* @return SUCCEED if successful
*/
static int eos_get_converted_hdf5dataset(hid_t h4toh5id, const char *h5groupname, const char *h5dsetname, const char *sdsname, int32 sdsref, hid_t *did, hobj_ref_t *dsref)
{
    char *h5crepsds_name = NULL;
    char *h5csds_name = NULL;
    char *cor_sdsname = NULL;
    char *cor_h5dsetname = NULL;
    hid_t group = -1;
    hid_t dataset = -1;
    hobj_ref_t dsreference = 0;
    int succeeded = 0;

    do {
        char refstr[MAXREF_LENGTH];
        h4toh5id_t *dt = H4TOH5I_object(h4toh5id);

        if(h5dsetname == NULL) {
            if (conv_int_str(h4toh5id, (uint16)sdsref, refstr) == FAIL) { H4TOH5ERROR_SET1(3, "fail to convert reference number"); break; }
            if ((h5crepsds_name = make_objname_no(h4toh5id, refstr, h5groupname, HDF4_SDS)) == NULL) { H4TOH5ERROR_NOMEM1("objname"); break; }
            if (lookup_name(h4toh5id, h5crepsds_name, SDS_HASHSIZE, dt->name_hashtab) == 1) {
                if ((h5csds_name = malloc(strlen(h5crepsds_name) + 1)) == NULL) { H4TOH5ERROR_NOMEM1("objname"); break; }
                strcpy(h5csds_name, h5crepsds_name);
            }
            else {
                if ((cor_sdsname = correct_name(h4toh5id, sdsname)) == NULL) { H4TOH5ERROR_SET1(3, "fail to get HDF5 dataset name"); break; }
                if ((h5csds_name = make_objname_yes(h4toh5id, cor_sdsname, h5groupname)) == NULL) { H4TOH5ERROR_SET1(3, "cannot obtain HDF5 sds name"); break; }
            }
        }
        else {
            if ((cor_h5dsetname = correct_name(h4toh5id, h5dsetname)) == NULL) { H4TOH5ERROR_SET1(3, "fail to get HDF5 dataset name"); break; }
            if ((h5csds_name = make_objname_yes(h4toh5id, cor_h5dsetname, h5groupname)) == NULL) { H4TOH5ERROR_SET1(3, "cannot obtain sds name"); break; }
            if (lookup_name(h4toh5id, h5csds_name, SDS_HASHSIZE, dt->name_hashtab) == 0) { H4TOH5ERROR_SET1(3, "this object name has not been set, results unexpected"); break; }
        }

        if ((group = get_h5groupid(h5groupname, h4toh5id,0)) < 0) { H4TOH5ERROR_SET1(3, "cannot obtain HDF5 group id"); break; }
        if ((dataset = H5DOPEN(group, h5csds_name)) < 0) { H4TOH5ERROR_SET1(3, "cannot obtain HDF5 dataset"); break; }
        if (H5Rcreate(&dsreference, group, h5csds_name, H5R_OBJECT, -1) == -1) { H4TOH5ERROR_SET1(3, "cannot create h5 ref"); break; }

        succeeded = 1;
    } while (0);

    if (1) {
        if (h5crepsds_name) free(h5crepsds_name);
        if (h5csds_name) free(h5csds_name);
        if (cor_sdsname) free(cor_sdsname);
        if (cor_h5dsetname) free(cor_h5dsetname);
        if (group != -1) H5Gclose(group);
    }
    if (succeeded) {
        *did = dataset;
        *dsref = dsreference;
    }
    else {
        if (dataset != -1) H5Dclose(dataset);
    }
    return succeeded ? SUCCEED : FAIL;
}


/****************H4toH5all_dimscale*******************

* Purpose:  translate dimensional scale dataset into
                                hdf5 dataset
*
* Return:   FAIL if failed, SUCCEED if successful.
*
  * In :
      h4toh5_id:              id for h4toh5 id handle
      sds_id:                 SDS identifier
      h5_dimgroupname:        hdf5 group name that user wants
                              to put dimensional scale dataset in
      h5_groupname:           hdf5 group name that sds
                              (not sds dimensional scale) will be put.
      h5_datasetname:         hdf5 dataset name of the sds
                              (not sds dimensional scale)object.
      ref_flag:               a flag to show whether object reference
                              and attribute name should be included to
                              the hdf5 dataset converted from sds object
      attr_flag:              a flag to indicate whether all attributes
                              of sds dimensional scale datasets should
                              be converted
    Out:
    Modification:

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

int H4toH5all_dimscale(hid_t    h4toh5_id,
                     int32  sds_id,
                     char*  h5groupname,
                     char*  h5dsetname,
                     char*  h5_dimgroupname,
                     int        attr_flag,
                     int        ref_flag)
{

    /*varibles for dimensional scale dataset. */
    int32       sdsdim_id; /* SDS dimensional scale id */
    int32       sdsdim_type = 0; /* SDS dimensional scale data type */
    int32       sds_dimscasize[1]; /* the size of SDS dimensional scale */
    int         i; /* temporary variable for "for loop" */
#if 0
    int         temp; /* temporary variable */
#endif
    int         count_h5objref; /* the counter to check the number of the object
                     references from the converted SDS to SDS dim.
                     scale. */
    int         count_h5attrname; /* the counter to check the number of
                         attributes that stores the attribute name
                         from HDF4 to HDF5. */
    int         check_sdsdim;  /* a temporary variable to check the existence of
                    SDS dimensional scale */
    int         check_gloattr; /* a temporary variable to check the existence of
                    the global attribute */
#if 0
    int*        check_lookupptr; /* the pointer to check "hashing table" that
                        handles the collisions of SDS object names*/
#endif
    int         check_sharename; /* a temporary variable to check whether SDS
                        dim. scale is shared. */
    int32       num_sdsdimattrs; /* number of SDS dimensional scale attributes. */
    char        refstr[MAXREF_LENGTH];/* string format of the reference number */
    void*       dim_scadata; /* dim. scale data buffer */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    char*       cor_sdsdimname; /* the "corrected" SDS dimensional scale name */
    size_t  h4dim_memsize; /*dimensional scale size in memory*/
    size_t  h4dim_size; /* dimensional scale size in disk*/
    int         use_eosgriddimscale = 0; /* using HDF-EOS2 grid dim scale */
    int     use_eosswathdimscale = 0; /* using HDF-EOS2 swath dim scale */
    int     use_fakedimscale = 0; /* creating fake dimensions */

    /* variables for SDS */
    int32       istat; /* temporary variable to check the "return" status  of HDF4 APIs */
    int32       sds_ref; /* SDS reference number */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* SDS rank */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */
    int*        sdsdimempty; /* this array is used to handle the inconsistent
                situation when the dim. scale name is given but
                the dim. scale data is not. */
    char        sdsname[H4H5_MAX_NC_NAME]; /* SDS name */

    /* varibles for HDF5. */
    hid_t       sh5_dimgroup; /* the parent HDF5 group of the object converted from
                 the dimensional scale */
    hid_t       h5dim_dset; /* HDF5 dataset converted from the dimensional scale */
    hid_t       h5dim_sid;  /* HDF5 data space id for "dimensional scale " */
    hid_t       h5dim_tid; /* HDF5 data type for "dimensional scale " */
    hid_t       h5dim_memtype; /* HDF5 data type for "dimensional scale" in memory */
    hid_t       create_plist; /* property list id for data creation */

    hid_t       h5dset; /* the HDF5 dataset */
    hid_t       h5_group; /* the parent HDF5 group of the "SDS" object */
    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */

    char*       h5sdsdim_name; /* HDF5 "SDS dimensional scale name " */
    char*       ori_h5sdsdimname; /* If the current dimensional scale has already
                         been converted, the original dimensional scale
                         dataset name */

    char*       h5csds_name; /* the absolute path of HDF5 dataset converted
                from SDS*/
    char*       h5crepsds_name; /* the temporary variable to store absolute path
                     of HDF5 dataset converted from SDS */
    char        h5sdsdim_allname[H4H5_MAX_VAR_DIMS * H4H5_MAX_DIM_NAME];/* The SDS dimensional
                                 scale dataset name list */
    char        h5dimpath_name[H4H5_MAX_DIM_NAME]; /* The parent HDF5 group name of the
                         converted "SDS dimensional scale */
    herr_t  ret; /* the temporary variable to check the "return" status  of HDF5 APIs */

    char* cor_h5dsetname = NULL;
    char* cor_sdsname =NULL;

    h4toh5id_t* temph4toh5id; /* a pointer to h4toh5 id*/

#if 0
    temp = 0;
    check_lookupptr = &temp;
#endif

    temph4toh5id = H4TOH5I_object(h4toh5_id);
    /*zero out memory for h5sdsdim_allname and h5dimpath_name */

    h4toh5_ZeroMemory(h5sdsdim_allname,(H4H5_MAX_VAR_DIMS*H4H5_MAX_DIM_NAME)*sizeof(char));
    h4toh5_ZeroMemory(h5dimpath_name,H4H5_MAX_DIM_NAME*sizeof(char));

    sds_ref = SDidtoref(sds_id);
    if(sds_ref==FAIL) {
        H4toH5error_set(temph4toh5id,2,"fail to obtain SDS reference number",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* using SDS getinfo to get all the information of this SDS object.*/
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,"fail to get SDS information",
                __FILE__,__LINE__);
        return FAIL;
    }

#ifdef HAVE_LIBHDFEOS
    if (H4toH5config_use_eos2_conversion())  {
        int succeeded = 0;
        hid_t convertedid;
        hobj_ref_t convertedref;

        if (eos_get_converted_hdf5dataset(h4toh5_id, h5groupname, h5dsetname, sdsname, sds_ref, &convertedid, &convertedref) == 0) {
            do {
               /* Since SWATH data have very different model, modifying this function to handle SWATH dimscale
                * makes it too compliated.
                */
               if (H4toH5sds_eosswath_dimscale(h4toh5_id, h5groupname, sds_id, convertedid, convertedref, &use_eosswathdimscale) == FAIL) {
                   H4toH5error_set(temph4toh5id, 2, "fail to get HDF-EOS2 swath dim scale", __FILE__, __LINE__);
                   break;
               }
               if (use_eosswathdimscale) {
                   succeeded = 1;
                   break;
               }

               /* Since GRID data may have two-dimensional dimscale, handling general GRID dimscale no longer suits
                * this function which iterates each dimension
                */
               if (H4toH5sds_eosgrid_dimscale(h4toh5_id, h5groupname, sds_id, convertedid, convertedref, &use_eosgriddimscale) == FAIL) {
                   H4toH5error_set(temph4toh5id, 2, "fail to get HDF-EOS2 grid dim scale", __FILE__, __LINE__);
                   break;
               }
               if (use_eosgriddimscale) {
                   succeeded = 1;
                   break;
               }

               /* 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()) {
                   if (H4toH5sds_noneos_fake_dimscale(h4toh5_id, h5groupname, sds_id, convertedid, convertedref, &use_fakedimscale) == FAIL) {
                       H4toH5error_set(temph4toh5id, 2, "fail to create fake dimensions", __FILE__, __LINE__);
                       break;
                   }
                   if (use_fakedimscale) {
                       succeeded = 1;
                       break;
                   }
               }
            } while (0);

            H5Dclose(convertedid);
        }

        /* if -nc4strict is given, do not fall through the general routine */
        if (H4toH5config_use_netcdf4_strict())
            return succeeded ? SUCCEED : FAIL;
        else if (succeeded)
            return SUCCEED;
    }
#endif

    sdsdimempty = malloc(sds_rank *sizeof(int32));

    for (i=0;i<sds_rank;i++)
        sdsdimempty[i] = 0;

    /* the following section checks whether the dimensional scale
         is empty. */

    count_h5objref   = 0;
    count_h5attrname = 0;

    for (i = 0; i<sds_rank;i++) {
        sdsdim_id        = SDgetdimid(sds_id,i);
        if(sdsdim_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }

        istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                    &sdsdim_type,&num_sdsdimattrs);

        if (istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension information",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }

        /* Although SDS dimension data is empty, as long as it has
             a valid dimensional name, we should still keep the name in
             the dimensional name list. fakeDim is added by HDF4 library,
             we won't count those as valid dimensional name. */
        if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname)==0) {
            if(strncmp(sdsdim_name,fakeDim,strlen(fakeDim))==0){
                continue;
            }
        }
        /* count_h5objref and count_h5attrname are treated as
             flags to check if SDS dimensional scale data is empty,
             they will be reset in later code. */
        count_h5objref ++;
        count_h5attrname ++;
        if(count_h5objref !=0 || count_h5attrname !=0)
            break;
    }

    /* if the dimensional scale is not empty, we will assign a group. */
    if(count_h5objref !=0 || count_h5attrname !=0) {
        /* getting hdf5 dim group;
             when the inputting dimensional scale group name is not NULL; */
        if(h5_dimgroupname != NULL) {
            sh5_dimgroup = get_h5groupid(h5_dimgroupname,h4toh5_id,attr_flag);
            strcpy(h5dimpath_name,h5_dimgroupname);
        }
        else { /* if user doesn't define hdf5 dimensional group name */
            if (H4toH5config_use_netcdf4_hack()) {
               /* Since netCDF4 searches dimension scale only from ancestors,
                * we should put dimension scale dataset in the same group.
                */
               strcpy(h5dimpath_name,h5groupname);
            }
            else
               strcpy(h5dimpath_name,HDF4_DIMG);
            sh5_dimgroup = get_h5groupid(h5dimpath_name,h4toh5_id,attr_flag);
        }

        if(sh5_dimgroup < 0) {
            H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional group id",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }
    }

    else {
        free(sdsdimempty);
        return SUCCEED;
    }

    /* initialize the dimensional number of SDS dimensions and do the real job. */

    count_h5objref   = 0;
    count_h5attrname = 0;


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

        sdsdim_id        = SDgetdimid(sds_id,i);
        if(sdsdim_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                    &sdsdim_type,&num_sdsdimattrs);

        if (istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension information",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        /* for unlimited SDS dimension, grab the current dimensional size. */
        if(sds_dimscasize[0] == 0) sds_dimscasize[0] = sds_dimsizes[0];

        /* Here we have very messy cases for dimensional scale when
             sdsdim_type is 0(or not set).
             When sdsdim_type is 0, it means no SDS dimensional scale
             data for this dimensions. However, users may define SDS dimensional
             scale name. We want to keep this information.
        */

        if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname) == 0) {
            if(strncmp(sdsdim_name,fakeDim,strlen(fakeDim))==0){
                continue;
            }
        }

        /* checking whether sds dimensional scale name contains ORI_SLASH,
             changing them into CHA_SLASH.*/

        /* no dimensional scale dataset is specified.*/
        cor_sdsdimname = correct_name(h4toh5_id,sdsdim_name);
        if(cor_sdsdimname == NULL) {
            H4toH5error_set(temph4toh5id,4,"cannot obtain corrected dimensional scale name",__FILE__,__LINE__);
            H5Gclose(sh5_dimgroup);
            free(sdsdimempty);
            return FAIL;
        }

        /* generating HDF5 dimensional scale name. */
        h5sdsdim_name = make_objname_yes(h4toh5_id,cor_sdsdimname,h5dimpath_name);
        if(h5sdsdim_name == NULL) {
            H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional name",
                    __FILE__,__LINE__);
            free(cor_sdsdimname);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        /** hdf4 and netcdf assure that SDS dim. name is unique. So if the
    absolute path of the sds dim. name is found to be used,
    this dimension should share with the dimensional name that
    first used this name to represent dimension**/
        free(cor_sdsdimname);

        /* check whether this name has been used before. */
        check_sdsdim = modlookup_updatename(h4toh5_id,sdsdim_name,h5sdsdim_name,
                    DIM_HASHSIZE,
                    temph4toh5id->moddim_hashtab);

        check_sharename= lookup_updatename(h4toh5_id,h5sdsdim_name,OBJECT_HASHSIZE,
                             temph4toh5id->name_hashtab);
        if(check_sdsdim == 1) {

            /* 0. check the special case whether this sds dimensional name is shared,
     if yes, just increase the counter.*/
            /* Here we assume that the shared dimension name is unique among object names.
                 This may not be true for rare cases. Since we are going to implement
                 the SDS dimension scale to follow dimension scale specification. This piece of
                 code may not be used at all. So just document it here. KY 2014-05-21
            */
            if(check_sharename == 1) {
                strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
                free(h5sdsdim_name);
                SDendaccess(sdsdim_id);
                if(sdsdim_type == 0 || strcmp(sdsdim_name,sdsname) == 0) {
                    /*ignore when the dim name is the SDS name */
                    count_h5attrname++;
                    continue;
                }
                count_h5objref = count_h5objref + 1;
                count_h5attrname = count_h5attrname + 1;
                continue;
            }

            /* 1. create a hardlink to the dimensional scale that is already there.
     2. copy the name to h5sdsdim_allname for dealing with object
     reference and attribute.
            */
            ori_h5sdsdimname = get_modname2(h4toh5_id,sdsdim_name,DIM_HASHSIZE,
                            temph4toh5id->moddim_hashtab);
            if(ori_h5sdsdimname == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain the original dimension name ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(H5Glink(sh5_dimgroup,H5G_LINK_HARD,ori_h5sdsdimname,h5sdsdim_name) <0) {
                H4toH5error_set(temph4toh5id,3,"fail to create hardlink",
                        __FILE__,__LINE__);
                free(ori_h5sdsdimname);
                free(sdsdimempty);
                free(h5sdsdim_name);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            free(h5sdsdim_name);
            free(ori_h5sdsdimname);
            count_h5objref ++;
            count_h5attrname ++;
            continue;
        }

        /* Here we should add some comments for fakedim0--name.
             It seems that hdf4(netcdf) will use unique fake dimension name,
             fakedim + unique number, so check_sdsdim will never be 1 if the
             dimension name is fake name. Under this case, count_h5objref
             and count_h5attrname will not increase if this dimension doesnot
             have dimensional scale data.
             That assures the object reference of sds is correct. */

        else { /* the dimensional scale is not visited. */

            /* get h5 dimensional scale data type. */
            /* Here we come to another messy case:
                 if some dimensional names are fake names(fakedim0) and some
                        are real names, we will still put those dimensional names into
                        dimensional name lists.*/

            if(strcmp(sdsdim_name,sdsname) == 0) {
                free(h5sdsdim_name);
                continue;
            }
            if(sdsdim_type == 0 ) {
                strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
                sdsdimempty[i] =1;
                count_h5attrname ++;
                free(h5sdsdim_name);
                continue;
            }

            if(h4type_to_h5type(h4toh5_id,sdsdim_type,&h5dim_memtype,
                &h4dim_memsize,&h4dim_size,&h5dim_tid)== FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "fail to convert HDF4 datatype into HDF5 datatype ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* dimensional scale dataset cannot be H5T_STRING data type.
            So transferring back to int8 */

            if (h5dim_tid == H5T_STRING) {
                if(h5string_to_int(h4toh5_id,sdsdim_type,&h5dim_memtype,h4dim_memsize,
                             &h5dim_tid)==FAIL){
                    H4toH5error_set(temph4toh5id,5,
                            "fail to convert HDF5 string into INT ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(sdsdimempty);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
            }

            /* get the dimensional scale data. */
            dim_scadata = malloc(h4dim_memsize*sds_dimscasize[0]);
            if(dim_scadata == NULL) {
                H4toH5error_set(temph4toh5id,2,"cannot allocate memory for dimensional data ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            istat               = SDgetdimscale(sdsdim_id,(VOIDP)dim_scadata);
            if (istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,"cannot get SDS dimensional scale data ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                free(dim_scadata);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* set dimensional scale size properly. */
            h5dimscas[0] = sds_dimscasize[0];

            /* only set for the first dimension if SDS is unlimited dimension. */
            if(SDisrecord(sds_id) && i == 0)
                max_h5dimscas[0] = H5S_UNLIMITED;
            else
                max_h5dimscas[0] = h5dimscas[0];
            h5dim_sid        = H5Screate_simple(1,h5dimscas,max_h5dimscas);
            if(h5dim_sid <0) {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 space ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* create property list, for chunked sds or unlimited dimension cases */
            create_plist = get_dimchunking_plistid(h4toh5_id,sds_id,sdsdim_id,i,sds_dimsizes[0]);
            if(create_plist == -1) {
                H4toH5error_set(temph4toh5id,5,"cannot get property list" ,
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            /* create h5 dataset under h5 dimensional group*/
            h5dim_dset   = H5DCREATE(sh5_dimgroup,h5sdsdim_name,h5dim_tid,
                         h5dim_sid,create_plist);
            if(h5dim_dset <0) {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 dataset",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Pclose(create_plist);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if (H5Dwrite(h5dim_dset,h5dim_memtype,h5dim_sid,h5dim_sid,
             H5P_DEFAULT,(void *)dim_scadata)<0) {
                H4toH5error_set(temph4toh5id,3,"cannot write HDF5 dataset",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Pclose(create_plist);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(is_valid_attr_flag(attr_flag)==0) {
                H4toH5error_set(temph4toh5id,5,"attribute flag is set wrong ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Pclose(create_plist);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(ref_flag <0 || ref_flag > 1) {
                H4toH5error_set(temph4toh5id,5,"reference flag is set wrong ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Pclose(create_plist);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
                check_gloattr = 0;
                if(sds_transattrs(h4toh5_id,sdsdim_id,h5dim_dset,num_sdsdimattrs,check_gloattr,attr_flag)
                     == FAIL){
                    H4toH5error_set(temph4toh5id,5,"fail to convert SDS dimension attributes ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(dim_scadata);
                    free(sdsdimempty);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Pclose(create_plist);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
            }

            free(dim_scadata);

            /* updating object reference count and attribute name count. */

            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            count_h5objref = count_h5objref + 1;
            count_h5attrname =count_h5attrname  + 1;
        }
        free(h5sdsdim_name);

        /*HDF5 interfaces related to dimensional datasets should be released. */
        ret = H5Pclose(create_plist);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 property list",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Sclose(h5dim_sid);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        ret = H5Sclose(h5dim_sid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 data space",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        ret = H5Dclose(h5dim_dset);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 dim data set",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
    }


    /*1. create object reference number to dimensional scale dataset.
        2. store absolute name of dimensional name into
        dimensional list. */

    /* open original hdf5 dataset. */

    if(ref_flag == 0) {
        /*** no object reference and hdf5 dataset name will be returned. ***/
        H5Gclose(sh5_dimgroup);
        free(sdsdimempty);
        return SUCCEED;
    }

    else {

        /* obtain the new h5dataset name */
        if(h5dsetname == NULL) {
            /* generating two names.
     1. make up name based on HDF4_SDS,h5groupname,sds_ref.
     call this name h5replacesds_name
     2. using lookup_name to check whether this name is stored already.
     3. If yes, use this name as the h5datasetname.
     4. no, obtain name based on groupname + sds name.
            */

            if(conv_int_str(h4toh5_id,(uint16)sds_ref,refstr)== FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "fail to convert reference number into HDF5 string ",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }
            h5crepsds_name = make_objname_no(h4toh5_id,refstr,h5groupname,HDF4_SDS);
            if(lookup_name(h4toh5_id,h5crepsds_name,SDS_HASHSIZE,
                 temph4toh5id->name_hashtab)==1){
                h5csds_name = malloc(strlen(h5crepsds_name)+1);
                if(h5csds_name == NULL) {
                    H4toH5error_set(temph4toh5id,1,
                            "unable to allocate memory for HDF5 sds name ",
                            __FILE__,__LINE__);
                    H5Gclose(sh5_dimgroup);
                    free(sdsdimempty);
                    return FAIL;
                }
                strcpy(h5csds_name, h5crepsds_name);
            }

            else {
                cor_sdsname = correct_name(h4toh5_id,sdsname);
                if(cor_sdsname == NULL){
                    H4toH5error_set(temph4toh5id,4,"failed to get HDF5 dataset name",
                            __FILE__,__LINE__);
                    H5Gclose(sh5_dimgroup);
                    free(sdsdimempty);
                    return FAIL;
                }
                h5csds_name = make_objname_yes(h4toh5_id,cor_sdsname,h5groupname);
                            free(cor_sdsname);
                if(h5csds_name == NULL) {
                    H4toH5error_set(temph4toh5id,4,
                            "cannot obtain hdf5 sds name ",
                            __FILE__,__LINE__);
                    H5Gclose(sh5_dimgroup);
                    free(sdsdimempty);
                    return FAIL;
                }
            }
            free(h5crepsds_name);
        }
        else {
            cor_h5dsetname = correct_name(h4toh5_id,h5dsetname);
            if(cor_h5dsetname == NULL){
                H4toH5error_set(temph4toh5id,4,"failed to get HDF5 dataset name",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }

            h5csds_name = make_objname_yes(h4toh5_id,cor_h5dsetname,h5groupname);
            free(cor_h5dsetname);
            if(h5csds_name == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain hdf5 sds name ",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }
            if(lookup_name(h4toh5_id,h5csds_name,SDS_HASHSIZE,
                 temph4toh5id->name_hashtab)==0){
                H4toH5error_set(temph4toh5id,4,
                        "this object name has not been set, results unexpected ",
                        __FILE__,__LINE__);
                free(h5csds_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
        }

        /* Obtain HDF5 group ID and DATASET ID that refer to SDS dimensional
             scale. */

        h5_group        =  get_h5groupid(h5groupname,h4toh5_id,attr_flag);

        if(h5_group < 0) {
            H4toH5error_set(temph4toh5id,4,
                    "cannot obtain hdf5 group id ",
                    __FILE__,__LINE__);
            free(h5csds_name);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        h5dset = H5DOPEN(h5_group,h5csds_name);

        if (h5dset < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot open hdf5 dataset ",
                    __FILE__,__LINE__);
            free(h5csds_name);
            free(sdsdimempty);
            H5Gclose(h5_group);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        if(store_objref(h4toh5_id,count_h5objref,h5sdsdim_allname,
                sh5_dimgroup,h5dset,sdsdimempty)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "cannot store object reference",
                    __FILE__,__LINE__);
            free(h5csds_name);
            free(sdsdimempty);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        if(store_attrname(h4toh5_id,count_h5attrname,h5sdsdim_allname,h5dset)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "cannot store attribute name",
                    __FILE__,__LINE__);
            free(h5csds_name);
            free(sdsdimempty);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        if (attach_allscales(h4toh5_id,h5dset,count_h5objref,h5sdsdim_allname,sh5_dimgroup,h5csds_name,h5_group,sdsdimempty) == FAIL){
            H4toH5error_set(temph4toh5id,5,
            "cannot attach dim scale",
            __FILE__,__LINE__);
            free(h5csds_name);
            free(sdsdimempty);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        ret = H5Dclose(h5dset);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 data set",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            free(h5csds_name);
            H5Gclose(h5_group);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        ret = H5Gclose(h5_group);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 group",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            free(h5csds_name);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        ret = H5Gclose(sh5_dimgroup);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 dim group",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            free(h5csds_name);
            return FAIL;
        }
        free(h5csds_name);
    }
    free(sdsdimempty);
    return SUCCEED;

}

/****************H4toH5all_dimscalecdf*******************

* Purpose:       translate netcdf dimensional scale dataset into
                                hdf5 dataset
*
* Return:   FAIL if failed, SUCCEED if successful.
*
* In :
        h4toh5_id:              id for h4toh5 id handle
        sds_id:                 SDS identifier
        h5_dimgroupname:        hdf5 group name that user wants
                                to put dimensional scale dataset in
        h5_groupname:               hdf5 group name that sds
                                (not sds dimensional scale) will be put.
        h5_datasetname:         hdf5 dataset name of the sds
                                (not sds dimensional scale)object.
        ref_flag:               a flag to show whether object reference
                                and attribute name should be included to
                                the hdf5 dataset converted from sds object
        attr_flag:              a flag to indicate whether all attributes
                                of sds dimensional scale datasets should
                                be converted
  Out:
  Modification:

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

int H4toH5all_dimscalecdf(hid_t  h4toh5_id,
                int32  sds_id,
                char*  h5groupname,
                char*  h5dsetname,
                char*  h5_dimgroupname,
                int      attr_flag,
                int      ref_flag)
{
    /*varibles for dimensional scale dataset. */
    int32       sdsdim_id; /* SDS dimensional scale id */
    int32       sdsdim_type = 0; /* SDS dimensional scale data type */
    int32       sds_dimscasize[1]; /* the size of SDS dimensional scale */
    int         i; /* temporary variable for "for loop" */
    int         temp; /* temporary variable */
    int         count_h5objref; /* the counter to check the number of the object
                     references from the converted SDS to SDS dim.
                     scale. */
    int         count_h5attrname; /* the counter to check the number of
                         attributes that stores the attribute name
                         from HDF4 to HDF5. */
    int         check_sdsdim;  /* a temporary variable to check the existence of
                    SDS dimensional scale */
    int         check_gloattr; /* a temporary variable to check the existence of
                    the global attribute */
    int*        check_lookupptr; /* the pointer to check "hashing table" that
                        handles the collisions of SDS object names*/
    int         check_sharename; /* a temporary variable to check whether SDS
                        dim. scale is shared. */
    int32       num_sdsdimattrs; /* number of SDS dimensional scale attributes. */
    void*       dim_scadata; /* dim. scale data buffer */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    char*       cor_sdsdimname; /* the "corrected" SDS dimensional scale name */
    size_t  h4dim_memsize; /*dimensional scale size in memory*/
    size_t  h4dim_size; /* dimensional scale size in disk*/
    hsize_t chunk_dims[1];

    /* variables for SDS */
    int32       istat; /* temporary variable to check the "return" status  of HDF4 APIs */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* SDS rank */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */
    int*        sdsdimempty; /* this array is used to handle the inconsistent
                situation when the dim. scale name is given but
                the dim. scale data is not. */
    char        sdsname[H4H5_MAX_NC_NAME]; /* SDS name */

    /* varibles for HDF5. */
    hid_t       sh5_dimgroup; /* the parent HDF5 group of the object converted from
                 the dimensional scale */
    hid_t       h5dim_dset; /* HDF5 dataset converted from the dimensional scale */
    hid_t       h5dim_sid;  /* HDF5 data space id for "dimensional scale " */
    hid_t       h5dim_tid; /* HDF5 data type for "dimensional scale " */
    hid_t       h5dim_memtype; /* HDF5 data type for "dimensional scale" in memory */
    hid_t       create_plist; /* property list id for data creation */

    hid_t       h5dset; /* the HDF5 dataset */
    hid_t       h5_group; /* the parent HDF5 group of the "SDS" object */
    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */

    char*       h5sdsdim_name; /* HDF5 "SDS dimensional scale name " */
    char*       ori_h5sdsdimname; /* If the current dimensional scale has already
                         been converted, the original dimensional scale
                         dataset name */

    char*       h5csds_name; /* the absolute path of HDF5 dataset converted
                from SDS*/
    char        h5sdsdim_allname[H4H5_MAX_VAR_DIMS * H4H5_MAX_DIM_NAME];/* The SDS dimensional
                                 scale dataset name list */
    char        h5dimpath_name[H4H5_MAX_DIM_NAME]; /* The parent HDF5 group name of the
                         converted "SDS dimensional scale */
    herr_t  ret; /* the temporary variable to check the "return" status  of HDF5 APIs */

    char* cor_h5dsetname = NULL;
    char* cor_sdsname =NULL;

    h4toh5id_t* temph4toh5id; /* a pointer to h4toh5 id*/

    temp = 0;
    check_lookupptr = &temp;

    temph4toh5id = H4TOH5I_object(h4toh5_id);
    /*zero out memory for h5sdsdim_allname and h5dimpath_name */

    h4toh5_ZeroMemory(h5sdsdim_allname,(H4H5_MAX_VAR_DIMS*H4H5_MAX_DIM_NAME)*sizeof(char));
    h4toh5_ZeroMemory(h5dimpath_name,H4H5_MAX_DIM_NAME*sizeof(char));


    /* using SDS getinfo to get all the information of this SDS object.*/
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,"fail to get SDS information",
                __FILE__,__LINE__);
        return FAIL;
    }

    sdsdimempty = malloc(sds_rank *sizeof(int32));

    for (i=0;i<sds_rank;i++)
        sdsdimempty[i] = 0;

    /* the following section checks whether the dimensional scale
         is empty. */
    count_h5objref   = 0;
    count_h5attrname = 0;

    for (i = 0; i<sds_rank;i++) {
        sdsdim_id        = SDgetdimid(sds_id,i);
        if(sdsdim_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }

        istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                    &sdsdim_type,&num_sdsdimattrs);

        if (istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension information",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }

        if(sdsdim_type == 0) {
            if(strncmp(sdsdim_name,fakeDim,strlen(fakeDim))==0){
                continue;
            }
        }
        count_h5objref ++;
        count_h5attrname ++;
        if(count_h5objref !=0 || count_h5attrname !=0)
            break;
    }

    /* if the dimensional scale is not empty, we will assign a group. */
    if(count_h5objref !=0 || count_h5attrname !=0) {
        /* getting hdf5 dim group;
             when the inputting dimensional scale group name is not NULL; */
        if(h5_dimgroupname != NULL) {
            sh5_dimgroup = get_h5groupid(h5_dimgroupname,h4toh5_id,attr_flag);
            strcpy(h5dimpath_name,h5_dimgroupname);
        }
        else { /* if user doesn't define hdf5 dimensional group name */
            strcpy(h5dimpath_name,HDF4_DIMG);
            sh5_dimgroup = get_h5groupid(h5dimpath_name,h4toh5_id,attr_flag);
        }
        if(sh5_dimgroup < 0) {
            H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional group id",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            return FAIL;
        }
    }

    else {
        free(sdsdimempty);
        return SUCCEED;
    }

    /* initialize the dimensional number of SDS dimensions */

    count_h5objref   = 0;
    count_h5attrname = 0;


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

        sdsdim_id        = SDgetdimid(sds_id,i);
        if(sdsdim_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                    &sdsdim_type,&num_sdsdimattrs);

        if (istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,"cannot obtain SDS dimension information",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        /* for unlimited SDS dimension, grab the current dimensional size. */
        if(sds_dimscasize[0] == 0) sds_dimscasize[0] = sds_dimsizes[0];

        /* Here we have very messy cases for dimensional scale when
             sdsdim_type is 0(or not set).
             When sdsdim_type is 0, it means no SDS dimensional scale
             data for this dimensions. However, users may define SDS dimensional
             scale name. We want to keep this information.
        */

        /* checking whether sds dimensional scale name contains ORI_SLASH,
             changing them into CHA_SLASH.*/

        /* no dimensional scale dataset is specified.*/
        cor_sdsdimname = correct_name(h4toh5_id,sdsdim_name);
        if(cor_sdsdimname == NULL) {
            H4toH5error_set(temph4toh5id,4,"cannot obtain corrected dimensional scale name",__FILE__,__LINE__);
            H5Gclose(sh5_dimgroup);
            free(sdsdimempty);
            return FAIL;
        }

        /* generating HDF5 dimensional scale name. */
        h5sdsdim_name = make_objname_yes(h4toh5_id,cor_sdsdimname,h5dimpath_name);
        if(h5sdsdim_name == NULL) {
            H4toH5error_set(temph4toh5id,5,"cannot obtain hdf5 dimensional name",
                    __FILE__,__LINE__);
            free(cor_sdsdimname);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
        free(cor_sdsdimname);
        /* check whether this name has been used before. */
        check_sdsdim = modlookup_updatename(h4toh5_id,sdsdim_name,h5sdsdim_name,
                    DIM_HASHSIZE,
                    temph4toh5id->moddim_hashtab);

        check_sharename= lookup_updatename(h4toh5_id,h5sdsdim_name,OBJECT_HASHSIZE,
                             temph4toh5id->name_hashtab);
        if(check_sdsdim == 1) {

            /* 0. check the special case whether this SDS dimensional name is shared,
     if yes, just increase the counter.*/
            if(check_sharename == 1) {
                strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
                free(h5sdsdim_name);
                SDendaccess(sdsdim_id);
                if(sdsdim_type == 0) {
                    count_h5attrname++;
                    continue;
                }
                count_h5objref = count_h5objref + 1;
                count_h5attrname = count_h5attrname + 1;
                continue;
            }

            /* 1. create a hardlink to the dimensional scale that is already there.
     2. copy the name to h5sdsdim_allname for dealing with object
     reference and attribute.
            */
            ori_h5sdsdimname = get_modname2(h4toh5_id,sdsdim_name,DIM_HASHSIZE,
                            temph4toh5id->moddim_hashtab);
            if(ori_h5sdsdimname == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain the original dimension name ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            if(H5Glink(sh5_dimgroup,H5G_LINK_HARD,ori_h5sdsdimname,h5sdsdim_name) <0) {
                H4toH5error_set(temph4toh5id,3,"fail to create hardlink",
                        __FILE__,__LINE__);
                free(ori_h5sdsdimname);
                free(sdsdimempty);
                free(h5sdsdim_name);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            free(ori_h5sdsdimname);
            free(h5sdsdim_name);
            count_h5objref ++;
            count_h5attrname ++;
            continue;
        }


        /** hdf4 and netcdf assure that SDS dim. name is unique. So if the
    absolute path of the sds dim. name is found to be used,
    this dimension should share with the dimensional name that
    first used this name to represent dimension**/
        else {

            SDendaccess(sdsdim_id);
            if(sdsdim_type == 0) {
                count_h5attrname++;
                strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
                sdsdimempty[i] = 1;
                continue;
            }


            if(h4type_to_h5type(h4toh5_id,sdsdim_type,&h5dim_memtype,
                &h4dim_memsize,&h4dim_size,&h5dim_tid)== FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "fail to convert HDF4 datatype into HDF5 datatype ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* dimensional scale dataset cannot be H5T_STRING data type.
     So transferring back to int8 */

            if (h5dim_tid == H5T_STRING) {
                if(h5string_to_int(h4toh5_id,sdsdim_type,&h5dim_memtype,h4dim_memsize,
                             &h5dim_tid)==FAIL){
                    H4toH5error_set(temph4toh5id,5,
                            "fail to convert HDF5 string into INT ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(sdsdimempty);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
            }
            /* get the dimensional scale data. */
            dim_scadata = malloc(h4dim_memsize*sds_dimscasize[0]);
            if(dim_scadata == NULL) {
                H4toH5error_set(temph4toh5id,2,"cannot allocate memory for dimensional data ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }
            istat               = SDgetdimscale(sdsdim_id,(VOIDP)dim_scadata);
            if (istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,"cannot get SDS dimensional scale data ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(sdsdimempty);
                free(dim_scadata);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            /* set dimensional scale size properly. */
            h5dimscas[0] = sds_dimscasize[0];

            /* only set for the first dimension if SDS is unlimited dimension. */
            if(SDisrecord(sds_id) && i == 0)
                max_h5dimscas[0] = H5S_UNLIMITED;
            else
                max_h5dimscas[0] = h5dimscas[0];
            h5dim_sid        = H5Screate_simple(1,h5dimscas,max_h5dimscas);
            if(h5dim_sid <0) {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 space ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            create_plist = H5Pcreate(H5P_DATASET_CREATE);
            if(SDisrecord(sds_id) && i == 0){
                chunk_dims[0] =(hsize_t)(sds_dimscasize[0]);
                if(H5Pset_chunk(create_plist, 1, chunk_dims)<0) {
                    H4toH5error_set(temph4toh5id,3,
                            "unable to set chunk property list",
                            __FILE__,__LINE__);
                    H5Pclose(create_plist);
                    free(h5sdsdim_name);
                    free(dim_scadata);
                    free(sdsdimempty);
                    H5Sclose(h5dim_sid);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
            }

            /* create h5 dataset under h5 dimensional group*/
            h5dim_dset   = H5DCREATE(sh5_dimgroup,h5sdsdim_name,h5dim_tid,
                         h5dim_sid,create_plist);
            if(h5dim_dset <0) {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 dataset",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Gclose(sh5_dimgroup);
                H5Pclose(create_plist);
                return FAIL;
            }
            if(H5Dwrite(h5dim_dset,h5dim_memtype,h5dim_sid,h5dim_sid,
               H5P_DEFAULT,(void *)dim_scadata)<0) {
                H4toH5error_set(temph4toh5id,3,"cannot write HDF5 dataset",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                H5Pclose(create_plist);
                return FAIL;
            }

            if(is_valid_attr_flag(attr_flag)==0) {
                H4toH5error_set(temph4toh5id,5,"attribute flag is set wrong ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(ref_flag <0 || ref_flag > 1) {
                H4toH5error_set(temph4toh5id,5,"reference flag is set wrong ",
                        __FILE__,__LINE__);
                free(h5sdsdim_name);
                free(dim_scadata);
                free(sdsdimempty);
                H5Sclose(h5dim_sid);
                H5Dclose(h5dim_dset);
                H5Gclose(sh5_dimgroup);
                return FAIL;
            }

            if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
                check_gloattr = 0;
                if(sds_transattrscdf(h4toh5_id,sdsdim_id,h5dim_dset,num_sdsdimattrs,check_gloattr)
                     == FAIL){
                    H4toH5error_set(temph4toh5id,5,"fail to convert SDS dimension attributes ",
                            __FILE__,__LINE__);
                    free(h5sdsdim_name);
                    free(dim_scadata);
                    free(sdsdimempty);
                    H5Sclose(h5dim_sid);
                    H5Dclose(h5dim_dset);
                    H5Gclose(sh5_dimgroup);
                    return FAIL;
                }
            }

            free(dim_scadata);

            /* updating object reference count and attribute name count. */

            strcpy(&h5sdsdim_allname[count_h5attrname*H4H5_MAX_DIM_NAME],h5sdsdim_name);
            count_h5objref = count_h5objref + 1;
            count_h5attrname =count_h5attrname  + 1;

            free(h5sdsdim_name);
        }


        /*HDF5 interfaces related to dimensional datasets should be released. */

        ret = H5Sclose(h5dim_sid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 data space",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Dclose(h5dim_dset);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }

        ret = H5Dclose(h5dim_dset);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 dim data set",
                    __FILE__,__LINE__);
            free(sdsdimempty);
            H5Gclose(sh5_dimgroup);
            return FAIL;
        }
    }
    /*1. create object reference number to dimensional scale dataset.
        2. store absolute name of dimensional name into
        dimensional list. */

    /* open original hdf5 dataset. */

    if(ref_flag == 0) {
        /*** no object reference and hdf5 dataset name will be returned. ***/
        H5Gclose(sh5_dimgroup);
        free(sdsdimempty);
        return SUCCEED;
    }

    else {

        /* obtain the new h5dataset name */
        if(h5dsetname == NULL) {
            /* generating two names.
        1. make up name based on HDF4_SDS,h5groupname,sds_ref.
        call this name h5replacesds_name
        2. using lookup_name to check whether this name is stored already.
        3. If yes, use this name as the h5datasetname.
        4. no, obtain name based on groupname + sds name.
            */

            cor_sdsname = correct_name(h4toh5_id,sdsname);
            if(cor_sdsname == NULL){
                H4toH5error_set(temph4toh5id,4,"failed to get HDF5 dataset name",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }
            h5csds_name = make_objname_yes(h4toh5_id,cor_sdsname,h5groupname);
            free(cor_sdsname);
            if(h5csds_name == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain hdf5 sds name ",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }
        }

        else {
            cor_h5dsetname = correct_name(h4toh5_id,h5dsetname);
            if(cor_h5dsetname == NULL){
                H4toH5error_set(temph4toh5id,4,"failed to get HDF5 dataset name",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }

            h5csds_name = make_objname_yes(h4toh5_id,cor_h5dsetname,h5groupname);
            free(cor_h5dsetname);
            if(h5csds_name == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain hdf5 sds name ",
                        __FILE__,__LINE__);
                H5Gclose(sh5_dimgroup);
                free(sdsdimempty);
                return FAIL;
            }

        }
    }

    /* Obtain HDF5 group ID and DATASET ID that refer to SDS dimensional
         scale. */

    h5_group        =  get_h5groupid(h5groupname,h4toh5_id,attr_flag);

    if(h5_group < 0) {
        H4toH5error_set(temph4toh5id,4,
                "cannot obtain hdf5 group id ",
                __FILE__,__LINE__);
        free(h5csds_name);
        free(sdsdimempty);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }

    h5dset = H5DOPEN(h5_group,h5csds_name);

    if (h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot open hdf5 dataset ",
                __FILE__,__LINE__);
        free(h5csds_name);
        free(sdsdimempty);
        H5Gclose(h5_group);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }

    if(store_objref(h4toh5_id,count_h5objref,h5sdsdim_allname,
            sh5_dimgroup,h5dset,sdsdimempty)==FAIL){
        H4toH5error_set(temph4toh5id,5,
                "cannot store object reference",
                __FILE__,__LINE__);
        free(h5csds_name);
        free(sdsdimempty);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }
    if(store_attrname(h4toh5_id,count_h5attrname,h5sdsdim_allname,h5dset)==FAIL){
        H4toH5error_set(temph4toh5id,5,
                "cannot store attribute name",
                __FILE__,__LINE__);
        free(h5csds_name);
        free(sdsdimempty);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }
    if (attach_allscales(h4toh5_id,h5dset,count_h5objref,h5sdsdim_allname,sh5_dimgroup,h5csds_name,h5_group,sdsdimempty) == FAIL){
    H4toH5error_set(temph4toh5id,5,
            "cannot attach dim scale",
            __FILE__,__LINE__);
        free(h5csds_name);
        free(sdsdimempty);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }

    ret = H5Dclose(h5dset);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot close HDF5 data set",
                __FILE__,__LINE__);
        free(sdsdimempty);
        free(h5csds_name);
        H5Gclose(h5_group);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }
    ret = H5Gclose(h5_group);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot close HDF5 group",
                __FILE__,__LINE__);
        free(sdsdimempty);
        free(h5csds_name);
        H5Gclose(sh5_dimgroup);
        return FAIL;
    }
    ret = H5Gclose(sh5_dimgroup);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot close HDF5 dim group",
                __FILE__,__LINE__);
        free(sdsdimempty);
        free(h5csds_name);
        return FAIL;
    }
    free(h5csds_name);

    free(sdsdimempty);

    return SUCCEED;

}


/*-------------------------------------------------------------------------
 * Function:    H4toH5sds
 *
 * Purpose:         translate a SDS object into an HDF5 dataset
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id:     h4toh5 identifier
 sds_id:            SDS identifier
 h5groupname: hdf5 group name(must be provided)
 h5dsetname:    hdf5 dataset name(can be set NULL)
 h5_dimgroupfullpath: hdf5 dimensional path name(can be set NULL)
 dim_flag:      flag to control the conversion of dimensional
 scale dataset
 attr_flag:  flag to control the conversion of attributes

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

int H4toH5sds(hid_t h4toh5_id,
                int32 sds_id,
                char* h5groupname,
                char* h5dsetname,
                char* h5_dimgroupfullpath,
                int dim_flag,
                int attr_flag)
{
    h4toh5id_t* temph4toh5id;

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

    /* file_id is valid only when H interfaces are used. For HDF4-generated netcdf, file_id is -1.
         Hishdf() is used to check.
         if Hishdf returns 1, the file is an HDF file, otherwise, it may be an HDF4-generated netcdf file.
         The check_filetype function can be found in the h4toh5main.c. */
    if(temph4toh5id->file_id == -1){
        if(H4toH5_sdscdf(h4toh5_id,sds_id,h5groupname,h5dsetname,
                 h5_dimgroupfullpath,dim_flag,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,2,
                    "cannot successfully convert CDF dataset",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }
    else {
        if(H4toH5_sds(h4toh5_id,sds_id,h5groupname,h5dsetname,h5_dimgroupfullpath,
            dim_flag,attr_flag) == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                    "cannot successfully convert CDF dataset",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }
    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:    H4toH5_sdscdf
 *
 * Purpose:         translate a netcdf dataset into an HDF5 dataset
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id:     h4toh5 identifier
 sds_id:            SDS identifier
 h5groupname: hdf5 group name(must be provided)
 h5dsetname:    hdf5 dataset name(can be set NULL)
 h5_dimgroupfullpath: hdf5 dimensional path name(can be set NULL)
 dim_flag:      flag to control the conversion of dimensional
 scale dataset
 attr_flag:  flag to control the conversion of attributes

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

int H4toH5_sdscdf(hid_t h4toh5_id,
            int32 sds_id,
            char* h5groupname,
            char* h5dsetname,
            char* h5_dimgroupfullpath,
            int dim_flag,
            int attr_flag)
{
    /* HDF4 variables. */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* rank of SDS */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* array to describe dimensional
                     size of SDS */
    int32*  sds_start; /* The starting point of SDS array to convert */
    int32*  sds_edge; /* The ending point of SDS array to convert */
    int32*  sds_stride; /* The stride of SDS array to convert */
    int32       count_sdsdata; /* The count of SDS array */
    int32       istat; /* check the "return" status  of HDF4 APIs */
    int         i; /* temporary variable to represent the index of for loop */
    int32       num_sdsattrs; /* number of SDS attributes */
    void*       sds_data; /* buffer to store SDS data */

    int         check_gloattr; /* temporary variable to check the SD interface
                    variable */

    char        sdsname[H4H5_MAX_NC_NAME]; /* SDS name */
    char        sdslabel[H4H5_MAX_NC_NAME]; /* SDS label */
    size_t  h4size; /* file size of the SDS data type */
    size_t  h4memsize; /* memory size of the SDS data type */
    hsize_t* chunk_dims;


    /* varibles for hdf5. */
    hid_t       h5_group; /* HDF5 group id */
    hid_t       h5dset; /* HDF5 dataset id */
    hid_t       h5d_sid; /* HDF5 data space id */
    hid_t       h5ty_id; /* HDF5 data type(in disk) id */
    hid_t       h5_memtype; /* HDF5 data type(in memory) id */
    hid_t       create_plist; /* creation property list of dataset*/
    hsize_t h5dims[H4H5_MAX_VAR_DIMS]; /* an array of size of each dimension of HDF5
                     dataset converted from SDS*/
    hsize_t max_h5dims[H4H5_MAX_VAR_DIMS]; /* the array of maximum size of each
                             dimension of HDF5 dataset converted from SDS */
    char*       h5csds_name; /* absolute path of HDF5 dataset converted from SDS */
    herr_t  ret; /* the temporary variable to check the "return" status of HDF5 APIs */

    h4toh5id_t* temph4toh5id; /* pointer to h4toh5id structure */

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

    /*** part I: SDS object handling. ***/

    /* zeroing out the memory for sdsname and sdslabel.*/
    h4toh5_ZeroMemory(sdsname,H4H5_MAX_NC_NAME);
    h4toh5_ZeroMemory(sdslabel,H4H5_MAX_NC_NAME);

#if 0
    /* check whether the SDS is empty. */
    if(SDcheckempty(sds_id,&sds_empty)== FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot run SDcheckempty routine",
                __FILE__,__LINE__);
        return FAIL;
    }

#endif
    /*obtain name,rank,dimsizes,datatype and num of attributes of sds */
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get information of SDS object",
                __FILE__,__LINE__);
        return FAIL;
    }

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

    if(sdsname[0]=='\0'){
        H4toH5error_set(temph4toh5id,5,
                "Netcdf dataset name is NULL",
                __FILE__,__LINE__);
        return FAIL;
    }

    h5csds_name = make_objname_yes(h4toh5_id,sdsname,h5groupname);

#if 0
    if(sds_empty != 0) {
        if(sds_dimsizes[0] == 0) return SUCCEED; /*{
                                 if(convert_netcdfzerounlimit(h4toh5_id,sds_id,h5_group,h5groupname,
                                 h5csds_name,attr_flag)==FAIL){
                                 H4toH5error_set(temph4toh5id,5,
                                 "cannot convert SDS unlimited dimension correctly",
                                 __FILE__,__LINE__);
                                 return FAIL;
                                 }
                                 return SUCCEED;
                                 }*/
        else return SUCCEED; /* {
                    if(convert_sdsfillvalue(h4toh5_id,sds_id,h5_group,h5groupname,
                    h5csds_name,attr_flag)==FAIL) {
                    H4toH5error_set(temph4toh5id,5,
                    "cannot convert SDS fill value correctly",
                    __FILE__,__LINE__);
                    free(h5csds_name);
                    H5Gclose(h5_group);
                    return FAIL;
                    }
                    return SUCCEED;
                    }
             */
    }
#endif
    /* part III. obtain start,edge, stride and number of sds data. */
    if(sds_rank != 0) {
        sds_start           = malloc(sizeof(int32)*sds_rank);
        if(sds_start == NULL) {
            H4toH5error_set(temph4toh5id,1,
                    "cannot allocate memory for SDS starting array",
                    __FILE__,__LINE__);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        sds_edge            = malloc(sizeof(int32)*sds_rank);
        if(sds_edge == NULL) {
            H4toH5error_set(temph4toh5id,1,
                    "cannot allocate memory for SDS edging array",
                    __FILE__,__LINE__);
            free(sds_start);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        sds_stride      = malloc(sizeof(int32)*sds_rank);
        if(sds_stride == NULL) {
            H4toH5error_set(temph4toh5id,1,
                    "cannot allocate memory for SDS stride",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        count_sdsdata = 1;
        for (i=0;i<sds_rank;i++){
            sds_stride[i] = 1;
            sds_start[i]    = 0;
            sds_edge[i]     = sds_dimsizes[i];
            count_sdsdata = count_sdsdata*sds_dimsizes[i];
        }

        for (i=0;i<sds_rank;i++) {
            h5dims[i] = sds_edge[i]-sds_start[i];
            max_h5dims[i] = h5dims[i];
        }
    }
    else {
        sds_start = malloc(sizeof(int32));
        sds_edge = malloc(sizeof(int32));
        sds_stride = malloc(sizeof(int32));
        sds_start[0] = 0;
        sds_edge[0] = 1;
        sds_stride[0] = 1;
        count_sdsdata = 1;
    }

    if(sds_rank != 0)
        if(SDisrecord(sds_id)) max_h5dims[0] = H5S_UNLIMITED;

    /* Datatype conversion is done here since memory allocation size
         should be known first. */
    /* convert HDF4 data type to HDF5 data type. */
    if  (h4type_to_h5type(h4toh5_id,sds_dtype,&h5_memtype,&h4memsize,&h4size,
            &h5ty_id) == FAIL) {
        H4toH5error_set(temph4toh5id,5,
                "cannot convert HDF4 data type to HDF5 data type",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* check whether the datatype is string, if we find string format,
         we will change them back into integer format.*/
    if (h5ty_id == H5T_STRING) {

        /* rechange string datatype into numerical datatype.*/
        if(h5string_to_int(h4toh5_id,sds_dtype,&h5_memtype,h4memsize,
                     &h5ty_id)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "cannot translate H5T_STRING into int",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    sds_data = malloc(h4memsize*count_sdsdata);
    if(sds_data == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS data",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    create_plist = H5Pcreate(H5P_DATASET_CREATE);
    if(create_plist == -1) {
        H4toH5error_set(temph4toh5id,3,
                "unable to create property list",
                __FILE__,__LINE__);
        free(sds_data);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(h5csds_name);
        H5Gclose(h5_group);
 
        return FAIL;
    }
    if(sds_rank != 0) {
        chunk_dims   = malloc(sizeof(hsize_t)*sds_rank);
        if(chunk_dims == NULL) {
            H5Pclose(create_plist);
            H4toH5error_set(temph4toh5id,1,
                    "unable to allocate memory for chunk_dims",
                    __FILE__,__LINE__);
           free(sds_data);
           free(sds_start);
           free(sds_edge);
           free(sds_stride);
           free(h5csds_name);
           H5Gclose(h5_group);
            return FAIL;
        }

        for (i =0;i<sds_rank;i++)
            chunk_dims[i] = (hsize_t)(sds_dimsizes[i]);
    }

    else {
        chunk_dims = malloc(sizeof(hsize_t));
        chunk_dims[0] = 1;
    }

    if(sds_rank != 0) {
        if(SDisrecord(sds_id)){
            if(H5Pset_chunk(create_plist, sds_rank, chunk_dims)<0) {
                H4toH5error_set(temph4toh5id,3,
                        "unable to obtain chunk information for unlimited dimension",
                        __FILE__,__LINE__);
                free(chunk_dims);
                free(sds_start);
                free(sds_edge);
                free(sds_stride);
                free(sds_data);
                free(h5csds_name);
                H5Gclose(h5_group);
                H5Pclose(create_plist);
                return FAIL;
            }
        }
    }
    istat        = SDreaddata(sds_id, sds_start, sds_stride, sds_edge,
            (VOIDP)sds_data);
    if (istat == FAIL)  {
        H4toH5error_set(temph4toh5id,2,
                "cannot read SDS data",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        free(chunk_dims);
        H5Pclose(create_plist);
        return FAIL;
    }



    /* part IV. converting SDS into hdf5 dataset. */

    if(sds_rank == 0) {
        h5d_sid = H5Screate(H5S_SCALAR);
    }

    else {
        h5d_sid = H5Screate_simple(sds_rank,h5dims,max_h5dims);
        if (h5d_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot create HDF5 data space",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(sds_data);
            free(h5csds_name);
            H5Gclose(h5_group);
            free(chunk_dims);
            H5Pclose(create_plist);
            return FAIL;
        }
    }
    h5dset = H5DCREATE(h5_group,h5csds_name,h5ty_id,h5d_sid,create_plist);
    if (h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot create HDF5 dataset converted from SDS ",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        H5Sclose(h5d_sid);
        free(h5csds_name);
        H5Gclose(h5_group);
        free(chunk_dims);
        H5Pclose(create_plist);
        return FAIL;
    }

    if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,H5P_DEFAULT,
                 (void *)sds_data)<0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to write HDF5 dataset",
                __FILE__,__LINE__);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        free(chunk_dims);
        H5Pclose(create_plist);
        return FAIL;
    }

    free(sds_start);
    free(sds_edge);
    free(sds_stride);
    free(sds_data);
    free(chunk_dims);
    if(is_valid_attr_flag(attr_flag)==0) {
        H4toH5error_set(temph4toh5id,5,
                "attribute flag is set wrong ",
                __FILE__,__LINE__);
        H5Pclose(create_plist);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(dim_flag <0 || dim_flag > 1) {
        H4toH5error_set(temph4toh5id,5,
                "dimensional flag is set wrong",
                __FILE__,__LINE__);
        H5Pclose(create_plist);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }


    if(dim_flag == H425_DIMSCALE) {
        if(attr_flag == H425_ALLATTRS || attr_flag == H425_NO_PREDEF_ATTRS || attr_flag == H425_SV) {
            if(H4toH5all_dimscale_h5ds(h4toh5_id,sds_id,h5dset,attr_flag) == FAIL){
                H4toH5error_set(temph4toh5id,5,
                                            "unable to convert all dimensional scales to HDF5 datasets",
                                            __FILE__,__LINE__);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }

        else {
            if(H4toH5all_dimscalecdf(h4toh5_id,sds_id,h5groupname,h5dsetname,
                         h5_dimgroupfullpath,attr_flag,1) == FAIL) {

                H4toH5error_set(temph4toh5id,5,
                        "unable to convert all dimensional scales to HDF5 datasets",
                        __FILE__,__LINE__);
                H5Pclose(create_plist);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
    }
    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        check_gloattr = 0;
        if (sds_transattrscdf(h4toh5_id,sds_id,h5dset,num_sdsattrs,check_gloattr)==FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "unable to convert SDS attributes",
                    __FILE__,__LINE__);
            H5Pclose(create_plist);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        strcpy(sdslabel,"netCDF");

        if(attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_ALLATTRS) {
            if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_TYPE,sdslabel)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                    "unable to convert SDS label to attribute",
                    __FILE__,__LINE__);
                H5Pclose(create_plist);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
    }
    ret     = H5Sclose(h5d_sid);
    if( ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to close HDF5 data space interface",
                __FILE__,__LINE__);
        H5Dclose(h5dset);
        free(h5csds_name);
        H5Pclose(create_plist);
        H5Gclose(h5_group);
        return FAIL;
    }
    ret     = H5Dclose(h5dset);
    if( ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to close HDF5 dataset interface",
                __FILE__,__LINE__);
        free(h5csds_name);
        H5Pclose(create_plist);
        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(h5csds_name);
        H5Pclose(create_plist);
        return FAIL;
    }
    H5Pclose(create_plist);
    free(h5csds_name);
    return SUCCEED;
}


static int add_fillvalue(hid_t h4toh5_id, int32 sds_id, hid_t plist, size_t h4memsize, hid_t h5ty_id)
{
    void *fillvalue = 0;
    h4toh5id_t* temph4toh5id;
    int succeeded = 0;

    temph4toh5id = H4TOH5I_object(h4toh5_id);
    do {

        if ((fillvalue = malloc(h4memsize)) == NULL) {
            H4toH5error_set(temph4toh5id,2,
                    "cannot allocate buffer to fetch fill value", __FILE__, __LINE__);
            break;
        }

        if (SDgetfillvalue(sds_id, fillvalue) == SUCCEED) {
            if (H5Pset_fill_value(plist, h5ty_id, fillvalue) < 0) {
                H4toH5error_set(temph4toh5id,2,
                        "unable to set HDF5 fill value option", __FILE__, __LINE__);
                break;
            }
        }

        succeeded = 1;
    } while (0);

    if (fillvalue) free(fillvalue);
    return succeeded ? SUCCEED : FAIL;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5_sds
 *
 * Purpose:         translate a SDS object into an HDF5 dataset
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id:     h4toh5 identifier
 sds_id:            SDS identifier
 h5groupname: hdf5 group name(must be provided)
 h5dsetname:    hdf5 dataset name(can be set NULL)
 h5_dimgroupfullpath: hdf5 dimensional path name(can be set NULL)
 dim_flag:      flag to control the conversion of dimensional
 scale dataset
 attr_flag:  flag to control the conversion of attributes

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

int H4toH5_sds(hid_t h4toh5_id,
                 int32 sds_id,
                 char* h5groupname,
                 char* h5dsetname,
                 char* h5_dimgroupfullpath,
                 int dim_flag,
                 int attr_flag)
{
    /* HDF4 variables. */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* rank of SDS */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* array to describe dimensional
                     size of SDS */
    int32*  sds_start; /* The starting point of SDS array to convert */
    int32*  sds_edge; /* The ending point of SDS array to convert */
    int32*  sds_stride; /* The stride of SDS array to convert */
    int32       count_sdsdata; /* The count of SDS array */
    int32       sds_ref; /* SDS reference number */
    intn        sds_empty; /* the variable to check whether SDS is empty. */
    int32       istat; /* check the "return" status  of HDF4 APIs */
    int         i; /* temporary variable to represent the index of for loop */
    int         check_sds; /* temporary variable to check SDS */
    int32       num_sdsattrs; /* number of SDS attributes */
    void*       sds_data; /* buffer to store SDS data */

    int         check_sdsname; /* temporary variable to check the confliction
                    of SDS name */
    int         check_gloattr; /* temporary variable to check the SD interface
                    variable */

    char        sdsname[H4H5_MAX_NC_NAME]; /* SDS name */
    char        sdslabel[H4H5_MAX_NC_NAME]; /* SDS label */
    size_t  h4size; /* file size of the SDS data type */
    size_t  h4memsize; /* memory size of the SDS data type */
    size_t bufsize;


    /* varibles for hdf5. */
    hid_t       h5_group; /* HDF5 group id */
    hid_t       h5dset; /* HDF5 dataset id */
    hid_t       h5d_sid; /* HDF5 data space id */
    hid_t       h5ty_id; /* HDF5 data type(in disk) id */
    hid_t       h5_memtype; /* HDF5 data type(in memory) id */
    hid_t       create_plist; /* creation property list of dataset*/
    hid_t       write_plist;
    hsize_t h5dims[H4H5_MAX_VAR_DIMS]; /* an array of size of each dimension of HDF5
                     dataset converted from SDS*/
    hsize_t max_h5dims[H4H5_MAX_VAR_DIMS]; /* the array of maximum size of each
                             dimension of HDF5 dataset converted from SDS */
    char*       h5csds_name; /* absolute path of HDF5 dataset converted from SDS */
    char*       ori_h5csds_name; /* The absolute path of the original HDF5 dataset
                        if the current SDS is visited */
    herr_t  ret; /* the temporary variable to check the "return" status of HDF5 APIs */
    int         check_lookup; /* variable to check the status of SDS look-up table */
    int         temp; /* temporary variable */
    int*        check_lookupptr; /* an integer pointer to pass the check_lookup value */

    h4toh5id_t* temph4toh5id; /* pointer to h4toh5id structure */

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

    /* check_lookup is to check whether h5dsetname is already
         used as the name of other HDF5 object.
    */

    check_lookup = 0;
    check_lookupptr =&check_lookup;
    temp =0;

    /*** part I: SDS object handling. ***/

    /* zeroing out the memory for sdsname and sdslabel.*/
    h4toh5_ZeroMemory(sdsname,H4H5_MAX_NC_NAME);
    h4toh5_ZeroMemory(sdslabel,H4H5_MAX_NC_NAME);

    /* check whether the SDS is empty. */
    if(SDcheckempty(sds_id,&sds_empty)== FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot run SDcheckempty routine",
                __FILE__,__LINE__);
        return FAIL;
    }

    /*obtain name,rank,dimsizes,datatype and num of attributes of sds */
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get information of SDS object",
                __FILE__,__LINE__);
        return FAIL;
    }

    if(lookup_name(h4toh5_id,sdsname,DIMPURE_HASHSIZE,temph4toh5id->puredim_hashtab) ==1)
        return SUCCEED;
    /* Due to the bug in SDcheckempty(), sds_empty may not be correct.
     * In particular, sds_empty can be zero even when sds_dimsizes[0] is zero.
     * So, sds_empty has the second chance to be non-zero, here.
     * This is related to the bugzilla #1382.
     * This second chance is not necessary for HDF4 later than 4.2r3.
     */
    if (sds_empty == 0)
        sds_empty = sds_dimsizes[0] == 0;

    /* part II. obtain the hdf5  name. */
    /*obtaining reference number and name of h5 dataset
        corresponding to sds. */

    sds_ref = SDidtoref(sds_id);
    /* Just for netcdf conversion */
    if(sds_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot obtain SDS reference number",
                __FILE__,__LINE__);
        return FAIL;
    }

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

    check_sds = lookup(h4toh5_id,sds_ref,SDS_HASHSIZE,temph4toh5id->sds_hashtab,&temp);

    /* obtain the new h5dataset name */
    if(h5dsetname == NULL) {

        /*
             1) Assume the user will not use HDF4_SDS_REF as their own
             SDS name.
             2) Check whether this SDS was looked up or not. If this SDS
             has been looked up, it must be assigned a name.
             lookup_name is to make sure the obtained name is not used
             before.
        */

        h5csds_name = get_h5datasetname(h4toh5_id,h5groupname,sdsname,(uint16)sds_ref,
                        HDF4_SDS,OBJECT_HASHSIZE,check_lookupptr);
#ifdef HAVE_LIBHDFEOS
        if (H4toH5config_use_eos2_conversion())
            H4toH5eos_add_mangled_sdsname(h4toh5_id, sdsname, h5csds_name);
#endif

        if(lookup_name(h4toh5_id,h5csds_name,OBJECT_HASHSIZE,
             temph4toh5id->name_hashtab)==1) {
            H4toH5error_set(temph4toh5id,4,
                    "this SDS name has been used",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    else {
        h5csds_name = get_h5datasetname(h4toh5_id,h5groupname,h5dsetname,
                        (uint16)sds_ref,HDF4_SDS,OBJECT_HASHSIZE,check_lookupptr);

#ifdef HAVE_LIBHDFEOS
        if (H4toH5config_use_eos2_conversion())
            H4toH5eos_add_mangled_sdsname(h4toh5_id, h5dsetname, h5csds_name);
#endif

        if(*check_lookupptr == 1) {/* the user-input sds name is used.*/
            H4toH5error_set(temph4toh5id,4,
                    "this dataset name is used by another object",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    /*update the hdf5 dataset table*/
    if(lookup_updatename(h4toh5_id,h5csds_name,OBJECT_HASHSIZE,
                     temph4toh5id->name_hashtab)==-1) {
        H4toH5error_set(temph4toh5id,4,
                "cannot update the object name in the name table",
                __FILE__,__LINE__);
        H5Gclose(h5_group);
        free(h5csds_name);
        return FAIL;
    }

    /* check whether this sds is touched, if not; put this SDS name into
         the SDS table; this will be used to create hardlink when
         multiple groups include one SDS object.*/

    if(check_sds == 0) {
        /* put the absolute path of sds into "hashing table".*/
        if(set_name(h4toh5_id,sds_ref,SDS_HASHSIZE,temph4toh5id->sds_hashtab,
        h5csds_name,-1)==FAIL) {
            H4toH5error_set(temph4toh5id,4,
                    "cannot set object name properly",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5csds_name);
            return FAIL;
        }
    }

    else {/* create a hard link and return back.*/
        ori_h5csds_name = get_name(h4toh5_id,sds_ref,SDS_HASHSIZE,
                         temph4toh5id->sds_hashtab,&check_sdsname);
        if(ori_h5csds_name == NULL) {
            H4toH5error_set(temph4toh5id,4,
                    "cannot get the original HDF5 dataset name converted from SDS", __FILE__,__LINE__);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        if(H5Glink(h5_group,H5G_LINK_HARD,ori_h5csds_name,h5csds_name) <0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot set up hard link to original dataset name ",
                    __FILE__,__LINE__);
            free(h5csds_name);
            free(ori_h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }
        free(h5csds_name);
        free(ori_h5csds_name);
        ret = H5Gclose(h5_group);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "cannot close HDF5 group interface ",
                    __FILE__,__LINE__);
            return FAIL;
        }
        return SUCCEED;
    }

    if(sds_empty != 0) {
        if(sds_dimsizes[0]==0) {
            /*currently H4 to H5 converter support this case, we will not implement
    this special case in the beta-release until we get more responses.
    Jan. some time, 2002.
    We have to re-implement h4toh5 converter utility with h4toh5 library
    so, we have to deal with this special case now,July 15th, 2002.*/

            if(convert_sdszerounlimit(h4toh5_id,sds_id,h5_group,h5groupname,h5dsetname,
                h5csds_name,attr_flag)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "cannot convert SDS unlimited dimension correctly",
                        __FILE__,__LINE__);
                if(h5csds_name != NULL)
                        free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }

            if(h5csds_name !=NULL)
                free(h5csds_name);
            H5Gclose(h5_group);
            return SUCCEED;
        }


        else {
            if(convert_sds_fillvalue_or_nodim_data(h4toh5_id,sds_id,h5_group,h5groupname,h5dsetname,
                        h5csds_name,h5_dimgroupfullpath,dim_flag,attr_flag,0)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "cannot convert SDS fill value correctly",
                        __FILE__,__LINE__);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
            if(h5csds_name !=NULL)
                free(h5csds_name);
            H5Gclose(h5_group);

            return SUCCEED;
        }
    }

    /* part III. obtain start,edge, stride and number of sds data. */
    sds_start           = malloc(sizeof(int32)*sds_rank);
    if(sds_start == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS starting array",
                __FILE__,__LINE__);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    sds_edge            = malloc(sizeof(int32)*sds_rank);
    if(sds_edge == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS edging array",
                __FILE__,__LINE__);
        free(sds_start);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    sds_stride      = malloc(sizeof(int32)*sds_rank);
    if(sds_stride == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS stride",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    count_sdsdata = 1;
    for (i=0;i<sds_rank;i++){
        sds_stride[i] = 1;
        sds_start[i]    = 0;
        sds_edge[i]     = sds_dimsizes[i];
        count_sdsdata = count_sdsdata*sds_dimsizes[i];
    }

    for (i=0;i<sds_rank;i++) {
        h5dims[i] = sds_edge[i]-sds_start[i];
        max_h5dims[i] = h5dims[i];
    }

    if(SDisrecord(sds_id)) max_h5dims[0] = H5S_UNLIMITED;

    /* Datatype conversion is done here since memory allocation size
         should be known first. */

    /* convert HDF4 data type to HDF5 data type. */
    if  (h4type_to_h5type(h4toh5_id,sds_dtype,&h5_memtype,&h4memsize,&h4size,
            &h5ty_id) == FAIL) {
        H4toH5error_set(temph4toh5id,5,
                "cannot convert HDF4 data type to HDF5 data type",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* check whether the datatype is string, if we find string format,
         we will change them back into integer format.*/
    if (h5ty_id == H5T_STRING) {

        /* rechange string datatype into numerical datatype.*/
        if(h5string_to_int(h4toh5_id,sds_dtype,&h5_memtype,h4memsize,
                     &h5ty_id)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "cannot translate H5T_STRING into int",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    sds_data = malloc(h4memsize*count_sdsdata);
    if(sds_data == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS data",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    istat        = SDreaddata(sds_id, sds_start, sds_stride, sds_edge,
            (VOIDP)sds_data);
    if (istat == FAIL)  {
        H4toH5error_set(temph4toh5id,2,
                "cannot read SDS data",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* part IV. converting SDS into hdf5 dataset. */

    h5d_sid = H5Screate_simple(sds_rank,h5dims,max_h5dims);
    if (h5d_sid < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot create HDF5 data space",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* create property list. */

    create_plist = get_chunking_plistid(h4toh5_id,sds_id);
    if(create_plist < 0) {
        H4toH5error_set(temph4toh5id,2,
                "cannot generate HDF4 chunking list ",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    if (add_fillvalue(h4toh5_id,sds_id,create_plist,h4memsize,h5_memtype) < 0) {
        H4toH5error_set(temph4toh5id,2,
                "cannot add fill value to the chunking list ",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    h5dset = H5DCREATE(h5_group,h5csds_name,h5ty_id,h5d_sid,create_plist);
    if (h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot create HDF5 dataset converted from SDS ",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        H5Sclose(h5d_sid);
        H5Pclose(create_plist);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }


    write_plist = H5Pcreate(H5P_DATASET_XFER);
    bufsize = h4memsize;
    for(i=0;i<sds_rank;i++)
        bufsize *= h5dims[i];

    if(H5Pset_buffer(write_plist,bufsize,NULL,NULL)<0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to set HDF5 buffer for property list",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        H5Sclose(h5d_sid);
        H5Pclose(create_plist);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,write_plist,
                 (void *)sds_data)<0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to write HDF5 dataset",
                __FILE__,__LINE__);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        H5Pclose(create_plist);
        H5Pclose(write_plist);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(sds_data);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }




    /*  if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,H5P_DEFAULT,
            (void *)sds_data)<0) {
            H4toH5error_set(temph4toh5id,3,
            "cannot write HDF5 dataset ",
            __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(sds_data);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
            }

    */
    free(sds_start);
    free(sds_edge);
    free(sds_stride);
    free(sds_data);
    H5Pclose(write_plist);
    if(is_valid_attr_flag(attr_flag)==0) {
        H4toH5error_set(temph4toh5id,5,
                "attribute flag is set wrong ",
                __FILE__,__LINE__);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        H5Pclose(create_plist);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(dim_flag <0 || dim_flag > 1) {
        H4toH5error_set(temph4toh5id,5,
                "dimensional flag is set wrong",
                __FILE__,__LINE__);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        H5Pclose(create_plist);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }
    /* convert sds annotation into attribute of sds dataset.
         Since there is no routines to find the exact tag of sds object,
         we will check three possible object tags of sds objects, that is:
         DFTAG_SD,DFTAG_SDG,DFTAG_NDG. If the object tag of sds object is
         falling out of this scope, we will not convert annotations into
         hdf5 attributes; it is user's responsibility to make sure object tags
         for sds objects are only one of the above three tags.*/
    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                 DFTAG_SD,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                DFTAG_SD,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                 DFTAG_SDG,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                DFTAG_SDG,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                 DFTAG_NDG,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,(uint16)sds_ref,
                DFTAG_NDG,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

    }
    /* convert sds dimensional scale dataset into hdf5 dataset. */
    /* CHECK *** why this dim_flag is called */
    if(dim_flag == H425_DIMSCALE) {
        if(attr_flag == H425_ALLATTRS || attr_flag == H425_NO_PREDEF_ATTRS || attr_flag == H425_SV) {
            if(H4toH5all_dimscale_h5ds(h4toh5_id,sds_id,h5dset,attr_flag) == FAIL){
                H4toH5error_set(temph4toh5id,5,
                                        "unable to convert all dimensional scales to HDF5 datasets",
                                        __FILE__,__LINE__);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }

        else {
            if(H4toH5all_dimscale(h4toh5_id,sds_id,h5groupname,h5dsetname,
                h5_dimgroupfullpath,attr_flag,1) == FAIL) {

                H4toH5error_set(temph4toh5id,5,
                    "unable to convert all dimensional scales to HDF5 datasets",
                    __FILE__,__LINE__);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
    }

    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        check_gloattr = 0;
        if (sds_transattrs(h4toh5_id,sds_id,h5dset,num_sdsattrs,check_gloattr,attr_flag)==FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "unable to convert SDS attributes",
                    __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        /********************************************/
        /*  handle extra attributes of sds : sds label, object type
    and reference num */

        strcpy(sdslabel,SDSLABEL);

        if(attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_ALLATTRS) {
            if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_TYPE,sdslabel)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "unable to convert SDS label to attribute",
                        __FILE__,__LINE__);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }

            if(sdsname[0] != '\0') {
                if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_NAME,sdsname)==FAIL){
                    H4toH5error_set(temph4toh5id,5,
                            "unable to convert SDS name to the attribute",
                            __FILE__,__LINE__);
                    H5Sclose(h5d_sid);
                    H5Dclose(h5dset);
                    H5Pclose(create_plist);
                    free(h5csds_name);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }

            if(h4_transnumattr(h4toh5_id,h5dset,HDF4_REF_NUM,(uint16)sds_ref)==FAIL){
                H4toH5error_set(temph4toh5id,5,
                        "unable to convert SDS reference to the attribute",
                        __FILE__,__LINE__);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                free(h5csds_name);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
    }

    ret     = H5Pclose(create_plist);
    if( ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to close HDF5 property list interface",
                __FILE__,__LINE__);
        H5Sclose(h5d_sid);
        H5Dclose(h5dset);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }
    ret     = H5Sclose(h5d_sid);
    if( ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to close HDF5 data space interface",
                __FILE__,__LINE__);
        H5Dclose(h5dset);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }
    ret     = H5Dclose(h5dset);
    if( ret < 0) {
        H4toH5error_set(temph4toh5id,3,
                "unable to close HDF5 dataset interface",
                __FILE__,__LINE__);
        free(h5csds_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(h5csds_name);
        return FAIL;
    }
    free(h5csds_name);
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5sds_attr_name
 *
 * Purpose:         translate one SDS attribute into attribute of an hdf5 dataset
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id: h4toh5 identifier
 sds_id: SDS identifier
 h5groupfullpath: hdf5 group name(must be provided)
 h5dsetname: hdf5 dataset name(can be set NULL)
 h4attrname:            hdf4 attribute name
 *-------------------------------------------------------------------------
 */
int H4toH5sds_attr_name(hid_t  h4toh5id,
            int32  sds_id,
            char*  h5groupname,
            char*  h5dsetname,
            char*  h4attrname)
{
    h4toh5id_t *temph4toh5id; /* pointer to h4toh5 id structure */
    int h4index; /* the index number of attribute to convert */

    temph4toh5id = H4TOH5I_object(h4toh5id);
    if ((h4index=SDfindattr(sds_id,h4attrname))==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to find index from the attribute name",
                __FILE__,__LINE__);
        return FAIL;
    }
    if(H4toH5sds_attr_index(h4toh5id,sds_id,h5groupname,h5dsetname,h4index)==FAIL){
        H4toH5error_set(temph4toh5id,5,"unable to convert SDS attribute",
                __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5sds_attr_index
 *
 * Purpose:         translate one SDS attribute into attribute of an hdf5 dataset
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id: h4toh5 identifier
 sds_id: SDS identifier
 h5groupfullpath: hdf5 group name(must be provided)
 h5dsetname: hdf5 dataset name(can be set NULL)
 h4index:            attribute index
 *-------------------------------------------------------------------------
 */
int H4toH5sds_attr_index(hid_t  h4toh5id,
             int32  sds_id,
             char*  h5groupname,
             char*  h5dsetname,
             int        h4index)
{
    char            ssdsattr_name[2*H4H5_MAX_NC_NAME]; /* SDS attribute name */
    char            sdsname[H4H5_MAX_NC_NAME];/* SDS name */
    char*           cor_sdsname;
    char*           sdstempattr_name; /* temporary name of SDS attribute */

    int32           count_ssdsadata; /* number of SDS attribute elements */
    uint32      temp_countadata; /* temporary number of SDS attribute elements */
    int32           ssds_atype; /* SDS attribute data type */
    int32           sds_ref; /* SDS reference number */

    int32           sds_dtype; /* SDS data type */
    int32           sds_rank; /* rank of SDS object */
    int32           sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* array of the size of each dimension
                         of SDS */
    int32           num_sdsattrs; /* number of SDS attribute */
    char            refstr[MAXREF_LENGTH]; /* string format of the reference number */

    size_t      sh4_amemsize; /* memory size of data type of the SDS attribute */
    size_t      sh4_asize; /* file size of data type of the SDS attribute */

    hid_t           h5_group;/* HDF5 group id */
    hid_t           h5dset; /* HDF5 dataset id */
    hid_t           sh5a_sid; /* data space id of HDF5 attribute
             that is converted from the SDS attribute
                    */
    hid_t           sh5a_id; /* attribute id of HDF5 that is
                        converted from the SDS attribute*/
    hid_t           sh5_atype; /* HDF5 attribute data type(in disk) */
    hid_t           sh5_amemtype; /* HDF5 attribute data type(in memory) */
    hid_t           sh5str_type; /* HDF5 attribute data type with HDF5 string
                    format(in disk)*/
    hid_t           sh5str_memtype; /* HDF5 attribute data ype with HDF5 string
                         format(in memory)*/
    char*           h5csds_name; /* The absolute path of HDF5 dataset converted
                    from SDS */
    char*           h5crepsds_name; /* The temporary name that describes the absolute
                         path of HDF5 dataset converted from SDS*/
    int*            check_lookupptr; /* pointer to pass the value of the flag that
                checks the look-up table */

    int             temp; /* temporary variable */

    hsize_t     sh5dims[1]; /* The size of the dimension for this attribute */
    void*           ssds_adata; /* data buffer that stores the SDS attribute*/
    herr_t      sret; /* the temporary variable to check the "return" status    of
                 HDF5 APIs */
    h4toh5id_t *temph4toh5id; /* a pointer to h4toh5 id */


    temp = 0;
    check_lookupptr = &temp;
    temph4toh5id = H4TOH5I_object(h4toh5id);

    /* obtain h5_group id */
    h5_group        =  get_h5groupid(h5groupname,h4toh5id,H425_OSPEC_ALLATTRS);
    if(h5_group < 0) {
        H4toH5error_set(temph4toh5id,5,
                "cannot obtain HDF5 group ID",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* obtain the hdf5  name. */
    /*obtaining reference number and name of h5 dataset
        corresponding to sds. */

    /*obtain name,rank,dimsizes,datatype and num of attributes of sds */
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get information of SDS object",
                __FILE__,__LINE__);
        H5Gclose(h5_group);
        return FAIL;
    }
    sds_ref = SDidtoref(sds_id);
    if(sds_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot obtain SDS reference number",
                __FILE__,__LINE__);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* obtain the new h5dataset name */
    if(h5dsetname == NULL) {
        /* generating two names.
             1. make up name based on HDF4_SDS,h5groupname,sds_ref.
             call this name h5replacesds_name
             2. using lookup_name to check whether this name is stored already.
             3. If yes, use this name as the h5datasetname.
             4. no, obtain name based on groupname + sds name.
        */

        /* change format of reference number. */
        if(conv_int_str(h4toh5id,(uint16)sds_ref,refstr)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "fail to convert reference number into HDF5 string ",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
        h5crepsds_name = make_objname_no(h4toh5id,refstr,h5groupname,HDF4_SDS);
        if(lookup_name(h4toh5id,h5crepsds_name,SDS_HASHSIZE,
             temph4toh5id->name_hashtab)==1){
            h5csds_name = malloc(strlen(h5crepsds_name)+1);
            if(h5csds_name == NULL) {
                H4toH5error_set(temph4toh5id,1,
                        "unable to allocate memory for HDF5 sds name ",
                        __FILE__,__LINE__);
                H5Gclose(h5_group);
                return FAIL;
            }
            strncpy(h5csds_name,h5crepsds_name,strlen(h5crepsds_name));
        }

        else {
            cor_sdsname = correct_name(h4toh5id,sdsname);
            if(cor_sdsname == NULL) {
                H4toH5error_set(temph4toh5id,5,"cannot obtain corrected sds name",
                        __FILE__,__LINE__);
                H5Gclose(h5_group);
                return FAIL;
            }
            h5csds_name = make_objname_yes(h4toh5id,cor_sdsname,h5groupname);
            free(cor_sdsname);
            if(h5csds_name == NULL) {
                H4toH5error_set(temph4toh5id,4,
                        "cannot obtain hdf5 sds name ",
                        __FILE__,__LINE__);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        free(h5crepsds_name);
    }
    else {
        h5csds_name = make_objname_yes(h4toh5id,h5dsetname,h5groupname);
        if(h5csds_name == NULL) {
            H4toH5error_set(temph4toh5id,4,
                    "cannot obtain hdf5 sds name ",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;
        }
        if(lookup_name(h4toh5id,h5csds_name,SDS_HASHSIZE,
             temph4toh5id->name_hashtab)==0){
            H4toH5error_set(temph4toh5id,4,
                    "this object name has not been set, results unexpected ",
                    __FILE__,__LINE__);
            H5Gclose(h5_group);
            free(h5csds_name);
        }
    }

    h5dset = H5DOPEN(h5_group,h5csds_name);
    if(h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "cannot open HDF5 dataset converted from SDS ",
                __FILE__,__LINE__);
        free(h5csds_name);
        H5Gclose(h5_group);
        return FAIL;
    }
    free(h5csds_name);

    if (SDattrinfo(sds_id,h4index,ssdsattr_name,&ssds_atype,
         &count_ssdsadata)==FAIL){
        H4toH5error_set(temph4toh5id,2,"cannot start SD attribute information",
                __FILE__,__LINE__);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* convert HDF4 attribute data type to HDF5 attribute data type. */

    if(h4type_to_h5type(h4toh5id,ssds_atype,&sh5_amemtype,&sh4_amemsize,
                    &sh4_asize,&sh5_atype)== FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot convert SDS attribute data type from H4 to H5",
                __FILE__,__LINE__);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* allocating memory for SDS attribute data. */
    ssds_adata = malloc(sh4_amemsize * count_ssdsadata);
    if(ssds_adata == NULL) {
        H4toH5error_set(temph4toh5id,1,"cannot allocate memory for SDS attribute data",
                __FILE__,__LINE__);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    if(SDreadattr(sds_id,h4index,(VOIDP)ssds_adata)== FAIL) {
        H4toH5error_set(temph4toh5id,2,"cannot read SDS attribute",
                __FILE__,__LINE__);
        free(ssds_adata);
        H5Dclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    /* if an attribute doesn't have a name, a default name is set. */
    if(ssdsattr_name[0] == '\0') {
        sdstempattr_name = trans_obj_name(h4toh5id,DFTAG_NDG,h4index);
        strncpy(ssdsattr_name,sdstempattr_name,sizeof(ssdsattr_name));
        free(sdstempattr_name);
    }

    /* now do attribute-transferring.
         1. deal with string data type
         2. set attribute space.
         3. get attribute name, set property list. */

    if (sh5_atype == H5T_STRING) {

        sh5a_sid = H5Screate(H5S_SCALAR);
        if (sh5a_sid < 0) {
            H4toH5error_set(temph4toh5id,3,"cannot create HDF5 attribute space",
                    __FILE__,__LINE__);
            free(ssds_adata);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        temp_countadata = count_ssdsadata;
        H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5id,(size_t)temp_countadata,
                     H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,"cannot make HDF5 string type",
                    __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            free(ssds_adata);
            return FAIL;
        }

        if ((sh5str_memtype = mkstr(h4toh5id,count_ssdsadata*sh4_amemsize,
                H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,"cannot make hdf5 memory string type",
                    __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            free(ssds_adata);
            return FAIL;
        }


        sh5a_id = H5Acreate_safe(h4toh5id,h5dset,ssdsattr_name,sh5str_type,
            sh5a_sid,H5P_DEFAULT);

        if (sh5a_id <0) {
            if (transattrs_split(h4toh5id, h5dset, ssdsattr_name, sh5a_sid, ssds_adata, count_ssdsadata) < 0) {
                H4toH5error_set(temph4toh5id,3,"cannot create hdf5 attribute id",
                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                free(ssds_adata);
                return FAIL;
            }
        }
        else if (H5Awrite(sh5a_id,sh5str_memtype,(void *)ssds_adata) < 0) {
            H4toH5error_set(temph4toh5id,3,"cannot write hdf5 attribute",
                    __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            free(ssds_adata);
            return FAIL;
        }
    }

    else {

        if(count_ssdsadata == 1) {

            sh5a_sid = H5Screate(H5S_SCALAR);
            if (sh5a_sid < 0) {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 attribute space",
                        __FILE__,__LINE__);
                free(ssds_adata);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        else {
            sh5dims[0] = count_ssdsadata;
            sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);

            if (sh5a_sid < 0)  {
                H4toH5error_set(temph4toh5id,3,"cannot create HDF5 attribute space",
                        __FILE__,__LINE__);
                free(ssds_adata);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        sh5a_id = H5Acreate_safe(h4toh5id,h5dset,ssdsattr_name,sh5_atype,
            sh5a_sid,H5P_DEFAULT);

        if(sh5a_id <0) {
            H4toH5error_set(temph4toh5id,3,"cannot create HDF5 attribute id",
                    __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            free(ssds_adata);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)ssds_adata);
        if(sret <0) {
            H4toH5error_set(temph4toh5id,3,"cannot write HDF5 attribute space",
                    __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            H5Aclose(sh5a_id);
            H5Dclose(h5dset);
            H5Gclose(h5_group);
            free(ssds_adata);
            return FAIL;
        }
    }

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

    free(ssds_adata);

    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    get_chunking_plistid
 *
 * Purpose:         get HDF5 dataset creation property list id converted from
 SDS
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5id: h4toh5 identifier
 sds_id: SDS identifier
 *-------------------------------------------------------------------------
 */
hid_t get_chunking_plistid(hid_t h4toh5id,int32 sds_id)
{
    HDF_CHUNK_DEF c_def_out; /* HDF4 chunking defination struct */
    hsize_t*    chunk_dims; /* chunking dimensions */
    int32       c_flags; /* flag to set for chunking */
    int  i; /* index of for loop */
    hid_t create_plist;/* property list id to handle chunking info */
    int32       sds_dtype; /* SDS data type id */
    int32       sds_ref;     /* SDS reference number */
    int32       sds_rank; /* the rank of SDS dimension */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS];/* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */
    char        sdsname[H4H5_MAX_NC_NAME];/* SDS name */
    h4toh5id_t *temph4toh5id; /* a pointer to h4toh5 id*/

    /* for checking compression */
    int32                       file_id;
    comp_coder_t        comp_coder_type;
    comp_info                    c_info;
    int                         szip_pixels_per_block;
    int                         options_mask;

    c_flags = -1;
    comp_coder_type = COMP_CODE_NONE;
    temph4toh5id = H4TOH5I_object(h4toh5id);
    file_id = temph4toh5id->file_id;

    /*obtaining reference number and name of h5 dataset
        corresponding to sds. */

    sds_ref = SDidtoref(sds_id);
    if(sds_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot obtain SDS reference number",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* It turned out that SDgetchunkinfo() returns FAIL if an SDS has unlimited dimension.
     * If an SDS has unlimited dimension, that SDS cannot be chunked; so, SDgetchunkinfo()
     * can be skipped.
     */
    if (SDisrecord(sds_id)) {
        c_flags = HDF_NONE;
        /* c_def_out is used only when c_flags has HDF_CHUNK flag. */
    }
    else {
        /*check whether the SDS is created with unlimited dimension. */
        if(SDgetchunkinfo(sds_id,&c_def_out, &c_flags)== FAIL) {
            H4toH5error_set(temph4toh5id,2,
                    "unable to obtain SDS chunking information",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }

    /*obtain name,rank,dimsizes,datatype and num of attributes of sds */
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get SDS information",
                __FILE__,__LINE__);
        return FAIL;
    }

    if (SDgetcompinfo(sds_id, &comp_coder_type, &c_info) == FAIL) {
            H4toH5error_set(temph4toh5id, 3,
                    "unable to get compress information for property list",
                    __FILE__, __LINE__);
            return FAIL;
    }

    /* create property list. */
    create_plist = H5Pcreate(H5P_DATASET_CREATE);
    if(create_plist == -1) {
        H4toH5error_set(temph4toh5id,3,
                "unable to create property list",
                __FILE__,__LINE__);
        return FAIL;
    }
    chunk_dims   = malloc(sizeof(hsize_t)*sds_rank);

    if(chunk_dims == NULL) {
        H5Pclose(create_plist);
        H4toH5error_set(temph4toh5id,1,
                "unable to allocate memory for chunk_dims",
                __FILE__,__LINE__);
        return FAIL;
    }

    unsigned short use_chunk = 0;
    if(c_flags == HDF_NONE) {

        /*HDF5 requires the use of chunks for unlimited dimension array */
        if(SDisrecord(sds_id)) {
            int remains = H4H5_DEFAULT_NUMELEM_IN_CHUNK;
            for(i=0;i<sds_rank;i++) {
                chunk_dims[i] = (hsize_t)(sds_dimsizes[i]);
                if (chunk_dims[i])
                    remains /= chunk_dims[i];
            }
            if (remains == 0)
                remains = 1;

            /* chunk_dims[i] can be zero, but HDF5 does not allow zero. */
            for (i = 0; i < sds_rank; ++i) {
                if (chunk_dims[i] == 0)
                    chunk_dims[i] = remains;
            }
            use_chunk = 1;
        }
        /*HDF5 requires the use of chunks for compressed dataset */
        else if(comp_coder_type != COMP_CODE_NONE) {
            for(i=0;i<sds_rank;i++){
                chunk_dims[i] = (hsize_t)(sds_dimsizes[i]);
            }
            use_chunk = 1;
        }
    }
    else {/*Need to keep chunking storage anyway */
        use_chunk = 1;
        for(i=0;i<sds_rank;i++){
            chunk_dims[i] = (hsize_t)c_def_out.chunk_lengths[i];
            if (chunk_dims[i] > sds_dimsizes[i])
                chunk_dims[i] = sds_dimsizes[i];
        }
    }

    /* Set up chunking storage */
    if(use_chunk == 1) {
        if(H5Pset_chunk(create_plist, sds_rank, chunk_dims)<0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to set chunk property list",
                    __FILE__,__LINE__);
            free(chunk_dims);
            H5Pclose(create_plist);
            return FAIL;
        }
    }
    free(chunk_dims);

    /* HDF4 can support various compression methods including simple RLE, NBIT, Skip Huffman, gzip,Jpeg , HDF5 currently only supports gzip  and szip compressions.
         By default, we will compress HDF5 dataset by using gzip compression if HDF5 file is compressed with
         compression methods besides szip and gzip.  Otherwise, we will keep the compression
         pattern when doing 4 to 5 conversion. Such as, gzip to gzip, szip to szip.
         Users should report their requests to hdfhelp@hdfgroup.org if they want to have another options
         to choose for compression, for example, szip in 4 and gzip in 5 etc. Also, shuffling algo. can
         be used with gzip compression to improve compression ratio for strong locality data. Users can
         also try their data with this in their custom conversion. We won't support due to funding limitations.
         April 6th, 2004, KY*/



    if(comp_coder_type == COMP_CODE_RLE || comp_coder_type == COMP_CODE_NBIT
         || comp_coder_type == COMP_CODE_SKPHUFF || comp_coder_type == COMP_CODE_DEFLATE) {

        /* Detect if gzip filter is present in HDF5. */
        if(H5Zfilter_avail(H5Z_FILTER_DEFLATE) != 1) {
                    fprintf(stderr, "Deflate filter is not available in HDF5.  Writing without compression.\n");
        }
        else{

            unsigned int deflate_level = H4H5_GZIP_COMLEVEL;
            if(comp_coder_type == COMP_CODE_DEFLATE)
                deflate_level =  c_info.deflate.level;

            if(H5Pset_deflate(create_plist,deflate_level)<0){
                    H4toH5error_set(temph4toh5id,3,
                        "unable to set deflate compression",
                __FILE__,__LINE__);
                H5Pclose(create_plist);
                return FAIL;
            }
        }
    }

    else if(comp_coder_type == COMP_CODE_SZIP){
        /* Detect if szip filter is present and able to encode in HDF5. */
        if(H5Zfilter_avail(H5Z_FILTER_SZIP) != 1)
        {
            fprintf(stderr, "szip filter is not available in HDF5.  Writing without compression.\n");
        }
        else
        {
            unsigned int filter_config;
            /* SZIP is present.  Is it configured to be able to encode? */
            if(H5Zget_filter_info(H5Z_FILTER_SZIP, &filter_config) < 0)
            {
                H4toH5error_set(temph4toh5id,2,"unable to get HDF5 szip filter information",__FILE__,__LINE__);
                H5Pclose(create_plist);
                return FAIL;
            }

            if(! (filter_config & H5Z_FILTER_CONFIG_ENCODE_ENABLED))
            {
                             fprintf(stderr, "szip configured without encoder in HDF5.  Writing without compression.\n");
            }
            else
            {
                szip_pixels_per_block = c_info.szip.pixels_per_block;
                options_mask = c_info.szip.options_mask;

                if(H5Pset_szip(create_plist,options_mask,szip_pixels_per_block)<0) {
                                H4toH5error_set(temph4toh5id,3,
                             "unable to set up data creation property list for szip",
                             __FILE__,__LINE__);
                                H5Pclose(create_plist);
                                return FAIL;
                }
            }
        }
    }


    return create_plist;
}

/*-------------------------------------------------------------------------
 * Function:    get_dimchunking_plistid
 *
 * Purpose:         get HDF5 dataset creation property list id converted from
 SDS dimensional scale dataset

 We assume that dimensional data is not compressed.
 8/7/2002, Kent Yang
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5id: h4toh5 identifier
 sds_id: SDS identifier
 *-------------------------------------------------------------------------
 */
hid_t get_dimchunking_plistid(hid_t h4toh5id,
                        int32 sds_id,
                        int32 sdsdim_id,
                        int dim_index,
                                                            int32 sds_firstsize)
{
    HDF_CHUNK_DEF c_def_out; /* HDF4 chunking defination struct */
    hsize_t             h5dim_chunkdim[1];/* chunking dimensions for dim. scale*/
    int32                   c_flags;    /* flag to set for chunking */
    hid_t                   create_plist; /* property list id to handle chunking info */
    int32                   sdsdim_type; /* SDS data type id */
    int32                   sds_dimscasize[1]; /* SDS dimensional scale size */
    int32                   num_sdsdimattrs; /* number of SDS dim. scale attributes */
    char                    sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dim. scale name */
    int32                       istat; /* a temporary variable to check the "return"
                    status of HDF4 interfaces */
    h4toh5id_t *temph4toh5id; /* a pointer to h4toh5 id*/

    temph4toh5id = H4TOH5I_object(h4toh5id);

    /* SDgetchunkinfo() may fail if this SDS has unlimited dimension. */
    if (SDisrecord(sds_id)) {
        c_flags = HDF_NONE;
        /* c_def_out is not accessed as long as this SDS does not have unlimited dimension. */
    }
    else {
        /*check whether the SDS is created with unlimited dimension. */
        if(SDgetchunkinfo(sds_id,&c_def_out, &c_flags)== FAIL) {
            H4toH5error_set(temph4toh5id,2,
                    "unable to obtain SDS chunking information",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }

    istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                &sdsdim_type,&num_sdsdimattrs);

    if (istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get SDS dimensional scale information",
                __FILE__,__LINE__);
        return FAIL;
    }
    /* create property list. */
    create_plist = H5Pcreate(H5P_DATASET_CREATE);
    if(create_plist == -1) {
        H4toH5error_set(temph4toh5id,2,
                "fail to create HDF5 property list",
                __FILE__,__LINE__);
        return FAIL;
    }
    /* Since only the unlimited dimensional scale needs to be chunked.
         So chunking information for dimensional scale
         is only considered when the dimension rank is the first dimension and the
         first dimension is unlimited. */

    if(c_flags == HDF_NONE && SDisrecord(sds_id) && dim_index == 0)
    {
        if(sds_dimscasize[0]==0)
            h5dim_chunkdim[0] = (hsize_t)sds_firstsize;
        else
            h5dim_chunkdim[0] = (hsize_t)(sds_dimscasize[0]);

        /* When chunk size is too small, the overhead grows, so we make
                 the default chunk size to be 512. It may still be too small. KY 2014-05-28*/

/*#if 0*/
        if(h5dim_chunkdim[0] < H4H5_DEFAULT_NUMELEM_IN_CHUNK)
            h5dim_chunkdim[0] = H4H5_DEFAULT_NUMELEM_IN_CHUNK;
/*#endif */

        if(H5Pset_chunk(create_plist,1, h5dim_chunkdim)<0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to set property list for chunking",
                    __FILE__,__LINE__);
            H5Pclose(create_plist);
            return FAIL;
        }
    }

    if(c_flags == HDF_CHUNK || c_flags == (HDF_CHUNK | HDF_COMP)
         || c_flags == (HDF_CHUNK | HDF_NBIT)  ){

        h5dim_chunkdim[0] = (hsize_t)c_def_out.chunk_lengths[0];

        if(H5Pset_chunk(create_plist,1, h5dim_chunkdim)<0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to set property list for chunking",
                    __FILE__,__LINE__);
            H5Pclose(create_plist);
            return FAIL;
        }
    }

    return create_plist;
}

/**
 * @brief create DIMENSION_LIST in dataset
 *
 * @param did dataset identifier
 * @param h4toh5id h4toh5 identifier
 * @param count_h5objref number of dimensions
 * @param h5sdsdim_allname list of dimension names
 * @param sh5_dimgroup HDF5 group where this dimension scale belongs to
 * @param dimempty list of flags that show if each dimension is empty
 *
 * @return FAIL if failed, SUCCEED if successful
 */
int write_dimscale_attribute(hid_t did, hid_t h4toh5id, int count_h5objref, const char h5sdsdim_allname[], hid_t sh5_dimgroup, int dimempty[])
{
    hvl_t *dimrefs = NULL;
    hid_t spaceid = FAIL;
    hid_t tvlenid = FAIL;
    hid_t tid = FAIL;
    hid_t attrid = FAIL;
    int succeeded = 0;

    do {
        hsize_t spacedimsizes[1];
        int i;

        spacedimsizes[0] = count_h5objref;
        if (count_h5objref) {
            int failinside = 0;
            /* XXX: The specification states the following.
             *   DIMENSION_LIST is a two dimensional array with one row for each dimension of the Dataset,
             *   and a variable number of entries in each row, one for each associated scale.
             * However, the caller does not consider multiple dimension scales for one dimension.
             */
            if ((spaceid = H5Screate_simple(1, spacedimsizes, NULL)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Screate_simple"); break; }
            /* XXX: I think the specification differs from the implementation. Both netCDF4 and H5DS
             * implementation uses VLEN of hobj_ref_t as datatype, and I follow this.
             */
            if ((tid = H5Tvlen_create(H5T_STD_REF_OBJ)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tvlen_create failure"); break; }

            if ((dimrefs = malloc(count_h5objref * sizeof(hvl_t))) == NULL) { H4TOH5ERROR_NOMEM1("dim ref vl type"); break; }
            for (i = 0; i < count_h5objref; ++i) {
                hobj_ref_t ref;
                if (dimempty[i]) continue;
                if (H5Rcreate(&ref, sh5_dimgroup, &h5sdsdim_allname[i * H4H5_MAX_DIM_NAME], H5R_OBJECT, -1) == FAIL) { H4TOH5ERROR_SET1(3, "HDF5 reference"); failinside = 1; break; }
                if ((dimrefs[i].p = malloc(sizeof(hobj_ref_t))) == NULL) { H4TOH5ERROR_NOMEM1("dim ref vl[i].p"); failinside = 1; break; }
                *((hobj_ref_t *)dimrefs[i].p) = ref;
                dimrefs[i].len = 1;
            }
            if (failinside) break;

            /* This routine will not be called more than once for each dataset. Checking if this dataset already contains the attribute is not required */
            if ((attrid = H5ACREATE(did, HDF5_DIMENSION_LIST, tid, spaceid, H5P_DEFAULT)) == FAIL) { H4TOH5ERROR_SET1(3, "dataset attribute"); break; }
            if (H5Awrite(attrid, tid, dimrefs) == FAIL) { H4TOH5ERROR_SET1(3, "write dataset attribute"); break; }
        }
        succeeded = 1;
    } while (0);

    if (1) {
        if (spaceid != FAIL) H5Sclose(spaceid);
        if (tvlenid != FAIL) H5Tclose(tvlenid);
        if (tid != FAIL) H5Tclose(tid);
        if (attrid != FAIL) H5Aclose(attrid);
        if (dimrefs != NULL) free(dimrefs);
    }
    return succeeded ? SUCCEED : FAIL;
}

/**
* @brief corresponding type of "Dataset Reference Type"
*/
typedef struct {
    hobj_ref_t ref;
    int32 index;
} reference_backpointer_t;

/**
 * @brief create or append REFERENCE_LIST to dimension scale dataset
 *
 * @param did identifier of dataset that refers to dimension scale
 * @param dsid identifier of dimension scale dataset referred to by @did
 * @param h4toh5id h4toh5 identifier
 * @param dref reference number of dataset that refers to dimension scale
 * @param dindex dimension index where this dimension scale is used
 *
 * @return FAIL if failed, SUCCEED if successful
 */
int write_dimscaledataset_ref_attribute(hid_t did, hid_t dsid, hid_t h4toh5id, hobj_ref_t dref, int dindex)
{
    hid_t spaceid = FAIL;
    hid_t oldspaceid = FAIL;
    hid_t tid = FAIL;
    hid_t attrid = FAIL;
    reference_backpointer_t *refs = NULL;
    int succeeded = 0;

    do {
        hssize_t numelems;
        hsize_t dimsize;

        /* If "REFERENCE_LIST" is already there, one element should be appended. It seems that appending
         * is not supported. To handle this, append in the memory first, and then remove and recreate the attribute
         */
        H5E_BEGIN_TRY {
            attrid = H5Aopen_name(dsid, HDF5_REFERENCE_LIST);
        } H5E_END_TRY;
        if (attrid != FAIL) {
            /* REFERENCE_LIST exists in ds dataset */
            if ((tid = H5Aget_type(attrid)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Aget_type"); break; }
            if ((oldspaceid = H5Aget_space(attrid)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Aget_space"); break; }
            if ((numelems = H5Sget_simple_extent_npoints(oldspaceid)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Sget_simple_extent_npoints"); break; }
            numelems++;
            if ((refs = malloc(numelems * sizeof(reference_backpointer_t))) == NULL) { H4TOH5ERROR_NOMEM1("reference_backpointer_t"); break; }
            if (H5Aread(attrid, tid, refs) == FAIL) { H4TOH5ERROR_SET1(3, "H5Aread"); break; }
            if (H5Adelete(dsid, HDF5_REFERENCE_LIST) == FAIL) { H4TOH5ERROR_SET1(3, "H5Adelete"); break; }
        }
        else {
            numelems = 1;
            if ((refs = malloc(numelems * sizeof(reference_backpointer_t))) == NULL) { H4TOH5ERROR_NOMEM1("reference_backpointer_t 1"); break; }
        }
        refs[numelems - 1].ref = dref;
        refs[numelems - 1].index = dindex;

        dimsize = numelems;
        if ((spaceid = H5Screate_simple(1, &dimsize, NULL)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Screate_simple"); break; }
        if (tid == FAIL) {
            if ((tid = H5Tcreate(H5T_COMPOUND, sizeof(reference_backpointer_t))) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tcreate"); break; }
            if (H5Tinsert(tid, "dataset", HOFFSET(reference_backpointer_t, ref), H5T_STD_REF_OBJ) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tinsert DATASET"); break; }
            if (H5Tinsert(tid, "index", HOFFSET(reference_backpointer_t, index), H5T_NATIVE_INT) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tinsert INDEX"); break; }
        }

        if ((attrid = H5ACREATE(dsid, HDF5_REFERENCE_LIST, tid, spaceid, H5P_DEFAULT)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Acreate"); break; }
        if (H5Awrite(attrid, tid, refs) == FAIL) { H4TOH5ERROR_SET1(3, "write dimension scale data set attribute"); break; }

        succeeded = 1;
    } while (0);

    if (1) {
        if (refs != NULL) free(refs);
        if (attrid != FAIL) H5Aclose(attrid);
        if (tid != FAIL) H5Tclose(tid);
        if (oldspaceid != FAIL) H5Sclose(oldspaceid);
        if (spaceid != FAIL) H5Sclose(spaceid);
    }
    return succeeded ? SUCCEED : FAIL;
}

/**
 * @brief try to write an attribute to dimension scale dataset
 *
 * @param dsid identifier of dimension scale dataset
 * @param h4toh5id h4toh5 identifier
 * @param attrname attribute name
 * @param attrvalue attribute value
 *
 * @return FAIL if failed, SUCCEED if successful
 */
int write_dimscaledataset_attribute(hid_t dsid, hid_t h4toh5id, const char *attrname, const char *attrvalue)
{
    hid_t spaceid = FAIL;
    hid_t tid = FAIL;
    hid_t attrid = FAIL;
    int succeeded = 0;

    do {
        hsize_t dimsize[1] = { 1 };

        /* if the attribute is there, do not touch */
        H5E_BEGIN_TRY {
            attrid = H5Aopen_name(dsid, attrname);
        } H5E_END_TRY;
        if (attrid == FAIL) {
            if ((spaceid = H5Screate_simple(1, dimsize, NULL)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Screate_simple failure"); break; }
            if ((tid = H5Tcopy(H5T_C_S1)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tcopy"); break; }
            if (H5Tset_size(tid, strlen(attrvalue)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Tset_size"); break; }
            if ((attrid = H5Acreate_safe(h4toh5id, dsid, attrname, tid, spaceid, H5P_DEFAULT)) == FAIL) { H4TOH5ERROR_SET1(3, "H5Acreate"); break; }
            if (H5Awrite(attrid, tid, attrvalue) == FAIL) { H4TOH5ERROR_SET1(3, "write dimension attr 'CLASS' fails"); break; }
        }

        succeeded = 1;
    } while (0);

    if (1) {
        if (attrid != FAIL) H5Aclose(attrid);
        if (tid != FAIL) H5Tclose(tid);
        if (spaceid != FAIL) H5Sclose(spaceid);
    }
    return succeeded ? SUCCEED : FAIL;
}

/**
 * @brief write proper attributes to a dataset and dimension scale datasets that the dataset refers to
 *
 * This is similar to H5DSattach_scale.
 *
 * @param h4toh5id h4toh5 identifier
 * @param did identifier of dataset that refers to dimension scales
 * @param count_h5objref number of dimension scales in @did
 * @param h5sdsdim_allname list of dimension scale names in @did
 * @param sh5_dimgroup HDF5 group where dimension scales belong to
 * @param h5sdsname actual name of HDF5 dataset corresponding to @did
 * @param h5_dgroup HDF5 group where @did belongs to
 * @param dimempty list of flags saying whether or not each dimension is empty
 *
 * @return FAIL if failed, SUCCEED if successful
 */
int attach_allscales(hid_t h4toh5id, hid_t did, int count_h5objref, const char h5sdsdim_allname[], hid_t sh5_dimgroup, const char *h5sdsname, hid_t h5_dgroup, int dimempty[])
{
    int succeeded = 0;

    do {
        hobj_ref_t dref;
        int i =0;
        int failinside = 0;

        /* The following attributes are part of HDF5 specification, but they were added only for
         * netCDF4 support so that netCDF4 can recognize dimensional scale. For this reason,
         * they are written only when netcdf4_hack options is set
         */
        if (H4toH5config_use_netcdf4_hack()) {
            /* dataset: DIMENSION_LIST */
            if (write_dimscale_attribute(did, h4toh5id, count_h5objref, h5sdsdim_allname, sh5_dimgroup, dimempty) == FAIL) { H4TOH5ERROR_SET0(3); break; }

            /* dimension scale dataset: REFERENCE_LIST, CLASS, NAME */
            if (H5Rcreate(&dref, h5_dgroup, h5sdsname, H5R_OBJECT, -1) == FAIL) { H4TOH5ERROR_SET1(3, "HDF5 reference"); break; }
            for (i = 0; i < count_h5objref; ++i) {
                hid_t dsid;
                if ((dsid = H5DOPEN(sh5_dimgroup, &h5sdsdim_allname[i * H4H5_MAX_DIM_NAME])) == FAIL) { H4TOH5ERROR_SET0(3); failinside = 1; break; }
                if (write_dimscaledataset_ref_attribute(did, dsid, h4toh5id, dref, i) == FAIL) { H4TOH5ERROR_SET0(3); failinside = 1; break; }
                if (write_dimscaledataset_attribute(dsid, h4toh5id, HDF5_DIMENSION_SCALE_CLASS, "DIMENSION_SCALE") == FAIL) { H4TOH5ERROR_SET0(3); failinside = 1; break; }
                if (write_dimscaledataset_attribute(dsid, h4toh5id, HDF5_DIMENSION_SCALE_NAME, "This is a netCDF dimension but not a netCDF variable.") == FAIL) { H4TOH5ERROR_SET0(3); failinside = 1; break; }
                H5Dclose(dsid);
            }
            if (failinside) break;
        }

        succeeded = 1;
    } while (0);

    return succeeded ? SUCCEED : FAIL;
}

/*-------------------------------------------------------------------------
 * Function:    store_objref
 *
 * Purpose:         store object references as attributes of an HDF5 dataset,
 these object references will connect the HDF5 dataset to
 HDF5 datasets converted from dimensional scale datasets.
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5id                    : h4toh5 identifier
 count_h5objref      : number of HDF5 object reference
 h5sdsdim_allname[]: character array that includes
 all dimensional scale names
 sh5_dimgroup            : dimensional scale group id of HDF5
 h5_dset                     : ID of HDF5 dataset where object references
 are stored as attributes
 dimempty                    : array to store the information
 of each dimension; 1 if this dimension is
 empty, 0 if not.

 *-------------------------------------------------------------------------
 */
int store_objref(hid_t h4toh5_id,
         int count_h5objref,
         char h5sdsdim_allname[],
         hid_t sh5_dimgroup,
         hid_t h5_dset,
         int dimempty[])
{

    char                h5newsdsdim_name[H4H5_MAX_DIM_NAME]; /* SDS dimensional scale name */
    hobj_ref_t  dim_refdat; /* object reference structure for reference from the
                     dataset to dim. scale */
    hobj_ref_t* alldim_refdat; /* all object references from the dataset
                to dim. scales */
    hid_t               attr_refSpace; /*reference space id */
    hid_t               attr_refType; /* reference datatype id */
    hid_t               attribID; /* HDF5 attribute id */
    int                 i,k; /* temporary variable to handle for loop and count */
    hsize_t         attr_refDims[1]; /* size of the "dimensional scale" attribute */
    herr_t          ret; /* the temporary variable to check the "return" status  of
                    HDF5 APIs */
    h4toh5id_t *temph4toh5id; /* a pointer to h4toh5 id*/

    /* it seems that netCDF4 cannot recognize REFERENCE type, and it raises error. */
    if (H4toH5config_use_netcdf4_hack())
        return SUCCEED;

    temph4toh5id = H4TOH5I_object(h4toh5_id);

    k = 0;
    if(count_h5objref != 0) {
        /* generating HDF5 object reference count */
        attr_refDims[0] = count_h5objref;
        attr_refSpace       = H5Screate_simple(1,attr_refDims,NULL);
        attr_refType        = H5Tcopy(H5T_STD_REF_OBJ);
        alldim_refdat       = calloc((size_t)count_h5objref,sizeof(hobj_ref_t));
        if(alldim_refdat == NULL) {
            H4toH5error_set(temph4toh5id,1,
                    "unable to allocate memory for object reference data",
                    __FILE__,__LINE__);
            H5Sclose(attr_refSpace);
            H5Tclose(attr_refType);
            return FAIL;
        }

        for(i=0;i<count_h5objref;i++){
            if(dimempty[k])
                k = k +1; /* no object reference is made. */
            h4toh5_ZeroMemory(h5newsdsdim_name,H4H5_MAX_DIM_NAME);
            strcpy(h5newsdsdim_name,&h5sdsdim_allname[k*H4H5_MAX_DIM_NAME]);
            ret                          = H5Rcreate(&dim_refdat,sh5_dimgroup,h5newsdsdim_name, H5R_OBJECT,-1);
            if(ret <0) {
                H4toH5error_set(temph4toh5id,3,
                        "unable to generate HDF5 reference",
                        __FILE__,__LINE__);
                free(alldim_refdat);
                H5Sclose(attr_refSpace);
                H5Tclose(attr_refType);
                return FAIL;
            }
            alldim_refdat[i] = dim_refdat;
            k = k + 1;
        }

        attribID            = H5ACREATE(h5_dset,HDF5_DIMENSION_LIST,attr_refType,attr_refSpace,
                        H5P_DEFAULT);
        if(attribID < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to create HDF5 object reference attribute ID ",
                    __FILE__,__LINE__);
            free(alldim_refdat);
            H5Sclose(attr_refSpace);
            H5Tclose(attr_refType);
            return FAIL;
        }

        ret                     = H5Awrite(attribID,attr_refType,(void *)alldim_refdat);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to write HDF5 object reference attribute ID ",
                    __FILE__,__LINE__);
            free(alldim_refdat);
            H5Sclose(attr_refSpace);
            H5Tclose(attr_refType);
            return FAIL;
        }

        ret = H5Sclose(attr_refSpace);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to close HDF5 dataspace ID ",
                    __FILE__,__LINE__);
            free(alldim_refdat);
            H5Tclose(attr_refType);
            H5Aclose(attribID);
            return FAIL;
        }

        ret = H5Tclose(attr_refType);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to close HDF5 data type ID ",
                    __FILE__,__LINE__);
            free(alldim_refdat);
            H5Aclose(attribID);
            return FAIL;
        }

        ret = H5Aclose(attribID);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to close HDF5 attribute ID ",
                    __FILE__,__LINE__);
            free(alldim_refdat);
            return FAIL;
        }
        free(alldim_refdat);

    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    store_attrname
 *
 * Purpose:         store dimensional scale names  as attributes of the
 HDF5 dataset,

 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5id: h4toh5 identifier
 count_h5attrname: number of dimensions that have user-defined
 attribute name
 h5sdsdim_allname: character array that stores all dimensional
 scale names
 h5_dset: HDF5 dataset where dimensional scale names are stored
 as attributes.
 *-------------------------------------------------------------------------
 */
int store_attrname(hid_t h4toh5id,
             int count_h5attrname,
             char h5sdsdim_allname[],
             hid_t h5_dset)
{
    hid_t       h5str_dimntype; /* each dimensional scale name is stored as a HDF5
                     string */
    hid_t       h5dim_nameaid; /*The attribute id to store dimensional scale names */
    hid_t       h5dim_namesid; /* The data space id of the HDF5 "dimensional scale"
                    name attribute */
    hsize_t h5dim_dims[1]; /* The size of the dimension of the HDF5
                    "dimensional scale" name attribute */
    hid_t       ret; /* the temporary variable to check the "return" status  of
            HDF5 APIs */

    h4toh5id_t *temph4toh5id; /* a pointer to h4toh5 id*/

    temph4toh5id = H4TOH5I_object(h4toh5id);

    if (H4toH5config_use_netcdf4_hack())
        return SUCCEED;

    if(count_h5attrname!= 0) {

        h5dim_dims[0]        = count_h5attrname;

        h5dim_namesid        = H5Screate_simple(1,h5dim_dims,NULL);
        if(h5dim_namesid <0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to create SDS dimensionalist space",
                    __FILE__,__LINE__);
            return FAIL;
        }

        h5str_dimntype   = mkstr(h4toh5id,H4H5_MAX_DIM_NAME,H5T_STR_NULLTERM);
        if(h5str_dimntype < 0) {
            H5Sclose(h5dim_namesid);
            H4toH5error_set(temph4toh5id,3,
                    "unable to make HDF5 string data type",
                    __FILE__,__LINE__);
            return FAIL;
        }

        h5dim_nameaid        = H5ACREATE(h5_dset,HDF4_DIMENSION_NAMELIST,h5str_dimntype,
                 h5dim_namesid,H5P_DEFAULT);
        if(h5dim_nameaid <0) {
            H5Sclose(h5dim_namesid);
            H4toH5error_set(temph4toh5id,3,
                    "unable to create HDF5 dimensional scale name attributes",
                    __FILE__,__LINE__);
            return FAIL;
        }

        ret = H5Awrite(h5dim_nameaid,h5str_dimntype,h5sdsdim_allname);
        if(ret < 0) {
            H5Sclose(h5dim_namesid);
            H5Aclose(h5dim_nameaid);
            H4toH5error_set(temph4toh5id,3,
                    "unable to write HDF5 dimensional scale name attributes",
                    __FILE__,__LINE__);
            return FAIL;
        }

        ret = H5Sclose(h5dim_namesid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to close HDF5 dimensional scale name attribute space",
                    __FILE__,__LINE__);
            H5Aclose(h5dim_nameaid);
            return FAIL;
        }
        ret = H5Aclose(h5dim_nameaid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to close HDF5 dimensional scale name attribute interface",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    convert_sds_fillvalue_or_nodim_data
 *
 * Purpose:         Convert SDS fill values to fill values of HDF5 datasets

 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id: h4toh5 identifier
 sds_id:        SDS id
 h5_group:  HDF5 group id
 h5groupname: absolute path of HDF5 group
 h5dsetname: HDF5 dataset name
 dim_flag:  Seem an oboselte flag(always H425_DIMSCALE)
 attr_flag:  attribute flag
 is_for_nodim_data: The flag to indicate if this function is for special SDS dimension handling.
 Note: redundence among h5_group,h5groupname and h5dsetname is for annotation
 conversion, just leave it for convenience.
 Since fill value implementation method will be changed in HDF5, we will
 leave this function open here without adding more comments.
 *-------------------------------------------------------------------------
 */

int convert_sds_fillvalue_or_nodim_data(hid_t h4toh5_id,
             int32 sds_id,
             hid_t h5_group,
             char* h5groupname,
             char* h5dsetname,
             char* h5csds_name,
             char* h5_dimgroupfullpath,
             int dim_flag,
             int attr_flag,
             uint8 is_for_nodim_data)
{
    int32       sds_dtype;
    int32       sds_rank;
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS];
    int32*  sds_start;
    int32*  sds_edge;
    int32*  sds_stride;
    int32       count_sdsdata;
    int32       sds_ref;
    int32       num_sdsattrs;
    void*       fill_value;
    int         i;
    int         check_gloattr;

    char        sdsname[H4H5_MAX_NC_NAME];
    char        sdslabel[H4H5_MAX_NC_NAME];
    size_t  h4size;
    size_t  h4memsize;
    hsize_t*    chunk_dims;

    /* define varibles for hdf5. */

    hid_t       h5dset;
    hid_t       h5d_sid;
    hid_t       h5ty_id;
    hid_t       h5_memtype;
    hid_t       create_plist;
    hsize_t h5dims[H4H5_MAX_VAR_DIMS];
    hsize_t max_h5dims[H4H5_MAX_VAR_DIMS];

    /* define h4toh5 temporary variable. */
    h4toh5id_t* temph4toh5id;

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

    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get information of SDS object",
                __FILE__,__LINE__);
        return FAIL;
    }


    /* obtain start,edge, stride and number of sds data. */

    sds_start           = malloc(sizeof(int32)*sds_rank);
    if(sds_start == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS starting array",
                __FILE__,__LINE__);
        return FAIL;
    }

    sds_edge            = malloc(sizeof(int32)*sds_rank);
    if(sds_edge == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS edging array",
                __FILE__,__LINE__);
        free(sds_start);
        return FAIL;
    }

    sds_stride      = malloc(sizeof(int32)*sds_rank);
    if(sds_stride == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS stride",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        return FAIL;
    }

    count_sdsdata = 1;
    for (i=0;i<sds_rank;i++){
        sds_stride[i] = 1;
        sds_start[i]    = 0;
        sds_edge[i]     = sds_dimsizes[i];
        count_sdsdata = count_sdsdata*sds_dimsizes[i];

    }
    for (i=0;i<sds_rank;i++) {
        h5dims[i] = sds_edge[i]-sds_start[i];
        max_h5dims[i] = h5dims[i];
    }

    if(SDisrecord(sds_id)) {
        max_h5dims[0] = H5S_UNLIMITED;
    }
    /* convert HDF4 data type to hdf5 data type. */
    if  (h4type_to_h5type(h4toh5_id,sds_dtype,&h5_memtype,&h4memsize,&h4size,
            &h5ty_id) == FAIL) {
        H4toH5error_set(temph4toh5id,5,
                "cannot convert HDF4 data type to HDF5 data type",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        return FAIL;
    }

    /* check whether the datatype is string, if we find string format,
         we will change them back into integer format.*/

    if (h5ty_id == H5T_STRING) {
        /* rechange string datatype into numerical datatype.*/
        if(h5string_to_int(h4toh5_id,sds_dtype,&h5_memtype,h4memsize,
                     &h5ty_id)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "cannot translate H5T_STRING into int",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            return FAIL;
        }
    }

    fill_value = malloc(h4memsize);
    h4toh5_ZeroMemory(fill_value,h4memsize*sizeof(char));
    if(num_sdsattrs != 0)
        if(SDgetfillvalue(sds_id,fill_value)==FAIL);
    /*printf("unable to get fill value, fill value will be set to zero \n");*/

    sds_ref = SDidtoref(sds_id);
    if(sds_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot obtain SDS reference number",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(fill_value);
        return FAIL;
    }

    h5d_sid = H5Screate_simple(sds_rank,h5dims,max_h5dims);
    if (h5d_sid < 0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 data space converted from SDS",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(fill_value);
        return FAIL;
    }

    /* set creation property list. */
    create_plist = H5Pcreate(H5P_DATASET_CREATE);
    if(create_plist <0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 property list",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(fill_value);
        return FAIL;
    }

    chunk_dims   = malloc(sizeof(hsize_t)*sds_rank);

    if(chunk_dims == NULL) {
        H5Pclose(H5P_DATASET_CREATE);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(fill_value);
        H4toH5error_set(temph4toh5id,1,
                "unable to allocate memory for chunk_dims",
                __FILE__,__LINE__);
        return FAIL;
    }

    if(SDisrecord(sds_id)){
        for(i=0;i<sds_rank;i++){
            chunk_dims[i] = (hsize_t)(sds_dimsizes[i]/2);
        }
        if(H5Pset_chunk(create_plist, sds_rank, chunk_dims)<0) {
            H4toH5error_set(temph4toh5id,3,
                    "unable to set HDF5 chunking property list",
                    __FILE__,__LINE__);
            free(chunk_dims);
            H5Pclose(create_plist);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(fill_value);
            return FAIL;
        }
    }
    if(H5Pset_fill_value(create_plist,h5_memtype,fill_value)<0){
        H4toH5error_set(temph4toh5id,3,
                "unable to set HDF5 chunking property list",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(chunk_dims);
        free(fill_value);
        H5Sclose(h5d_sid);
        H5Pclose(create_plist);
        return FAIL;
    }

    h5dset = H5DCREATE(h5_group,h5csds_name,h5ty_id,h5d_sid,create_plist);

    if (h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 dataset converted from SDS",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        free(chunk_dims);
        free(fill_value);
        H5Sclose(h5d_sid);
        H5Pclose(create_plist);
        return FAIL;
    }
    if(is_for_nodim_data == 1) {
        int32  istat;
        void*  sds_data;
        sds_data = malloc(h4memsize*count_sdsdata);
        if(sds_data == NULL) {
            H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS data",
                __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        istat        = SDreaddata(sds_id, sds_start, sds_stride, sds_edge,
                        (VOIDP)sds_data);
        if (istat == FAIL)  {
            H4toH5error_set(temph4toh5id,2,
                "cannot read SDS data",
                __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(sds_data);
            free(h5csds_name);
            H5Gclose(h5_group);
            return FAIL;
        }

        if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,H5P_DEFAULT,
            (void *)sds_data)<0) {
            H4toH5error_set(temph4toh5id,3,
            "unable to write HDF5 dataset",
            __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            return FAIL;
        }

        free(sds_data);
    }


    /* Before HDF5 library make the optimzation of dealing with fill value
         data, leave this alone.    H5Pset_buffer is also questionable.
         8/9/2001 kent
         Current HDF5 implementation does not need to use H5Dwrite.*/
#if 0
    /*  write_plist = H5Pcreate(H5P_DATASET_XFER);
            bufsize = h4memsize;
            for(i=1;i<sds_rank;i++)
            bufsize *= h5dims[i];

            if(H5Pset_buffer(write_plist,bufsize,NULL,NULL)<0) {
            H4toH5error_set(temph4toh5id,3,
            "unable to set HDF5 buffer for property list",
            __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Pclose(create_plist);
            return FAIL;
            }

            if (H5Dwrite(h5dset,h5_memtype,h5d_sid,h5d_sid,write_plist,
            (void *)sds_data)<0) {
            H4toH5error_set(temph4toh5id,3,
            "unable to write HDF5 dataset",
            __FILE__,__LINE__);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            H5Pclose(write_plist);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            return FAIL;
            }

    */
#endif
    /* convert sds annotation into attribute of sds dataset.
         Since there is no routines to find the exact tag of sds object,
         we will check three possible object tags of sds objects, that is:
         DFTAG_SD,DFTAG_SDG,DFTAG_NDG. If the object tag of sds object is
         falling out of this scope, we will not convert annotations into
         hdf5 attributes; it is user's responsibility to make sure object tags
         for sds objects are only one of the above three tags.*/
    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SD,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SD,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_NDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_NDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(chunk_dims);
            free(fill_value);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        check_gloattr = 0;
        if (sds_transattrs(h4toh5_id,sds_id,h5dset,num_sdsattrs,check_gloattr,attr_flag)==FAIL) {
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            free(fill_value);
            free(chunk_dims);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            H4toH5error_set(temph4toh5id,5,
                    "Error in obtaining SDS attributes ",
                    __FILE__,__LINE__);
            return FAIL;
        }

        /********************************************/
        /*  handle extra attributes of sds : sds label, object type
    and reference num */

        strcpy(sdslabel,SDSLABEL);

        if(attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_ALLATTRS) {
            if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_TYPE,sdslabel)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "unable to transfer SDS label to HDF4 OBJECT TYPE ",
                        __FILE__,__LINE__);
                free(sds_start);
                free(sds_edge);
                free(sds_stride);
                free(fill_value);
                free(chunk_dims);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                return FAIL;
            }


            if(sdsname[0] != '\0') {
                if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_NAME,sdsname)==FAIL){
                    free(sds_start);
                    free(sds_edge);
                    free(sds_stride);
                    free(fill_value);
                    free(chunk_dims);
                    H5Sclose(h5d_sid);
                    H5Dclose(h5dset);
                    H5Pclose(create_plist);
                    H4toH5error_set(temph4toh5id,5,
                            "unable to transfer SDS name to HDF4 OBJECT NAME ",
                            __FILE__,__LINE__);
                    return FAIL;
                }
            }

            if(h4_transnumattr(h4toh5_id,h5dset,HDF4_REF_NUM,sds_ref)==FAIL){
                free(sds_start);
                free(sds_edge);
                free(sds_stride);
                free(fill_value);
                free(chunk_dims);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                H4toH5error_set(temph4toh5id,5,
                        "unable to transfer SDS ref to HDF4 REF NUM ",
                        __FILE__,__LINE__);
                return FAIL;
            }
        }
    }
#ifdef HAVE_LIBHDFEOS
    if(dim_flag == H425_DIMSCALE) {
        if(H4toH5config_use_eos2_conversion()) {
            if(H4toH5all_dimscale(h4toh5_id,sds_id,h5groupname,h5dsetname,
                    h5_dimgroupfullpath,attr_flag,1) == FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "unable to convert all dimensional scales to HDF5 datasets",
                        __FILE__,__LINE__);
                free(sds_start);
                free(sds_edge);
                free(sds_stride);
                free(fill_value);
                free(chunk_dims);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                return FAIL;
            }
        }
    }
#endif
    free(sds_start);
    free(sds_edge);
    free(sds_stride);
    free(fill_value);
    free(chunk_dims);
    H5Sclose(h5d_sid);
    H5Dclose(h5dset);
    H5Pclose(create_plist);
    return SUCCEED;
}


/*-------------------------------------------------------------------------
 * Function:    convert_sdszerounlimit
 *
 * Purpose:         Convert SDS 0 unlimited dimension SDS to the HDF5 dataset

 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5_id: h4toh5 identifier
 sds_id:        SDS id
 h5_group:  HDF5 group id
 h5groupname: absolute path of HDF5 group
 h5dsetname: HDF5 dataset name
 attr_flag:  attribute flag
 Note: redundence among h5_group,h5groupname and h5dsetname is for annotation
 conversion, just leave it for convenience.
 Since fill value implementation method will be changed in HDF5, we will
 leave this function open here without adding more comments.
 *-------------------------------------------------------------------------
 */

int convert_sdszerounlimit(hid_t h4toh5_id,
                 int32 sds_id,
                 hid_t h5_group,
                 char* h5groupname,
                 char* h5dsetname,
                 char* h5csds_name,
                 int attr_flag)
{
    int32       sds_dtype;
    int32       sds_rank;
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS];
    int32*  sds_start;
    int32*  sds_edge;
    int32*  sds_stride;
    int32       count_sdsdata;
    int32       sds_ref;
    int32       num_sdsattrs;
    int         i;
    int         check_gloattr;

    char        sdsname[H4H5_MAX_NC_NAME];
    char        sdslabel[H4H5_MAX_NC_NAME];
    size_t  h4size;
    size_t  h4memsize;


    /* define varibles for hdf5. */

    hid_t       h5dset;
    hid_t       h5d_sid;
    hid_t       h5ty_id;
    hid_t       h5_memtype;
    hid_t       create_plist;
    hsize_t h5dims[H4H5_MAX_VAR_DIMS];
    hsize_t max_h5dims[H4H5_MAX_VAR_DIMS];

    /* define h4toh5 temporary variable. */
    h4toh5id_t* temph4toh5id;

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

    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "unable to get information of SDS object",
                __FILE__,__LINE__);
        return FAIL;
    }


    /* obtain start,edge, stride and number of sds data. */

    sds_start           = malloc(sizeof(int32)*sds_rank);
    if(sds_start == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS starting array",
                __FILE__,__LINE__);
        return FAIL;
    }

    sds_edge            = malloc(sizeof(int32)*sds_rank);
    if(sds_edge == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS edging array",
                __FILE__,__LINE__);
        free(sds_start);
        return FAIL;
    }

    sds_stride      = malloc(sizeof(int32)*sds_rank);
    if(sds_stride == NULL) {
        H4toH5error_set(temph4toh5id,1,
                "cannot allocate memory for SDS stride",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        return FAIL;
    }

    count_sdsdata = 1;
    for (i=0;i<sds_rank;i++){
        sds_stride[i] = 1;
        sds_start[i]    = 0;
        sds_edge[i]     = sds_dimsizes[i];
        count_sdsdata = count_sdsdata*sds_dimsizes[i];

    }
    for (i=0;i<sds_rank;i++) {
        h5dims[i] = sds_edge[i]-sds_start[i];
        max_h5dims[i] = h5dims[i];
    }

    if(SDisrecord(sds_id)) {
        max_h5dims[0] = H5S_UNLIMITED;
    }
    /* convert HDF4 data type to hdf5 data type. */
    if  (h4type_to_h5type(h4toh5_id,sds_dtype,&h5_memtype,&h4memsize,&h4size,
            &h5ty_id) == FAIL) {
        H4toH5error_set(temph4toh5id,5,
                "cannot convert HDF4 data type to HDF5 data type",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        return FAIL;
    }

    /* check whether the datatype is string, if we find string format,
         we will change them back into integer format.*/

    if (h5ty_id == H5T_STRING) {
        /* rechange string datatype into numerical datatype.*/
        if(h5string_to_int(h4toh5_id,sds_dtype,&h5_memtype,h4memsize,
                     &h5ty_id)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "cannot translate H5T_STRING into int",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            return FAIL;
        }
    }

    sds_ref = SDidtoref(sds_id);
    if(sds_ref == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "cannot obtain SDS reference number",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        return FAIL;
    }

    h5d_sid = H5Screate_simple(sds_rank,h5dims,max_h5dims);
    if (h5d_sid < 0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 data space converted from SDS",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);

        return FAIL;
    }

    /* set creation property list. */
    create_plist = get_chunking_plistid(h4toh5_id,sds_id);
    if(create_plist <0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 property list",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        H5Sclose(h5d_sid);
        return FAIL;
    }

    h5dset = H5DCREATE(h5_group,h5csds_name,h5ty_id,h5d_sid,create_plist);
    if (h5dset < 0) {
        H4toH5error_set(temph4toh5id,3,
                "failed to create hdf5 dataset converted from SDS",
                __FILE__,__LINE__);
        free(sds_start);
        free(sds_edge);
        free(sds_stride);
        H5Sclose(h5d_sid);
        return FAIL;
    }


    if(attr_flag == H425_ALLATTRS || attr_flag == H425_NO_PREDEF_ATTRS || attr_flag== H425_SV) {
        if(H4toH5all_dimscale_h5ds(h4toh5_id,sds_id,h5dset,attr_flag) == FAIL){
            H4toH5error_set(temph4toh5id,5,
                                            "unable to convert all dimensional scales to HDF5 datasets",
                                            __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            return FAIL;
        }
    }

    else {
        if(H4toH5all_dimscale(h4toh5_id,sds_id,h5groupname,h5dsetname,
                NULL,attr_flag,1) == FAIL) {
            H4toH5error_set(temph4toh5id,5,
                    "unable to convert all dimensional scales to HDF5 datasets",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            return FAIL;
        }
    }

    /* convert sds annotation into attribute of sds dataset.
         Since there are no routines to find the exact tag of the sds object,
         we will check three possible object tags of sds objects, that is:
         DFTAG_SD,DFTAG_SDG,DFTAG_NDG. If the object tag of sds object is
         falling out of this scope, we will not convert annotations into
         hdf5 attributes; it is user's responsibility to make sure object tags
         for sds objects are only one of the above three tags.*/
    if(is_valid_attr_flag(attr_flag) && attr_flag != H425_NOATTRS) {
        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SD,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SD,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);

            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_SDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_NDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object label conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupname,h5csds_name,sds_ref,DFTAG_NDG,attr_flag)
             == FAIL){
            H4toH5error_set(temph4toh5id,5,
                    "SDS annotation object description conversion is wrong ",
                    __FILE__,__LINE__);
            free(sds_start);
            free(sds_edge);
            free(sds_stride);
            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            return FAIL;
        }

        check_gloattr = 0;
        if (sds_transattrs(h4toh5_id,sds_id,h5dset,num_sdsattrs,check_gloattr,attr_flag)==FAIL) {
            free(sds_start);
            free(sds_edge);
            free(sds_stride);

            H5Sclose(h5d_sid);
            H5Dclose(h5dset);
            H5Pclose(create_plist);
            H4toH5error_set(temph4toh5id,5,
                    "Error in obtaining SDS attributes ",
                    __FILE__,__LINE__);
            return FAIL;
        }

        /********************************************/
        /*  handle extra attributes of sds : sds label, object type
    and reference num */

        strcpy(sdslabel,SDSLABEL);

        if(attr_flag == H425_OSPEC_ALLATTRS || attr_flag == H425_ALLATTRS) {
            if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_TYPE,sdslabel)==FAIL) {
                H4toH5error_set(temph4toh5id,5,
                        "unable to transfer SDS label to HDF4 OBJECT TYPE ",
                        __FILE__,__LINE__);
                free(sds_start);
                free(sds_edge);
                free(sds_stride);
                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                return FAIL;
            }


            if(sdsname[0] != '\0') {
                if(h4_transpredattrs(h4toh5_id,h5dset,HDF4_OBJECT_NAME,sdsname)==FAIL){
                    free(sds_start);
                    free(sds_edge);
                    free(sds_stride);

                    H5Sclose(h5d_sid);
                    H5Dclose(h5dset);
                    H5Pclose(create_plist);
                    H4toH5error_set(temph4toh5id,5,
                            "unable to transfer SDS name to HDF4 OBJECT NAME ",
                            __FILE__,__LINE__);
                    return FAIL;
                }
            }

            if(h4_transnumattr(h4toh5_id,h5dset,HDF4_REF_NUM,sds_ref)==FAIL){
                free(sds_start);
                free(sds_edge);
                free(sds_stride);

                H5Sclose(h5d_sid);
                H5Dclose(h5dset);
                H5Pclose(create_plist);
                H4toH5error_set(temph4toh5id,5,
                        "unable to transfer SDS ref to HDF4 REF NUM ",
                        __FILE__,__LINE__);
                return FAIL;
            }
        }
    }
    free(sds_start);
    free(sds_edge);
    free(sds_stride);
    H5Sclose(h5d_sid);
    H5Dclose(h5dset);
    H5Pclose(create_plist);
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5all_lone_sds
 *
 * Purpose:         convert all independent SDS objects to HDF5 datasets
 *
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :
 h4toh5id: h4toh5 identifier
 h5groupname: absolute path of HDF5 group
 h5_dimgroupfullpath: absolute path of HDF5 dimensional group
 dim_flag: dimensional scale flag
 attr_flag: attribute flag
 *-------------------------------------------------------------------------
 */
int H4toH5all_lone_sds(hid_t h4toh5id,
                     char* h5groupname,
                     char* h5_dimgroupfullpath,
                     int     dim_flag,
                     int     attr_flag)
{
    int32            file_id; /* HDF4 file id */
    int32            sd_id; /* SD interface id */
    int32            sds_id; /* SDS id */
    int32            sds_ref; /* SDS reference number */
    int32            num_sds; /* number of SDS objects */
    int32            num_glsdsattrs; /* number of global SD interface attributes */

    int              check_sds; /* a variable to indicate whether this SDS is checked. */
    int              i; /* temporary variable used in " for " loop */
    int              temp; /* a temporary variable */
    h4toh5id_t* temph4toh5id; /* a pointer to h4toh5 id struct */

    temp = 0;

    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5id);
    file_id          = temph4toh5id->file_id;
    sd_id                = temph4toh5id->sd_id;
    if(SDfileinfo(sd_id,&num_sds,&num_glsdsattrs) == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                "error in obtaining SDS information from the file",
                __FILE__,__LINE__);
        return FAIL;
    }

    /* find all SDS objects under certain vgroups and update the cache table.*/
    if(file_id != -1) {
        if (checkvringobject(h4toh5id,file_id)==FAIL){
            H4toH5error_set(temph4toh5id,2,
                    "cannot check HDF4 SDS and image objects properly",
                    __FILE__,__LINE__);
            return FAIL;
        }
    }

    /*convert all independent SDS objects to the group specificed by
        h5groupname. */

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

        sds_id  = SDselect(sd_id,i);
        if (sds_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                    "error in obtaining sd id",
                    __FILE__,__LINE__);
            return FAIL;
        }
        /* DO NOT convert SDS dimensional scale */
        if(SDiscoordvar(sds_id)){
                SDendaccess(sds_id);
                continue;
        }
        if(temph4toh5id->file_id != -1) {
            sds_ref = SDidtoref(sds_id);
            if (sds_ref == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                        "cannot obtain SDS reference number",
                        __FILE__,__LINE__);
                return FAIL;
            }

            check_sds = lookup(h4toh5id,sds_ref,SDS_HASHSIZE,
            temph4toh5id->sds_hashtab,&temp);
            /* If the SDS has already be touched , skip this one */
            if(check_sds == 1)  {
                 SDendaccess(sds_id);
                 continue;
            }
        }
        /* convert the "lone" SDS objects */
        if(H4toH5sds(h4toh5id,sds_id,h5groupname,NULL,h5_dimgroupfullpath,dim_flag,attr_flag)==FAIL){
            H4toH5error_set(temph4toh5id,5,"error in converting SDS objects.",
                    __FILE__,__LINE__);
            return FAIL;
        }
        SDendaccess(sds_id);
    }

    return SUCCEED;
}

uint16 get_SDref(int32 file_id,uint16 tag,int32 sds_ref)
{
    DFdi di;
    int32 found;
    int32 GroupID;
    int sd_ref = 0;


    if((GroupID = DFdiread(file_id,tag,(uint16)sds_ref))<0){
        /* for some cases, although sd_ref cannot be found, the current
             SDS object is still legal(unlimited dimension with the current
             size set to 0. so comment this the following warning printfs out. */
        /*      printf("cannot find sd_ref\n");*/
        return sd_ref;
    }

    found = 0;
    di.tag = DFTAG_NULL;
    di.ref = 0;
    while((found == 0) &&(DFdiget(GroupID,&di.tag,&di.ref)==0)){
        if(di.tag == DFTAG_SD)
            found = 1;
    }

    sd_ref = di.ref;
    /* comment out the following two lines. */
    /*if(!found) ;*/
    /* printf("cannot find sd_ref\n");*/

    DFdifree(GroupID);
    return sd_ref;
}

/****************H4toH5all_dimscale_h5ds*******************
* Function:         H4toH5all_dimscale_h5ds
* Purpose:          Convert all dimensions of this SDS to HDF5 by using HDF5
                                dimension scale APIs if possible
* Description:  1) If dimensions of this SDS have dimension scales,
                   HDF5 high-level dimension scale APIs H5DSset_scale and H5DSattach_scale
                   are used to generate dimension scales following the
                   HDF5 dimension scale specification rather than
                   the HDF4 to HDF5 mapping specification.

               2) If this SDS provides dimension info. but dimension scales are not
                  provided, this routine will create a pure dimension in HDF5 following
                  the netCDF-4 convention. In this way, netCDF-4's tool(ncdump)can still
                  access the dimension information successfully.
                  Note: We find a special case to convert MODIS MOD021KM files. The dimension is set
                  as a pure dimension but the same 1-D SDS(with the same dimension name) is also
                  provided. The conversion tool will fail when handling this pure dimension.
                  So we set a special convention to handle this case. If the 1-D SDS with the same pure
                  dimension name is found, we will treat this dimension as a general dimension scale case
                  with the 1-D SDS as the dimension scale.

              3) If the data producer of this HDF4 file doesn't provide any dimension to this
                 SDS, HDF4 will assign fakeDim1,fakeDim2, etc. as its dimensions. These fake
                 dimensions will be converted to HDF5 as case 2). However, the dimensions share
                 the same length will be collapsed as one dimension. For example, fakeDim1 =2,
                 fakeDim4 = 2, these two dimensions will be converted to one dimension.

*
* Return:        FAIL if failed, SUCCEED if successful.
*
* In :
*                               h4toh5id:                    h4toh5 interface identifier
*                               sdsid:                       SDS identifier
*                               h5dset_id:               HDF5 dataset identifier
*                               attr_flag:               Attribute flag, this is only used when handling
*                                                        pure dimensions.
*
*-------------------------------------------------------------------------
*/

int H4toH5all_dimscale_h5ds(hid_t  h4toh5id,int32 sds_id,hid_t h5dset_id,int attr_flag) {

        /*Varibles for SDS dimensional scales. */
    int32       sdsdim_id       = -1;        /* SDS dimensional scale id */
    int32       sdsdim_type = 0;     /* SDS dimensional scale data type */
    int32       sds_dimscasize[1]; /* the size of SDS dimensional scale */
    int         sdsdim_index = 0;           /* SDS dimension index. */
    int32       num_sdsdimattrs = 0; /* number of SDS dimensional scale attributes. */

    /* Should use HDF4's new APIs to dynamically obtain the dim. name length.
         This will be fixed in the future release(2.2.5 or later) with the other
         part of the tool */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    int         unlimited_dim = 0; /* Flag to check if this dimension is unlimited. */

    /* Variables for SDS */
    int32       istat; /* temporary variable to check the "return" status  of HDF4 APIs */
    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* SDS rank */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS]; /* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */

    /* Should use HDF4's new APIs to dynamically obtain the dim. name length.
         This will be fixed in the future release(2.2.5 or later) with the other
         part of the tool */
    char        sdsname[H4H5_MAX_NC_NAME]; /* SDS name */
    char     *cor_sdsdimname = NULL;         /* The corrected SDS dim. name ('/' to '_') */

    /* Varibles for HDF5. */
    hid_t       h5file_id = -1; /* HDF5 file ID */


    char *h5dim_abo_path = NULL; /* absolute path of HDF5 dim. scale */
    char slash_char[]        ="/";


    h4toh5id_t *h4toh5id_ptr = NULL; /* a pointer to h4toh5 id*/

    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5file_id        = h4toh5id_ptr->file5_id;


    /* using SDS getinfo to get all the information of this SDS object.*/
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
                                &num_sdsattrs)==FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"fail to get SDS information",
                                            __FILE__,__LINE__);
        return FAIL;
    }

    /* Loop through all the dimensions of this SDS */
    for (sdsdim_index = 0; sdsdim_index<sds_rank;sdsdim_index++) {
        sdsdim_id        = SDgetdimid(sds_id,sdsdim_index);
        if(sdsdim_id == FAIL) {
            H4toH5error_set(h4toh5id_ptr,2,"cannot obtain SDS dimension",
                                            __FILE__,__LINE__);
            return FAIL;
        }

        istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                                            &sdsdim_type,&num_sdsdimattrs);
        if (istat == FAIL) {
            H4toH5error_set(h4toh5id_ptr,2,"cannot obtain SDS dimension information",
                                                __FILE__,__LINE__);
            return FAIL;
        }

        /* for unlimited SDS dimension, grab the current dimensional size. */
        if(sds_dimscasize[0] == 0)
            sds_dimscasize[0] = sds_dimsizes[0];

        /* Set unlimited dimension flag be true if this is the first dimension and this SDS has unlimited dimension. */
        if(SDisrecord(sds_id) && sdsdim_index == 0)
            unlimited_dim = 1;

        /*Prepare the HDF5 dimension scale name.
            Since the SDS dimension name is unique and the dimension scale is independent of vgroups,
            we convert the dimension scales under the root group.
        */
        /* '/' is a predefined character in the HDF5 name, so we need to change the
                '/' inside the SDS dimension name to another character, in the tool, it is '_'.
        */
        cor_sdsdimname = correct_name(h4toh5id,sdsdim_name);
        if(cor_sdsdimname == NULL) {
            H4toH5error_set(h4toh5id_ptr,1,
                           "Unable to allocate the memory for the corrected SDS dimension name.",
                            __FILE__,__LINE__);
            return FAIL;
        }

        /*Build up the abosolute path of the HDF5 dataset converted from this SDS dimension */
        h5dim_abo_path = malloc(strlen(cor_sdsdimname)+2);
        if(h5dim_abo_path == NULL) {
            free(cor_sdsdimname);
            H4toH5error_set(h4toh5id_ptr,1,
                                  "Unable to allocate the memory for HDF5 dimension scale path.",
                                   __FILE__,__LINE__);
            return FAIL;
        }
        h4toh5_ZeroMemory(h5dim_abo_path,strlen(cor_sdsdimname)+2);
        strncpy(h5dim_abo_path,slash_char,1);
        h5dim_abo_path[1]='\0';
        strncat(h5dim_abo_path,cor_sdsdimname,strlen(cor_sdsdimname));

        /* If the dim. type of this dimension is 0, this dimension doesn't have a dimension scale.
             However, we still need to handle this case with HDF5 dimension scale APIs to keep
             the relations between the dimensions and the variables. We follow netCDF-4's way
             to handle this case due to the following two reasons:
             1) SDS is a mash-up of the netCDF data model, it is natural to follow netCDF-4 to handle these
                    cases.
             2) NetCDF tools(ncdump etc.) can correctly pin down the dimension/variable relations if
                    we follow the netCDF-4's way.
             KY 2014-06-16
        */
        if(sdsdim_type == 0) {

            /* Handle the fake dimension generated by the HDF4 library. The dimension name always starts with FakeDim etc.
            */
            if(strncmp(sdsdim_name,fakeDim,strlen(fakeDim))==0){
                if(handle_fake_dim_scale(h4toh5id,h5dim_abo_path,sdsdim_name,sds_dimscasize[0],
                                                             sdsdim_index,unlimited_dim,h5dset_id) == FAIL) {
                    H4toH5error_set(h4toh5id_ptr,5,"Fail to handle the conversion of SDS fake dimensions to HDF5 .",
                                                                                    __FILE__,__LINE__);
                    free(cor_sdsdimname);
                    free(h5dim_abo_path);
                    return FAIL;
                }
            }
            else {/* The user specifies the dimension name but doesn't provide any dimension scales */

                int8 dim_scale_exist = 0;
                /* Check if this SDS is 1-D and if the sdsname is the same as the sdsdim_name. */
                if(sds_rank == 1) {
                    if(strlen(sdsname) == strlen(sdsdim_name)) {
                        if(strncmp(sdsname,sdsdim_name,strlen(sdsname)) ==0)
                            dim_scale_exist = 1;
                    }
                }
                if(handle_pure_dim_scale(h4toh5id,h5dim_abo_path,sdsdim_name,sds_dimscasize[0],
                                                             sds_dtype,sdsdim_index,unlimited_dim,
                                                    sdsdim_id,h5dset_id,attr_flag,dim_scale_exist) == FAIL) {
                    H4toH5error_set(h4toh5id_ptr,5,"Fail to handle the conversion of SDS pure dimensions to HDF5 .",
                                                                                    __FILE__,__LINE__);
                    free(cor_sdsdimname);
                    free(h5dim_abo_path);
                    return FAIL;
                }
            }
        }
        /* Have dimension scales. */
        else {
            if(handle_general_dim_scale(h4toh5id,h5dim_abo_path,sdsdim_name,sds_dimscasize[0],
                                                                    sds_dtype,sdsdim_index,unlimited_dim,sds_id,sdsdim_id,h5dset_id) == FAIL) {
                free(cor_sdsdimname);
                free(h5dim_abo_path);
                return FAIL;
            }
        }
        if (unlimited_dim !=0)
            unlimited_dim = 0;
        free(cor_sdsdimname);
        free(h5dim_abo_path);
    } /* end of the for loop */

    return SUCCEED;

}
/****************handle_general_dim_scale*******************
* Function:         handle_general_dim_scale
* Purpose:          Handle dimension scale of the dimension that has a scale.
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                  h4toh5id:                    h4toh5 interface identifier
*                  h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
*                  sdsdim_name:             The name of this SDS dimension
                   sds_dimscale_size: The size of this SDS dimension(for unlimited dimension, the current dim. size is used.)
                   sds_dtype:               SDS data type
                   sdsdim_index:            The index of this SDS dimension
                   unlimited_dim:       Is this dimension an unlimited dimension?
*                  h5dset_id:               HDF5 dataset identifier
*-------------------------------------------------------------------------
*/


int handle_general_dim_scale(hid_t h4toh5id,
                             const char *h5dim_abo_path,
                             const char *sdsdim_name,
                             int     sds_dimscale_size,
                             int     sds_dtype,
                             int     sdsdim_index,
                             short unlimited_dim,
                             int32 sds_id,
                             int32 sdsdim_id,
                             hid_t h5dset_id) {

    h4toh5id_t *h4toh5id_ptr = NULL; /*Pointer to h4toh5 id */
    int dimscale_visited         = 0;  /* Flag to check if the dimscale is visited */
    hid_t h5_scale_id                = -1; /* HDF5 dimension scale dataset ID */
    hid_t h5file_id                  = -1; /* HDF5 file ID */

    /* Obtain pointer to h4toh5id; this is for error handling*/
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5file_id        = h4toh5id_ptr->file5_id;

    /* Check this dimension to see if it is visited or not */
    dimscale_visited = lookup_updatename(h4toh5id,sdsdim_name,DIMSCALE_HASHSIZE,h4toh5id_ptr->dimscale_hashtab);

    /* The dimension hasn't been visited. Just create the dimension scale and attach the scale to the dimension of this dataset. */
    if (0 == dimscale_visited) {

        /* Obtain the HDF5 dimension scale dataset ID if this dimension scale is just created. */
        h5_scale_id = create_general_dim_scale(h4toh5id,sds_id,sdsdim_id,h5dim_abo_path,sdsdim_index,sds_dimscale_size,unlimited_dim);
        if(h5_scale_id <0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to obtain HDF5 dataset ID converted from the SDS dimension. ",
                                                                                    __FILE__,__LINE__);
            return FAIL;
        }

        /* Attach this scale to the dimension of this HDF5 dataset */
        if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index) <0) {
            H5Dclose(h5_scale_id);
            H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS dimension.",
                                                                                     __FILE__,__LINE__);
            return FAIL;
        }
        H5Dclose(h5_scale_id);

    }
    /* The dimension has been visited. Just open the dimension scale dataset and attach the scale to the dimension of the HDF5 dataset
     * from the converted SDS
     */
    else if (1 == dimscale_visited) {
        if((h5_scale_id= H5DOPEN(h5file_id, h5dim_abo_path))<0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to open the HDF5 dataset converted from the SDS dimension.",
                                                                                     __FILE__,__LINE__);
            return FAIL;
        }

        if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index) <0) {
            H5Dclose(h5_scale_id);
            H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS dimension.",
                                                                                   __FILE__,__LINE__);
            return FAIL;
        }
        H5Dclose(h5_scale_id);
    }
    /* Something is wrong when checking if this dimension is visited. */
    else {
        H4toH5error_set(h4toh5id_ptr,5,"Fail to check if the dimension with scale is visited or not. ",
                                                                                         __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}


/****************handle_fake_dim_scale*******************
* Function:         handle_fake_dim_scale
* Purpose:          Handle dimension scale of the fake dimension.
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                 h4toh5id:                    h4toh5 interface identifier
*                 h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
*                 sdsdim_name:             The name of this SDS dimension
                  sds_dimscale_size: The size of this SDS dimension(for unlimited dimension, the current dim. size is used.)
                  sdsdim_index:                   The index of this SDS dimension
                  unlimited_dim:       Is this dimension an unlimited dimension?
*                 h5dset_id:               HDF5 dataset identifier
*-------------------------------------------------------------------------
*/


int handle_fake_dim_scale(hid_t h4toh5id,
                          const char *h5dim_abo_path,
                          const char *sdsdim_name,
                          int     sds_dimscale_size,
                          int     sdsdim_index,
                          short  unlimited_dim,
                          hid_t  h5dset_id) {

    h4toh5id_t *h4toh5id_ptr = NULL; /*Pointer to h4toh5 id */
    char *temp_fakedim_name  = NULL; /*Temporary fake dimension name */
    char *h5newdim_abo_path  = NULL; /* The new HDF5 absolute path of the dimension when the length of the fakedim is shared.*/
    short fakedim_error_flag = 0;        /*Error flag returned by obtaining the fakedim names */
    hid_t h5_scale_id                = -1;   /* HDF5 dimension scale dataset ID */
    hid_t h5file_id                  = -1;   /* HDF5 file id */

    char slash_char[]                ="/";   /* Used to create the absolute path of the HDF5 dimension */

    /* Obtain pointer to h4toh5id; this is for error handling*/
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5file_id        = h4toh5id_ptr->file5_id;

    /* Look up the fakedim in the table. If we find that this fakedim shares the
         same length with a fakedim stored in the table, we use the fakedim name stored
         in the table. This will effectively reduce many fakedim names.
         If no fakedim name is found, this fakedim name is inserted to the table, a NULL
         will be returned.
    */
    temp_fakedim_name = lookup_len_update_name(h4toh5id,sds_dimscale_size,
                                               h4toh5id_ptr->fakedim_hashtab,
                                               sdsdim_name,&fakedim_error_flag);

    /* If something is wrong when retrieving this fake dimension name,
         clean up the memory and return FAIL. */
    if (fakedim_error_flag < 0) {
        if(temp_fakedim_name != NULL) {
            H4toH5error_set(h4toh5id_ptr,4,"Fail to obtain the SDS fake dimension name.",
                                                                                         __FILE__,__LINE__);
            free(temp_fakedim_name);
            return FAIL;
        }
    }

    /* This fakedim is the first fake dimension that has this dimension length, just create a dim. scale. */
    if(temp_fakedim_name == NULL) {

        /*Create a pure FakeDim, dimension scale.
            NOTE: When using H5SDset_scale for dimensions without dimension scales, we follow the netCDF-4 data model.
                             the dimension name should be
                             ("This is a netCDF dimension but not a netCDF variable.")
        */
        h5_scale_id = create_pure_fake_dim_scale(h4toh5id,h5dim_abo_path,sds_dimscale_size,unlimited_dim);
        if(h5_scale_id <0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to obtain HDF5 dataset ID converted from the SDS fake dimension. ",
                                                                                     __FILE__,__LINE__);
            return FAIL;
        }

        /* Attach the dimension of this HDF5 dataset to the created dim scale */
        if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index) <0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS fake dimension.",
                                                                                     __FILE__,__LINE__);
            H5Dclose(h5_scale_id);
            return FAIL;
        }

        H5Dclose(h5_scale_id);
    }
    else { /* The dimension scale dataset has been created, we just need to open and attach. */
            /* Generate the new absolute path of the HDF5 dimension based on the visited fakedim name. */
        h5newdim_abo_path = malloc(strlen(temp_fakedim_name)+2);
        if(h5newdim_abo_path == NULL) {
            H4toH5error_set(h4toh5id_ptr,3,
                                        "unable to allocate the memory for the HDF5 dimension scale dataset name.",
                                        __FILE__,__LINE__);
            free(temp_fakedim_name);
            return FAIL;
        }
        h4toh5_ZeroMemory(h5newdim_abo_path,strlen(temp_fakedim_name)+2);
        strncpy(h5newdim_abo_path,slash_char,1);
        h5newdim_abo_path[1]='\0';
        strncat(h5newdim_abo_path,temp_fakedim_name,strlen(temp_fakedim_name));

        /* OPen the dimension scale */
        if((h5_scale_id = H5DOPEN(h5file_id, h5newdim_abo_path))<0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to open the HDF5 dataset converted from the SDS fake dimension.",
                                                                                     __FILE__,__LINE__);
            free(h5newdim_abo_path);
            free(temp_fakedim_name);
            return FAIL;
        }

        /* Attach the scale */
        if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index) <0) {
                H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS fake dimension.",
                                                                                     __FILE__,__LINE__);
            free(h5newdim_abo_path);
            free(temp_fakedim_name);
            H5Dclose(h5_scale_id);
            return FAIL;
        }
        free(temp_fakedim_name);
        free(h5newdim_abo_path);
        H5Dclose(h5_scale_id);
    }
    return SUCCEED;
}

/****************handle_pure_dim_scale*******************
* Function:         handle_pure_dim_scale
* Purpose:          Handle dimension scale of the user-defined dimension when the dimension doesn't have a dimension scale(pure dimension).
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                               h4toh5id:                    h4toh5 interface identifier
*                               h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
*                               sdsdim_name:             The name of this SDS dimension
                                sds_dimscale_size: The size of this SDS dimension(for unlimited dimension, the current dim. size is used.)
                                sds_dtype:               SDS data type
                                sdsdim_index:                   The index of this SDS dimension
                                unlimited_dim:       Is this dimension an unlimited dimension?
                                sdsdim_id:               SDS dimension ID
*                               h5dset_id:               HDF5 dataset identifier
*                               attr_flag:           conversion attribute flag, used when the dimension name is the same as the SDS name
*                               dim_scale_exist:     flag to indicate that the dimension name in the same as this SDS
*-------------------------------------------------------------------------
*/


int handle_pure_dim_scale(hid_t h4toh5id,
                          const char *h5dim_abo_path,
                          const char *sdsdim_name,
                          int     sds_dimscale_size,
                          int     sds_dtype,
                          int     sdsdim_index,
                          short unlimited_dim,
                          int32 sdsdim_id,
                          hid_t h5dset_id,
                          int attr_flag,
                          int8 dim_scale_exist_same_sds) {

    h4toh5id_t *h4toh5id_ptr = NULL; /*Pointer to h4toh5 id */
    int puredim_visited          = 0; /* Flag to check if the pure dimension is visited. */
    hid_t h5_scale_id                = -1; /* HDF5 dimension scale ID */
    hid_t h5file_id                  = -1; /* HDF5 file ID */

    int32 sd_id = -1;
    int nvars_sname = 0;
    int8 dim_scale_exist = dim_scale_exist_same_sds;
    intn ret_value = 0;

    /* Obtain pointer to h4toh5id; this is for error handling*/
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5file_id        = h4toh5id_ptr->file5_id;

    sd_id = h4toh5id_ptr->sd_id;

    if(dim_scale_exist == 0) {
        /* We will check if there is an SDS that has the same name as the dimension.*/
        ret_value=SDgetnumvars_byname(sd_id,sdsdim_name,&nvars_sname);
        if(ret_value == FAIL){
            H4toH5error_set(h4toh5id_ptr,2,"SDgetnumvars_byname API failed. ",__FILE__,__LINE__);
            return FAIL;
        }
        else if(nvars_sname>1) {
            H4toH5error_set2(h4toh5id,5,"More than 1 SDS shares the same dimension name,please use h4toh5 -na option  "
                                       ,sdsdim_name,__FILE__,__LINE__);
            return FAIL;
        }
        else if(nvars_sname == 1) {
            dim_scale_exist = check_sds_equ_dim(h4toh5id,sd_id,sdsdim_name,sds_dtype,sds_dimscale_size);
            if( dim_scale_exist == FAIL) {
                H4toH5error_set(h4toh5id_ptr,5,"check_sds_equ_dim function failed. ",__FILE__,__LINE__);
                return FAIL;
            }
            else if (dim_scale_exist == 0) {
                H4toH5error_set(h4toh5id_ptr,5,"h4toh5 failed due to the misuse of dimension names in the file. Use h4toh5 -na",__FILE__,__LINE__);
                return FAIL;
            }
        }
    }

    /*Check if this dimension is visited or not */
    puredim_visited = lookup_updatename(h4toh5id,sdsdim_name,DIMPURE_HASHSIZE,h4toh5id_ptr->puredim_hashtab);

    /* This dimension is not visited. We need to create an HDF5 dimension scale and attach this dataset to the scale.*/
    if (0 == puredim_visited) {

        /* Need to check if this HDF5 dataset(name: h5dim_abo_path) already exists by using H5Dopen */
        if(dim_scale_exist >= 1) {
            H5E_BEGIN_TRY {
               h5_scale_id = H5DOPEN(h5file_id,h5dim_abo_path);
            } H5E_END_TRY;
            if(h5_scale_id ==FAIL) {
                /* This SDS is not opened. We need to retrieve this SDS and convert it to an HDF5 dimension scale dataset. */
                int32 sds_index = SDnametoindex(sd_id,sdsdim_name);
                if(sds_index == FAIL) {
                    H4toH5error_set2(h4toh5id,2,"SDnametoindex API Failed. ",sdsdim_name,__FILE__,__LINE__);
                    return FAIL;
                }

                int32 sds_id = SDselect(sd_id,sds_index);
                if(sds_id == FAIL) {
                    H4toH5error_set2(h4toh5id,2,"SDselect API Failed. ",sdsdim_name,__FILE__,__LINE__);
                    return FAIL;
                }
                /* Here we call this convert_sds_... function to convert this SDS to an HDF5 dataset.
                   the last flag 1 indicates this is for nodim_data.
                   The HDF4_DIMG should not matter, just put it to be consistent with other codes.
                */
                if(convert_sds_fillvalue_or_nodim_data(h4toh5id,sds_id,h5file_id,"/",NULL,
                        (char *)sdsdim_name,HDF4_DIMG,H425_DIMSCALE,attr_flag,1)==FAIL) {
                    H4toH5error_set(h4toh5id_ptr,5,
                        "cannot convert SDS fill value correctly",
                        __FILE__,__LINE__);
                    SDendaccess(sds_id);
                    return FAIL;
                }

                /* Based on our conventions,this own SDS dimension will be changed to its own name if it is set.
                   This is the only way this can work. We can check if the dimension name is the same as this sds
                    name, if not, we will throw an error. The conversion tool cannot handle this properly.
                */
                int32 sdsdim_id = SDgetdimid(sds_id,0);
                char picked_dimscale_dimname[H4H5_MAX_NC_NAME+1];
                int32 temp_sds_dimscasize[1];
                int32 temp_sds_dimtype = 0;
                int temp_numsdsdimattrs = 0;
                if(SDdiminfo(sdsdim_id,picked_dimscale_dimname,temp_sds_dimscasize,&temp_sds_dimtype,&temp_numsdsdimattrs)==FAIL) {
                    H4toH5error_set(h4toh5id_ptr,2,
                        "cannot convert SDSdiminfo correctly",
                        __FILE__,__LINE__);
                    SDendaccess(sds_id);
                    return FAIL;
                }
                if(strncmp(picked_dimscale_dimname,fakeDim,strlen(fakeDim))!=0) {
                    if(strlen(sdsdim_name) != strlen(picked_dimscale_dimname) ||
                       strncmp(sdsdim_name,picked_dimscale_dimname,strlen(sdsdim_name))!=0) {
                        H4toH5error_set(h4toh5id_ptr,2,
                            "This SDS is a dimension scale but the SDS name is not the same as the dimension name. Use h4toh5 -na to convert.",
                            __FILE__,__LINE__);
                        SDendaccess(sds_id);
                        return FAIL;
                    }
                }
                SDendaccess(sds_id);
                /* Need to open this HDF5 dataset. */
                h5_scale_id = H5DOPEN(h5file_id,h5dim_abo_path);
                if(h5_scale_id ==FAIL) {
                    H4toH5error_set2(h4toh5id,3,
                        "unable to open HDF5 dimensional scale dataset",h5dim_abo_path,
                        __FILE__,__LINE__);
                    return FAIL;
                }
            }
            if(H5DSset_scale(h5_scale_id,h5dim_abo_path)<0) {
                H4toH5error_set2(h4toh5id,3,
                        "unable to set dimension scale for ",h5dim_abo_path,
                         __FILE__,__LINE__);
                return FAIL;
            }
            /* If dim_scale_exist is 1, this SDS is the dimension scale, you cannot attach the dim. scale to yourself. */
            if(dim_scale_exist == 2) {
                if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index)<0) {
                    H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS pure dimension.",
                                                                                     __FILE__,__LINE__);
                    H5Dclose(h5_scale_id);
                    return FAIL;
                }
            }
        }

        else {
            h5_scale_id = create_pure_dim_scale(h4toh5id,sdsdim_id,h5dim_abo_path,sds_dtype,sds_dimscale_size,unlimited_dim);
            if(h5_scale_id <0) {
                H4toH5error_set(h4toh5id_ptr,3,"Fail to obtain HDF5 dataset ID converted from the SDS pure dimension. ",
                                                                                     __FILE__,__LINE__);
                return FAIL;
            }
            if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index)<0) {
                H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS pure dimension.",
                                                                                     __FILE__,__LINE__);
                H5Dclose(h5_scale_id);
                return FAIL;
            }
        }

        H5Dclose(h5_scale_id);

    }
    /* The dimension is visited, so the scale is created. we just need to open and attach the scale. */
    else if (1 == puredim_visited) {
        if((h5_scale_id = H5DOPEN(h5file_id, h5dim_abo_path)) <0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to open the HDF5 dataset converted from the SDS pure dimension.",
                                                                                    __FILE__,__LINE__);
            return FAIL;

        }
        if(H5DSattach_scale(h5dset_id,h5_scale_id,sdsdim_index)<0) {
            H4toH5error_set(h4toh5id_ptr,3,"Fail to attach the HDF5 dimension scale converted from the SDS pure dimension.",
                                                                                     __FILE__,__LINE__);
            H5Dclose(h5_scale_id);
            return FAIL;
        }
        H5Dclose(h5_scale_id);
    }
    /* Something is wrong when checking this dimension. */
    else {
            H4toH5error_set(h4toh5id_ptr,5,"Fail to check if the pure dimension is visited or not.",
                                                                                         __FILE__,__LINE__);
            return FAIL;
    }
    return SUCCEED;
}

/****************create_general_dim_scale*******************************
* Function:         create_general_dim_scale
* Purpose:          create HDF5 dimension scale dataset for the dimension that has a scale
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                  h4toh5id:                    h4toh5 interface identifier
                   sds_id:                      SDS ID
                   sdsdim_id:               SDS dimension ID
*                  h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
                   dim_index:               The index of this SDS dimension
                   sds_firstdimsize:  The size of the first dimension of this SDS
                                                        (for unlimited dimension, the current dim. size is used.)
                   unlimited_dim:       Is this dimension an unlimited dimension?
*-------------------------------------------------------------------------
*/


hid_t create_general_dim_scale(hid_t h4toh5id, int sds_id, int sdsdim_id, const char *h5dim_abo_path,int dim_index, int sds_firstdimsize,short unlimited_dim){

    h4toh5id_t *h4toh5id_ptr         = NULL; /* a pointer to h4toh5 id*/

    int32       sdsdim_type                  = 0;       /* SDS dimensional scale data type */
    int32       sds_dimscasize[1];                  /* the size of SDS dimensional scale */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    size_t sh4_dimmemsize                = 0;        /* The size of the HDF4 memory datatype */
    size_t sh4_dimsize                   = 0;        /* The size of the HDF4 datatype */
    int32       num_sdsdimattrs          = 0; /* number of SDS dimensional scale attributes */
    int dim_attr_index                   = 0; /* Dimension attribute index */
    int     dim_scalen                       = 0; /* The length of the buffer that stores the scale */
    void    *dim_scadata                     = NULL; /* dim. scale data buffer */
    int32 istat                                  = -1;   /* HDF4 API status flag */

    hid_t h5_fileid                          = -1;   /* a temporary HDF5 file ID */
    hid_t h5dim_dset                         = -1; /* HDF5 dataset ID */
    hid_t h5dim_sid                          = -1; /* HDF5 dimension space ID */
    hid_t sh5_dimtype                        = 0;  /* file datatype of the HDF5 dimension scale dataset */
    hid_t sh5_dimmemtype                 = 0; /* memory datatype of the HDF5 dimension scale dataset */

    hid_t dset_cpl                           = -1; /* HDF5 dataset creation property list ID */
    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */
    char *temp_dim_scale_name           = NULL; /* Name of HDF5 dim. scale dataset */
    char *h5dim_rel_path            = NULL; /* Relative path of new HDF5 dim. scale dataset */


    /* Obtain H4toH5 id pointer and HDF5 file ID */
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5_fileid        = h4toh5id_ptr->file5_id;

    /* Check the size of the absolute path of the HDF5 dimension scale dataset, it should be at least /?, ?
         is an ASCII instance allowed by HDF5 */
    if(strlen(h5dim_abo_path) < 3) {
        H4toH5error_set(h4toh5id_ptr,1,"The length of the absolute name of the dimension should be at least 2.",
                                        __FILE__,__LINE__);
        return FAIL;
    }

    /*get the information of this dimensional scale*/
    istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                        &sdsdim_type,&num_sdsdimattrs);
    if (istat == FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot obtain SDS dimension information",
                                                                        __FILE__,__LINE__);
        return FAIL;
    }

    /* create HDF5 dimension, set properly for unlimited dimension. */
    if(sds_dimscasize[0] == 0)
        h5dimscas[0] = sds_firstdimsize;
    else
        h5dimscas[0] = sds_dimscasize[0];

    if(unlimited_dim == 1)
        max_h5dimscas[0] = H5S_UNLIMITED;
    else
        max_h5dimscas[0] = h5dimscas[0];

    h5dim_sid = H5Screate_simple(1,h5dimscas,max_h5dimscas);
    if(h5dim_sid <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 space ",
                                        __FILE__,__LINE__);
        return FAIL;
    }

    /* create property list, for chunked sds or unlimited dimension cases */
    dset_cpl = get_dimchunking_plistid(h4toh5id,sds_id,sdsdim_id,dim_index,sds_firstdimsize);
    if(dset_cpl == -1) {
        H4toH5error_set(h4toh5id_ptr,5,"cannot get property list" ,
                                       __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        return FAIL;
    }
    /* convert HDF4 dimension scale data type to HDF5 dimension scale data type. */
    if(h4type_to_h5type(h4toh5id,sdsdim_type,&sh5_dimmemtype,&sh4_dimmemsize,
                                                &sh4_dimsize,&sh5_dimtype)== FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot convert SDS attribute data type from H4 to H5",
                                        __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }

    /* Obtain the size of the buffer that stores the dimension scale */
    if(sds_dimscasize[0] == 0)
        dim_scalen = sh4_dimmemsize*sds_firstdimsize;
    else
        dim_scalen = sh4_dimmemsize*sds_dimscasize[0];

    /* get the dimensional scale data. */
    if(dim_scalen == 0) {
        H4toH5error_set(h4toh5id_ptr,2,"The current dimension scale data should not be 0",
                                                __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }
    dim_scadata = malloc(dim_scalen);
    if(dim_scadata == NULL) {
        H4toH5error_set(h4toh5id_ptr,1,"Cannot allocate memory for dimensional data ",
                                            __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }

    istat               = SDgetdimscale(sdsdim_id,(VOIDP)dim_scadata);
    if (istat == FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot get SDS dimensional scale data ",
                                            __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        free(dim_scadata);
        return FAIL;
    }

    /* Create the HDF5 dimension scale dataset */
    h5dim_dset = H5DCREATE(h5_fileid,h5dim_abo_path,sh5_dimtype,h5dim_sid,dset_cpl);
    if (h5dim_dset < 0) {
        H4toH5error_set(h4toh5id_ptr,3,
                                                "unable to create HDF5 dataset for SDS's fakedim",
                                                __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        free(dim_scadata);
        return FAIL;
    }

    /* Store the scale values to the HDF5 dimension scale dataset */
    if (H5Dwrite(h5dim_dset,sh5_dimmemtype,h5dim_sid,h5dim_sid,
                             H5P_DEFAULT,(void *)dim_scadata)<0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot write HDF5 dataset",
                                                                     __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5dim_dset);
        free(dim_scadata);
        return FAIL;
    }

    /* Convert HDF5 dimension scale attributes to HDF5 */
    for (dim_attr_index = 0; dim_attr_index <num_sdsdimattrs;dim_attr_index++) {
        if(sds_dimscale_transattr(h4toh5id,sdsdim_id,h5dim_dset,dim_attr_index) <0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot convert SDS dimension scale attributes successfully",
                                                                 __FILE__,__LINE__);
            H5Sclose(h5dim_sid);
            H5Pclose(dset_cpl);
            H5Dclose(h5dim_dset);
            free(dim_scadata);
            return FAIL;
        }
    }

    /* Obtain the relative path of the dimension scale to the HDF5 since H5DSset_scale
         will set an attribute NAME to store the value of the second parameter in H5DSset_scale.
         For a dimension lat, we want to store the NAME to be lat rather than /lat.
         This also follows the netCDF-4 way. */
    temp_dim_scale_name = malloc(strlen(h5dim_abo_path)+1);
    if(temp_dim_scale_name == NULL) {
        H4toH5error_set(h4toh5id_ptr,1,"cannot allocate memory for SDS dimension scale name",
                                        __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5dim_dset);
        free(dim_scadata);
        return FAIL;
    }
    h4toh5_ZeroMemory(temp_dim_scale_name,strlen(h5dim_abo_path)+1);

    /* Simply use strcpy to make sure temp_dim_scale_name is NULL terminated. */
    strcpy(temp_dim_scale_name,h5dim_abo_path);

    h5dim_rel_path = temp_dim_scale_name +1;

    if(H5DSset_scale(h5dim_dset,h5dim_rel_path)<0) {
        H4toH5error_set(h4toh5id_ptr,3,
                       "unable to create HDF5 dataset for SDS's fakedim",
                        __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5dim_dset);
        free(dim_scadata);
        free(temp_dim_scale_name);
        return FAIL;

    }

    H5Sclose(h5dim_sid);
    H5Pclose(dset_cpl);
    free(dim_scadata);
    free(temp_dim_scale_name);

    return h5dim_dset;

}

/****************create_pure_fake_dim_scale*******************************
* Function:         create_pure_fake_dim_scale
* Purpose:          create HDF5 dimension scale dataset for the dimension generated by the HDF4 library
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                     h4toh5id:                    h4toh5 interface identifier
*                     h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
                      sdsdim_size:             The size of the current dimension of this SDS
                                                           (for unlimited dimension, the current dim. size is used.)
                      unlimited_dim:       Is this dimension an unlimited dimension?
*-------------------------------------------------------------------------
*/


hid_t create_pure_fake_dim_scale(hid_t h4toh5id,
                                const char *h5dim_abo_path,
                                int     sdsdim_size,
                                short   unlimited_dim){

    h4toh5id_t* h4toh5id_ptr = NULL; /* a pointer to h4toh5 id*/
    hid_t h5_fileid                  = -1; /* a temporary HDF5 file ID */
    hid_t h5scale_id                 = -1; /* HDF5 dimension scale dataset ID */
    hsize_t h5dim_chunkdim[1]; /* Chunk size for this dimension. */
    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */

    hid_t h5dim_sid                  = -1;/* HDF5 data space ID for HDF5 dimension scale dataset*/
    hid_t dset_cpl                   = H5P_DEFAULT; /* HDF5 dataset creation property list ID */

    /* Obtain a pointer of HDF4 to HDF5 ID. This is for accessing the global table member. */
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);

    /* Obtain the HDF5 file ID */
    h5_fileid = h4toh5id_ptr->file5_id;

    /*Assign HDF5 dimension scale size. When this dimension is unlimited dimension,
        we should assign HDF5 maximum dimension size to be H5S_UNLIMITED. */
    h5dimscas[0] = sdsdim_size;
    if(unlimited_dim == 1)
        max_h5dimscas[0] = H5S_UNLIMITED;
    else
        max_h5dimscas[0] = h5dimscas[0];

    /* Create data space for the HDF5 dimension scale dataset. */
    h5dim_sid = H5Screate_simple(1,h5dimscas,max_h5dimscas);
    if(h5dim_sid <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 space ",
                                            __FILE__,__LINE__);
        return FAIL;
    }

    /* create dataset creation property list. */
    dset_cpl = H5Pcreate(H5P_DATASET_CREATE);
    if(dset_cpl < 0) {
        H4toH5error_set(h4toh5id_ptr,3,
                                            "fail to create HDF5 property list",
                                            __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        return FAIL;
    }

    /* For unlimited dimension, we need to create a chunked dataset */
    if(max_h5dimscas[0] == H5S_UNLIMITED) {

       /* If the dimension size is too small, we make the chunk size to be the library
            default one(512), it may still be too small, we will improve in the future.
            Depending on the use case, deflate compression can be added later. */
       if(h5dimscas[0]<H4H5_DEFAULT_NUMELEM_IN_CHUNK)
               h5dim_chunkdim[0] = H4H5_DEFAULT_NUMELEM_IN_CHUNK;
       else
               h5dim_chunkdim[0] = h5dimscas[0];

       if(H5Pset_chunk(dset_cpl,1, h5dim_chunkdim)<0) {
            H4toH5error_set(h4toh5id_ptr,3,
                               "unable to set property list for chunking",
                               __FILE__,__LINE__);
            H5Sclose(h5dim_sid);
            H5Pclose(dset_cpl);
            return FAIL;
       }

    }

    /* Check the size of the absolute path of the HDF5 dimension scale dataset, it should be at least /?, ?
         is an ASCII instance allowed by HDF5 */
    if(strlen(h5dim_abo_path) <3) {
        H4toH5error_set(h4toh5id_ptr,4,
                        "The size of the abosolute path of the HDF5 dimension should be at least 2.",
                         __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }


    /* Create the fake dimension scale dataset, use HDF5 native int as the datatype.
         This follows the way how netCDF-4 handles such a case.*/
    /* Note we don't need to provide relative path for the dataset name in this case,
         since the NAME attribute will be rewritten to follow the netCDF-4 model. */
    h5scale_id = H5DCREATE(h5_fileid,h5dim_abo_path,H5T_NATIVE_INT,h5dim_sid,dset_cpl);
    if (h5scale_id < 0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to create HDF5 dataset for SDS's fakedim",
                        __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }

    if(H5DSset_scale(h5scale_id,h5dim_abo_path)<0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to create HDF5 dataset for SDS's fakedim",
                         __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5scale_id);
        return FAIL;
    }

    /* Here we need to follow netCDF-4 to change the attribute "NAME" to
         reflect that this is a fake dimension that doesn't have dimension scale. */
    if(change_dim_attr_NAME_value(h4toh5id, h5scale_id)<0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to change the value for the attribute NAME of the HDF5 fake dimension",
                         __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5scale_id);
        return FAIL;
    }

    H5Sclose(h5dim_sid);
    H5Pclose(dset_cpl);

    return h5scale_id;
}

/****************create_pure_dim_scale*******************************
* Function:         create_prue_dim_scale
* Purpose:          create HDF5 dimension scale dataset for a user-defined dimension that doesn't have a scale
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                    h4toh5id:                    h4toh5 interface identifier
                     sdsdim_id:               SDS dimension ID
*                    h5dim_abo_path:      The absolute path of the HDF5 dimension scale converted from SDS
                     sds_dtype:               SDS data type
                     sds_firstdimsize:  The size of the first dimension of this SDS
                                                          (for unlimited dimension, the current dim. size is used.)
                     unlimited_dim:       Is this dimension an unlimited dimension?
*-------------------------------------------------------------------------
*/


hid_t create_pure_dim_scale(hid_t h4toh5id,
                            int sdsdim_id,
                            const char* h5dim_abo_path,
                            int sds_dtype,
                            int sds_firstdimsize,
                            short unlimited_dim){

    h4toh5id_t* h4toh5id_ptr     = NULL; /* a pointer to h4toh5 id*/
    hid_t h5_fileid              = -1; /* a temporary HDF5 file ID */
    hid_t sh5_dimtype                = 0;
    hid_t sh5_dimmemtype             = 0;
    size_t sh4_dimmemsize            = 0;
    size_t sh4_dimsize               = 0;
    int32 istat                      = -1;

    int32       sdsdim_type              = 0; /* SDS dimensional scale data type */
    int32       sds_dimscasize[1]; /* the size of SDS dimensional scale */
    char        sdsdim_name[H4H5_MAX_NC_NAME+1]; /* SDS dimensional name */
    int32       num_sdsdimattrs      = 0; /* number of SDS dimensional scale attributes */
    int dim_attr_index               = 0; /* Dimension attribute index */

    hid_t h5_dsetid                      = -1; /* HDF5 dataset ID */
    hsize_t h5dim_chunkdim[1]; /* Chunk size for this dimension. */
    hsize_t h5dimscas[1]; /* the size of the HDF5 "dimensional scale" */
    hsize_t max_h5dimscas[1]; /* the maximum size of the HDF5 "dimensional scale" */
    hid_t h5dim_sid                      = -1;  /* HDF5 dimension space ID */
    hid_t dset_cpl                       = H5P_DEFAULT; /* HDF5 dataset creation property list ID */

    /* Obtain H4toH5 id pointer and HDF5 file ID */
    h4toh5id_ptr = H4TOH5I_object(h4toh5id);
    h5_fileid = h4toh5id_ptr->file5_id;

    /* Check the size of the absolute path of the HDF5 dimension scale dataset, it should be at least /?, ?
         is an ASCII instance allowed by HDF5 */
    if(strlen(h5dim_abo_path) < 3) {
        H4toH5error_set(h4toh5id_ptr,1,"The length of the absolute name of the dimension is at least 2.",
                                        __FILE__,__LINE__);
        return FAIL;
    }
    /*get the information of this dimensional scale*/
    istat = SDdiminfo(sdsdim_id,sdsdim_name,sds_dimscasize,
                                        &sdsdim_type,&num_sdsdimattrs);
    if (istat == FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot obtain SDS dimension information",
                                        __FILE__,__LINE__);
        return FAIL;
    }

    /* create HDF5 pure dimension,for unlimited dimension, use the current dimension size. */
    if(sds_dimscasize[0] == 0)
        h5dimscas[0] = sds_firstdimsize;
    else
        h5dimscas[0] = sds_dimscasize[0];

    if(unlimited_dim == 1)
        max_h5dimscas[0] = H5S_UNLIMITED;
    else
        max_h5dimscas[0] = h5dimscas[0];

    /* Create HDF5 data space. */
    h5dim_sid = H5Screate_simple(1,h5dimscas,max_h5dimscas);
    if(h5dim_sid <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 space ",
                        __FILE__,__LINE__);
        return FAIL;
    }

    /* create property list. */
    dset_cpl = H5Pcreate(H5P_DATASET_CREATE);
    if(dset_cpl == -1) {
        H4toH5error_set(h4toh5id_ptr,2,
                        "fail to create HDF5 property list",
                         __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        return FAIL;
    }

     /* For unlimited dimension, we need to create a chunked dataset */
    if(max_h5dimscas[0] == H5S_UNLIMITED) {

        /* If the dimension size is too small, we make the chunk size to be the library
             default one(512), it may still be too small, we will improve in the future.
             Depending on the use case, deflate compression can be added later. */
        if(h5dimscas[0]<H4H5_DEFAULT_NUMELEM_IN_CHUNK)
            h5dim_chunkdim[0] = H4H5_DEFAULT_NUMELEM_IN_CHUNK;
        else
            h5dim_chunkdim[0] = h5dimscas[0];

        if(H5Pset_chunk(dset_cpl,1, h5dim_chunkdim)<0) {
            H4toH5error_set(h4toh5id_ptr,3,
                                        "unable to set property list for chunking",
                                        __FILE__,__LINE__);
            H5Sclose(h5dim_sid);
            H5Pclose(dset_cpl);
            return FAIL;
        }

    }

    /* convert HDF4 attribute data type to HDF5 attribute data type. */
    if(h4type_to_h5type(h4toh5id,sds_dtype,&sh5_dimmemtype,&sh4_dimmemsize,
                                                &sh4_dimsize,&sh5_dimtype)== FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot convert SDS attribute data type from H4 to H5",
                                        __FILE__,__LINE__);
        return FAIL;
    }

    /* Create HDF5 dimension scale dataset */
//printf("dim path is %s\n",h5dim_abo_path);
    h5_dsetid = H5DCREATE(h5_fileid,h5dim_abo_path,sh5_dimtype,h5dim_sid,dset_cpl);
    if (h5_dsetid < 0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to create HDF5 dataset for SDS's fakedim",
                        __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        return FAIL;
    }

    /* Convert HDF5 dimension scale attributes to HDF5 */
    for (dim_attr_index = 0; dim_attr_index <num_sdsdimattrs;dim_attr_index++) {
         /* Handle dimension attribute conversion */
        if(sds_dimscale_transattr(h4toh5id,sdsdim_id,h5_dsetid,dim_attr_index) < 0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot convert SDS dimension scale attributes successfully",
                                                                 __FILE__,__LINE__);
            H5Sclose(h5dim_sid);
            H5Pclose(dset_cpl);
            H5Dclose(h5_dsetid);
            return FAIL;
        }

    }

    if(H5DSset_scale(h5_dsetid,h5dim_abo_path)<0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to create HDF5 dataset for SDS's fakedim",
                         __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5_dsetid);
        return FAIL;

    }

    /* Here we need to follow netCDF-4 to change the attribute "NAME" to
         reflect that this is a fake dimension that doesn't have dimension scale. */
    if(change_dim_attr_NAME_value(h4toh5id, h5_dsetid)<0) {
        H4toH5error_set(h4toh5id_ptr,3,
                        "unable to change the value for the attribute NAME of the HDF5 fake dimension",
                             __FILE__,__LINE__);
        H5Sclose(h5dim_sid);
        H5Pclose(dset_cpl);
        H5Dclose(h5_dsetid);
        return FAIL;
    }

    H5Sclose(h5dim_sid);
    H5Pclose(dset_cpl);
    return h5_dsetid;
}

/****************sds_dimscale_transattr*******************************
* Function:         sds_dimscale_transattr
* Purpose:          Convert the attributes of the SDS dimension to HDF5 attributes
*
* Return:               FAIL if failed, SUCCEED if successful.
*
* In :
*                     h4toh5id:                    h4toh5 interface identifier
                      sdsdim_id:               SDS dimension ID
                      attr_index:              The index of this dimension attribute
                      dim_index:               The index of this dimension attribute
*-------------------------------------------------------------------------
*/
int sds_dimscale_transattr(hid_t h4toh5id,int sdsdim_id, hid_t h5_dim_dsetid,int attr_index) {

    h4toh5id_t* h4toh5id_ptr = NULL; /* a pointer to h4toh5 id*/
    char            sdimattr_name[2*H4H5_MAX_NC_NAME]; /* SDS attribute name*/
    char*           sdstempattr_name = NULL; /* a temporary variable to store SDS attribute name */

    int32           count_sdimadata = 0; /* number of elements of SDS attributes.*/
    uint32      temp_countadata = 0; /* temporary variable to describe the number of
                                                            SDS attributes */
    int32           sdim_atype  = 0; /* SDS attribute datatype */

    size_t      sh4_amemsize = 0;/* size of attribute data type in memory. */
    size_t      sh4_asize  = 0;  /* size of attribute data type in disk. */

    hid_t           sh5a_sid = 0; /* HDF5 attribute space id */
    hid_t           sh5a_id  = 0; /* HDF5 attribute id */
    hid_t           sh5_atype= 0; /* HDF5 attribute data type in disk */
    hid_t           sh5_amemtype = 0; /* HDF5 attribute data type in memory */
    hid_t           sh5str_type = 0; /* HDF5 attribute data type in disk when the data type is string. */
    hid_t           sh5str_memtype = 0; /* HDF5 attribute data type in memory when the data type is string. */

    hsize_t     sh5dims[1]; /* HDF5 attribute dimension */
    herr_t      sret = FAIL;             /* the temporary variable to check the "return" status  of
                                                                    HDF5 APIs */

    void*           sdim_adata = NULL; /* attribute data*/

    h4toh5id_ptr = H4TOH5I_object(h4toh5id);

    /* Obtain dimension attribute info. */
    if (SDattrinfo(sdsdim_id,attr_index,sdimattr_name,&sdim_atype,
         &count_sdimadata)==FAIL){
        H4toH5error_set(h4toh5id_ptr,2,"cannot start SD attribute information",
                                        __FILE__,__LINE__);
        return FAIL;
    }

    /* convert HDF4 attribute data type to HDF5 attribute data type. */
    if(h4type_to_h5type(h4toh5id,sdim_atype,&sh5_amemtype,&sh4_amemsize,
            &sh4_asize,&sh5_atype)== FAIL) {
        H4toH5error_set(h4toh5id_ptr,2,"cannot convert SDS dimension attribute data type from H4 to H5",
                                    __FILE__,__LINE__);
        return FAIL;
    }

    if(count_sdimadata != 0) {
        /* allocating memory for SDS attribute data. */
        sdim_adata = malloc(sh4_amemsize * count_sdimadata);
        if(sdim_adata == NULL) {
             H4toH5error_set(h4toh5id_ptr,1,"cannot allocate memory for SDS dimension attribute data",
                                             __FILE__,__LINE__);
             return FAIL;
        }

        /* Read this attribute */
        if(SDreadattr(sdsdim_id,attr_index,(VOIDP)sdim_adata)== FAIL) {
             H4toH5error_set(h4toh5id_ptr,2,"cannot read SDS attribute",
                                         __FILE__,__LINE__);
             free(sdim_adata);
             return FAIL;
        }
    }
    /* if an attribute doesn't have a name, a default name is set. */
    if(sdimattr_name[0] == '\0') {
        sdstempattr_name = trans_obj_name(h4toh5id,DFTAG_NDG,attr_index);
        strncpy(sdimattr_name,sdstempattr_name,sizeof(sdimattr_name));
        free(sdstempattr_name);
    }

    /* now do attribute-transferring.
         1. deal with string data type
         2. set attribute space.
         3. get attribute name, write attribute data*/

    if (sh5_atype == H5T_STRING) {

        sh5a_sid = H5Screate(H5S_SCALAR);
        if (sh5a_sid < 0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 attribute space",
                                     __FILE__,__LINE__);
            if(sdim_adata)
                    free(sdim_adata);
            return FAIL;
        }

        /*Dimension may have an attribute that doesn't have attribute data. */
        if(count_sdimadata != 0){

            temp_countadata = count_sdimadata*sh4_asize;

            /* This comes from general attribute handling routines, perhaps not necessary. */
            H425_CHECK_OVERFLOW(temp_countadata,uint32,size_t);
            if ((sh5str_type = mkstr(h4toh5id,(size_t)temp_countadata,
                                                             H5T_STR_NULLTERM))<0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot make HDF5 string type",
                                                                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                if (sdim_adata)
                        free(sdim_adata);
                return FAIL;
            }

            /* Following the general conversion routines to use NULLTERM,
                 may need to change to NULL TERM in the future. */
            if ((sh5str_memtype = mkstr(h4toh5id,count_sdimadata*sh4_amemsize,
                                                                H5T_STR_NULLTERM))<0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot make hdf5 memory string type",
                                                __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Tclose(sh5str_type);
                if (sdim_adata)
                        free(sdim_adata);
                return FAIL;
            }

            /* H5Acreate_safe is a wrapper function of H5Acreate. It allows the returned attribute ID to be -1*/
            sh5a_id = H5Acreate_safe(h4toh5id,h5_dim_dsetid,sdimattr_name,sh5str_type,
                                                 sh5a_sid,H5P_DEFAULT);
            if (sh5a_id <0) {
                /* H5Acreate() can fail just because this attribute is too long. This could be rejected,
                 * the following code tries to split it. */
                /* The above comments reflected for the HDF5 versions that HDF5 attribute size is limited to 64 K.
                     Now this limitation may be lifted. We will see if it is necessary to do in the future. We will
                     still keep the current way for the backward compatiability. Also the dimension attribute
                     may never come to this routine. KY 2014-06-17*/
                if (transattrs_split(h4toh5id, h5_dim_dsetid, sdimattr_name, sh5a_sid, sdim_adata, count_sdimadata) < 0) {
                            H4toH5error_set(h4toh5id_ptr,3,"cannot create hdf5 attribute id",
                                                                             __FILE__,__LINE__);
                        H5Sclose(sh5a_sid);
                        H5Tclose(sh5str_type);
                        H5Tclose(sh5str_memtype);
                        if (sdim_adata)
                                free(sdim_adata);
                        return FAIL;
                }
            }
            else if (sdim_adata != NULL) {
                sret = H5Awrite(sh5a_id,sh5str_memtype,(void *)sdim_adata);
                if (sret <0) {
                    H4toH5error_set(h4toh5id_ptr,3,"cannot write hdf5 attribute",
                                                    __FILE__,__LINE__);
                    H5Sclose(sh5a_sid);
                    H5Tclose(sh5str_type);
                    H5Tclose(sh5str_memtype);
                    H5Aclose(sh5a_id);
                    if (sdim_adata)
                            free(sdim_adata);
                    return FAIL;
                }
            }

            H5Tclose(sh5str_type);
            H5Tclose(sh5str_memtype);

        }
        else {/* treat the number of data as 1 for empty attribute*/

            if ((sh5str_type = mkstr(h4toh5id,(size_t)1*sh4_asize,
                                                         H5T_STR_NULLTERM))<0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot make HDF5 string type",
                                                                             __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                if (sdim_adata)
                        free(sdim_adata);
                return FAIL;
            }

            if ((sh5str_memtype = mkstr(h4toh5id,1*sh4_amemsize,
                                                                H5T_STR_NULLTERM))<0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot make hdf5 memory string type",
                                                                        __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Tclose(sh5str_type);
                if (sdim_adata)
                        free(sdim_adata);
                return FAIL;
            }

            sh5a_id = H5Acreate_safe(h4toh5id,h5_dim_dsetid,sdimattr_name,sh5str_type,
                                                     sh5a_sid,H5P_DEFAULT);
            if (sh5a_id <0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot create hdf5 attribute id",
                                                __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Tclose(sh5str_type);
                H5Tclose(sh5str_memtype);
                if (sdim_adata)
                        free(sdim_adata);
                return FAIL;
            }

            H5Tclose(sh5str_type);
            H5Tclose(sh5str_memtype);
        }

        H5Sclose(sh5a_sid);

        /* An HDF4 attribute could be converted into an HDF5 attribute. */
        if (sh5a_id >= 0)
            sret = H5Aclose(sh5a_id);
    }

    else {/* Non-string attributes. */

        if(count_sdimadata == 0) {
            H4toH5error_set(h4toh5id_ptr,3,"the attribute data must not be none",
                                                                            __FILE__,__LINE__);
            if (sdim_adata) free(sdim_adata);
            return FAIL;
        }
        sh5dims[0] = count_sdimadata;
        sh5a_sid =  H5Screate_simple(1,sh5dims,NULL);

        if (sh5a_sid < 0)  {
            H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 attribute space",
                                            __FILE__,__LINE__);
            if (sdim_adata) free(sdim_adata);
            return FAIL;
        }

        sh5a_id = H5Acreate_safe(h4toh5id,h5_dim_dsetid,sdimattr_name,sh5_atype,
                                                         sh5a_sid,H5P_DEFAULT);
        if(sh5a_id <0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot create HDF5 attribute id",
                                            __FILE__,__LINE__);
            H5Sclose(sh5a_sid);
            if (sdim_adata) free(sdim_adata);
            return FAIL;
        }

        if (sdim_adata) {
            sret = H5Awrite(sh5a_id,sh5_amemtype,(void *)sdim_adata);
            if(sret <0) {
                H4toH5error_set(h4toh5id_ptr,3,"cannot write HDF5 attribute",
                                                __FILE__,__LINE__);
                H5Sclose(sh5a_sid);
                H5Aclose(sh5a_id);
                if (sdim_adata) free(sdim_adata);
                return FAIL;
            }
        }

        sret = H5Sclose(sh5a_sid);
        if(sret < 0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot close HDF5 space",
                                            __FILE__,__LINE__);
            H5Aclose(sh5a_id);
            if (sdim_adata) free(sdim_adata);
            return FAIL;
        }
        sret = H5Aclose(sh5a_id);
        if(sret < 0) {
            H4toH5error_set(h4toh5id_ptr,3,"cannot close HDF5 attribute interface ",
                                            __FILE__,__LINE__);
            if (sdim_adata) free(sdim_adata);
            return FAIL;
        }
    }
    if(count_sdimadata !=0)
        if (sdim_adata) free(sdim_adata);

    return SUCCEED;
}

/****************change_dim_attr_NAME_value*******************************
 * * Function:         change_dim_attr_NAME_value
 * * Purpose:          change dimension NAME attribute value to follow the netCDF-4 data model
 * *
 * * Return:               FAIL if failed, SUCCEED if successful.
 * *
* In :
*   h4toh5id:                    h4toh5 interface identifier
    h5dset_id:               HDF5 dataset ID this attribute is attached.
*-------------------------------------------------------------------------
*/


int change_dim_attr_NAME_value(hid_t h4toh5id, hid_t h5dset_id) {

    h4toh5id_t* h4toh5id_ptr = NULL;
    hid_t tid = -1;
    hid_t sid = -1;
    hid_t aid = -1;

    /* Assign the attribute value for NAME to follow netCDF-4 data model. */
    char attr_value[] = "This is a netCDF dimension but not a netCDF variable.";

    h4toh5id_ptr = H4TOH5I_object(h4toh5id);

    /* Delete the original attribute. */
    if(H5Adelete(h5dset_id,"NAME") <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
            __FILE__,__LINE__);
        return FAIL;
    }

    if((tid = H5Tcopy(H5T_C_S1)) <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                         __FILE__,__LINE__);
        return FAIL;
    }

    if (H5Tset_size(tid, strlen(attr_value) + 1) <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                         __FILE__,__LINE__);
        H5Tclose(tid);
        return FAIL;
    }

    if (H5Tset_strpad(tid, H5T_STR_NULLTERM) <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                         __FILE__,__LINE__);
        H5Tclose(tid);
        return FAIL;
    }
    if((sid = H5Screate(H5S_SCALAR))<0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                         __FILE__,__LINE__);
        H5Tclose(tid);
        return FAIL;
    }

    /* Create and write a new attribute. */
    if ((aid = H5ACREATE(h5dset_id, "NAME", tid, sid, H5P_DEFAULT)) < 0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                            __FILE__,__LINE__);
        H5Tclose(tid);
        H5Sclose(sid);
        return FAIL;
    }

    if (H5Awrite(aid, tid, (void*)attr_value) <0) {
        H4toH5error_set(h4toh5id_ptr,3,"cannot delete HDF5 attribute NAME",
                         __FILE__,__LINE__);
        H5Tclose(tid);
        H5Sclose(sid);
        H5Aclose(aid);
        return FAIL;
    }


    if (aid != -1)
         H5Aclose(aid);
    if (sid != -1)
         H5Sclose(sid);
    if (tid != -1)
         H5Tclose(tid);

    return SUCCEED;

}
/****************check_sds_equ_dim*******************************
 * * Function:         check_sds_equ_dim
 * * Purpose:          check whether this sds can be used as this dimension's scale
 * *
 * * Return:               FAIL if failed, SUCCEED if successful.
 * *
* In :
*   h4toh5id:                    h4toh5 interface identifier
    sd_id:               SD interface ID.
    sdsdim_name:         SDS dimension name
    sds_dimtype:         SDS dimension scale type
    sds_dimscale_size    SDS dimension scale size
*-------------------------------------------------------------------------
*/


int8 check_sds_equ_dim(hid_t h4toh5id, int32 sd_id, const char* sdsdim_name,int sds_dimtype,int sds_dimscale_size) {

    int32       sds_dtype; /* SDS data type */
    int32       sds_rank; /* SDS rank */
    int32       sds_dimsizes[H4H5_MAX_VAR_DIMS];/* SDS dimensional scale size */
    int32       num_sdsattrs; /* number of SDS attributes */
    char        sdsname[H4H5_MAX_NC_NAME];/* SDS name */

    int32 sds_index = SDnametoindex(sd_id,sdsdim_name);
    if(sds_index == FAIL) {
        H4toH5error_set2(h4toh5id,2,"SDnametoindex API Failed. ",sdsdim_name,__FILE__,__LINE__);
        return FAIL;
    }

    int32 sds_id = SDselect(sd_id,sds_index);
    if(sds_id == FAIL) {
        H4toH5error_set2(h4toh5id,2,"SDselect API Failed. ",sdsdim_name,__FILE__,__LINE__);
        return FAIL;
    }


    /* using SDS "getinfo" API to get all the information of this SDS object.*/
    if (SDgetinfo(sds_id,sdsname,&sds_rank,sds_dimsizes,&sds_dtype,
        &num_sdsattrs)==FAIL) {
        H4toH5error_set2(h4toh5id,2,"fail to get SDS information",sdsname,
                __FILE__,__LINE__);
        return FAIL;
    }

    /* return 2 since 1 is used to indicate another special case.   */
    if(sds_rank == 1 && sds_dtype == sds_dimtype && sds_dimsizes[0] == sds_dimscale_size)
        return 2;

    return 0;
}

