/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * 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 lib 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 do not 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 

two sets of APIs:

2.1. convert hdf4 file annotation to the global attribute of hdf5 file
2.1.1. convert one annotation label to an attribute of hdf5 file.
2.1.2. convert one annotation description to an attribute of the hdf5 file.
2.1.3. convert all annotation labels to attributes of the hdf5 file.
2.1.4. convert all annotation descriptions to attributes of the hdf5 file.

2.2. convert hdf4 object annotation to the hdf5 attribute of the corresponding object

HDF4 object includes : SDS,image,independent vdata, vgroup,palette
2.2.1. convert one annotation label to an attribute of hdf5 object.
2.2.2. convert one annotation description to an attribute of the hdf5 object.
2.2.3. convert all annotation labels to attributes of the hdf5 object.
2.2.4. convert all annotation descriptions to attributes of the hdf5 object.

Author:  Kent Yang(myang6@hdfgroup.org)
 

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

#include "h4toh5main.h"
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_file_label
 *
 * Purpose:     translate file annotation object into hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5  identifier
        anno_labelname: annotation label name
                        (can be set to NULL by default)
        label_index: the index of the annotation label
    *-------------------------------------------------------------------------
 */     

int H4toH5anno_file_label(hid_t h4toh5_id,
            char* anno_labelname,
            int label_index)
{

    hid_t        h5_file; /* HDF5 file id */
    hid_t        h5_root; /* HDF5 root group id */
    int32        an_id;  /* AN interface id */
    int32        ann_id; /* annotation id */
    int32        file_id; /* HDF file id */
    int32        ann_length; /* annotation length */
    uint32   temp_length; /* temporary variable to store annotation length */

    int32        n_file_label = 0; /* number of file labels*/
    int32        n_file_desc    = 0; /* number of file descriptions*/
    int32        n_data_label = 0; /* number of data labels. */
    int32        n_data_desc    = 0; /* number of data descriptions. */

    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/
    char*        ann_buf; /* character array to store annotation buffer. */
    char*        new_annolabelname = NULL; /* annotation label name. */
    char         index_str[MAXREF_LENGTH]; /* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype; /* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */

    h4toh5id_t* temph4toh5id; /*pointer to temporary h4toh5 id. */

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

    /* obtain HDF4 annotation information */
    file_id = temph4toh5id->file_id;
    an_id        = ANstart(file_id);
    if(an_id < 0) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }

    if(label_index < 0 && label_index >=n_file_label) {
         H4toH5error_set(temph4toh5id,5,
             "file label index is not valid",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }

    ann_id       = ANselect(an_id,label_index,AN_FILE_LABEL);
    if(ann_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot obtain annotation id",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }
            
    ann_length = ANannlen(ann_id);
    if(ann_length == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        return FAIL;
    }

    ann_buf      = malloc((ann_length + 1)*sizeof(int8));
    if(ann_buf == NULL) {
        H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        return FAIL;
    }

    h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(char));
    istat            = ANreadann(ann_id,ann_buf,ann_length+1);
    if(istat==FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }
 
    istat  = ANendaccess(ann_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot end annotation interface",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }

    h5_sid       = H5Screate(H5S_SCALAR);
    if (h5_sid < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }

    temp_length = ann_length + 1;
    H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
    if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
        ANend(file_id);
        H5Sclose(h5_sid);
        free(ann_buf);
        return FAIL;
    }
    
    temp_length  = (ann_length+1)*sizeof(int8);
    H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
    if((sh5str_memtype = mkstr(h4toh5_id,(size_t)temp_length,
                     H5T_STR_NULLTERM))<0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type for memory",
             __FILE__,__LINE__);
        ANend(file_id);
        H5Sclose(h5_sid);
        free(ann_buf);
        return FAIL;
    }
    if(conv_int_str(h4toh5_id,(uint32)label_index,index_str) == FAIL) {
        H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
        H5Sclose(h5_sid);
        ANend(file_id);
        free(ann_buf);
        return FAIL;                    
    }

    if(anno_labelname == NULL) {
        new_annolabelname = malloc(strlen(HDF4_FILE_LABEL)+strlen(index_str)+2);
        if(new_annolabelname == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation label name",
             __FILE__,__LINE__);
            H5Sclose(h5_sid);
            ANend(file_id);
            free(ann_buf);
            return FAIL; 
        }
        strcpy(new_annolabelname,HDF4_FILE_LABEL);
        strcat(new_annolabelname,"_");
        strcat(new_annolabelname,index_str);
    }

    /* write file label to HDF5 attribute. */
    h5_file = temph4toh5id->file5_id;
    if (h5_file < 0) {
        H4toH5error_set(temph4toh5id,3,
             "fail to create HDF5 file id",
             __FILE__,__LINE__);
        H5Sclose(h5_sid);
        ANend(file_id);
        free(new_annolabelname);
        free(ann_buf);
        return FAIL;
    }

    h5_root = H5GOPEN(h5_file,"/");
    if(h5_root <0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 root group",
             __FILE__,__LINE__);
        ANend(file_id);
        H5Sclose(h5_sid);
        free(new_annolabelname);
        free(ann_buf);
        return FAIL;
    }

    if(anno_labelname != NULL)
        h5_aid = H5Acreate_safe(h4toh5_id, h5_root,anno_labelname,sh5str_type,
                     h5_sid,H5P_DEFAULT);
    else
        h5_aid = H5Acreate_safe(h4toh5_id, h5_root,new_annolabelname,sh5str_type,
                     h5_sid,H5P_DEFAULT);

    if (h5_aid < 0) {
        if (transattrs_split(h4toh5_id, h5_root, anno_labelname ? anno_labelname : new_annolabelname, h5_sid, ann_buf, temp_length) < 0) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot obtain HDF5 attribute ID",
                 __FILE__,__LINE__);
            ANend(file_id);
            H5Sclose(h5_sid);
            H5Gclose(h5_root);
            free(ann_buf);
            if(anno_labelname == NULL)
                free(new_annolabelname);
            return FAIL;
        }
    }
    else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
        ANend(file_id);
        H5Sclose(h5_sid);
        H5Aclose(h5_aid);
        free(ann_buf);
        if(anno_labelname == NULL)
            free(new_annolabelname);
        H5Gclose(h5_root);
        return FAIL;
    }

    free(ann_buf);
    if(anno_labelname == NULL)
        free(new_annolabelname);

    istat = ANend(file_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
        H5Sclose(h5_sid);
        H5Aclose(h5_aid);
        H5Gclose(h5_root);
        return FAIL;
    }
        
    ret     = H5Sclose(h5_sid);
    if (ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        H5Aclose(h5_aid);
        H5Gclose(h5_root);
        return FAIL;
    }

    if (h5_aid >= 0) {
        ret     = H5Aclose(h5_aid);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot close HDF5 data space interface",
                 __FILE__,__LINE__);
            H5Gclose(h5_root);
            return FAIL;
        }
    }
    
    ret     = H5Gclose(h5_root);
    if (ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    return SUCCEED;
}

 

/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_file_desc
 *
 * Purpose:     translate file annotation description into the attribute of 
                                HDF5 root group 
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5 identifier
        anno_descname: annotation desc name(can be set to NULL by default)
        desc_index: the index of the annotation desc
    *-------------------------------------------------------------------------
 */     

int H4toH5anno_file_desc(hid_t h4toh5_id,
                     char* anno_descname,
                     int     desc_index)
{

    hid_t        h5_file; /* HDF5 file id */
    hid_t        h5_root; /* HDF5 root id */
    int32        an_id; /* AN interface  id */
    int32        ann_id; /* annotation id */
    int32        file_id; /* HDF file id */
    int32        ann_length; /* annotation length */
    uint32   temp_length; /* temporary variable of annotation length */

    int32        n_file_label = 0; /* number of file labels*/
    int32        n_file_desc    = 0; /* number of file descriptions*/
    int32        n_data_label = 0; /* number of data labels. */
    int32        n_data_desc    = 0; /* number of data descriptions. */

    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/
    char*        ann_buf; /* character array to store annotation buffer. */
    char*        new_annodescname = NULL; /* annotation description name. */
    char         index_str[MAXREF_LENGTH]; /* a temporary variable to store the
                             string format of decimal index. */


    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype; /* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */

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

    /* obtain global table*/
    temph4toh5id = H4TOH5I_object(h4toh5_id);
    file_id = temph4toh5id->file_id;
    an_id        = ANstart(file_id);
    if(an_id < 0) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    /* obtain annotation information. */
    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }


    if(desc_index < 0 && desc_index >=n_file_desc) {
        H4toH5error_set(temph4toh5id,5,
             "file description index is not valid",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }

    /* obtain annotation */
    ann_id       = ANselect(an_id,desc_index,AN_FILE_DESC);
    if(ann_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot obtain annotation id",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }
            
    ann_length = ANannlen(ann_id);
    if(ann_length == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        return FAIL;
    }

    ann_buf      = malloc((ann_length + 1)*sizeof(int8));
    if(ann_buf == NULL) {
        H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        return FAIL;
    }
    h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(char));
    istat            = ANreadann(ann_id,ann_buf,ann_length+1);

    if(istat==FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
        ANendaccess(ann_id);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }
    istat = ANendaccess(ann_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot end annotation interface",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }


    /* write file description annotation to HDF5 attribute. */
    h5_sid       = H5Screate(H5S_SCALAR);
    if (h5_sid < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        return FAIL;
    }

    temp_length = ann_length + 1;
    H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
    if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        H5Sclose(h5_sid);
        return FAIL;
    }

    if((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),
                     H5T_STR_NULLTERM))<0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type for memory",
             __FILE__,__LINE__);
         ANend(file_id);
        H5Sclose(h5_sid);
        free(ann_buf);
        return FAIL;
    }

    if(conv_int_str(h4toh5_id,(uint32)desc_index,index_str)== FAIL) {
        H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        H5Sclose(h5_sid);
        return FAIL;                    
    }

    if(anno_descname == NULL) {
        new_annodescname = malloc(strlen(HDF4_FILE_DESC)+strlen(index_str)+2);
        H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation desc. name",
             __FILE__,__LINE__);
        strcpy(new_annodescname,HDF4_FILE_DESC);
        strcat(new_annodescname,"_");
        strcat(new_annodescname,index_str);
    }

    h5_file = temph4toh5id->file5_id;
    if (h5_file < 0) {
         H4toH5error_set(temph4toh5id,3,
             "fail to create HDF5 file id",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        H5Sclose(h5_sid);
        if(anno_descname == NULL)
            free(new_annodescname);
        return FAIL;
    }

    h5_root = H5GOPEN(h5_file,"/");

    if(h5_root <0) {
         H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 root group",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        H5Sclose(h5_sid);
        if(anno_descname == NULL)
            free(new_annodescname);
        return FAIL;
    }

    if(anno_descname != NULL)
        h5_aid = H5Acreate_safe(h4toh5_id, h5_root,anno_descname,sh5str_type,
                     h5_sid,H5P_DEFAULT);
    else
        h5_aid = H5Acreate_safe(h4toh5_id, h5_root,new_annodescname,sh5str_type,
                     h5_sid,H5P_DEFAULT);

    if (h5_aid < 0) {
        if (transattrs_split(h4toh5_id, h5_root, anno_descname ? anno_descname : new_annodescname, h5_sid, ann_buf, temp_length) < 0) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot obtain HDF5 attribute ID",
                 __FILE__,__LINE__);
            ANend(file_id);
            H5Sclose(h5_sid);
            H5Gclose(h5_root);
            free(ann_buf);
            if(anno_descname == NULL)
                free(new_annodescname);
            return FAIL;
        }
    }
    else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
        ANend(file_id);
        free(ann_buf);
        if(anno_descname == NULL)
            free(new_annodescname);
        H5Sclose(h5_sid);
        H5Aclose(h5_aid);
        H5Gclose(h5_root);
        return FAIL;
    }

    free(ann_buf);
    if(anno_descname == NULL)
        free(new_annodescname);

    istat = ANend(file_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
        H5Sclose(h5_sid);
        H5Aclose(h5_aid);
        H5Gclose(h5_root);
        return FAIL;
    }
        
    ret     = H5Sclose(h5_sid);
    if (ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        H5Aclose(h5_aid);
        H5Gclose(h5_root);
        return FAIL;
    }

    if (h5_aid >= 0) {
        ret = H5Aclose(h5_aid);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
                 "cannot close HDF5 data space interface",
                 __FILE__,__LINE__);
            H5Gclose(h5_root);
            return FAIL;
        }
    }
    
    ret     = H5Gclose(h5_root);
    if (ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    return SUCCEED;
}


/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_file_all_labels
 *
 * Purpose:     translate all file annotation labels into hdf5 attributes of root group
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
            h4toh5_id: h4toh5  identifier
    *-------------------------------------------------------------------------
 */     

int H4toH5anno_file_all_labels(hid_t h4toh5_id)
{

    hid_t        h5_file; /* HDF5 file id */
    hid_t        h5_root; /* HDF5 root group id */
    int32        an_id; /* AN interface id */
    int32        ann_id; /* annotation id */
    int32        i; /* an index */
    int32        file_id; /* HDF file id */
    int32        ann_length; /* annotation length */
    uint32   temp_length; /* temporary variable of annotation length */

    int32        n_file_label = 0; /* number of file labels*/
    int32        n_file_desc    = 0; /* number of file descriptions*/
    int32        n_data_label = 0; /* number of data labels. */
    int32        n_data_desc    = 0; /* number of data descriptions. */

    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/
    char*        ann_buf; /* character array to store annotation buffer. */
    char*        new_annolabelname; /* annotation label name. */
    char         index_str[MAXREF_LENGTH]; /* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype; /* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */

    h4toh5id_t* temph4toh5id; /*pointer to temporary h4toh5 id. */

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

    /* obtain HDF4 annotation information */
    file_id = temph4toh5id->file_id;
    an_id        = ANstart(file_id);
    if(an_id < 0) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(an_id);
        return FAIL;
    }

    /* obtain file id, group id and space id;
         and write file labels to HDF5 attributes. */
    h5_file = temph4toh5id->file5_id;
    h5_root = H5GOPEN(h5_file,"/");

    if(h5_root <0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 root group",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }

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

        ann_id       = ANselect(an_id,i,AN_FILE_LABEL);
        if(ann_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain annotation id",
             __FILE__,__LINE__);
            ANend(file_id);
            H5Gclose(h5_root);
            return FAIL;
        }
            
        ann_length = ANannlen(ann_id);
        if(ann_length == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(file_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        ann_buf      = malloc((ann_length + 1)*sizeof(int8));
        if(ann_buf == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(file_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        temp_length = (ann_length+1)*sizeof(char);
        H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
        h4toh5_ZeroMemory(ann_buf,temp_length);

        istat            = ANreadann(ann_id,ann_buf,ann_length+1);
        if(istat==FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(file_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }
 
        istat  = ANendaccess(ann_id);
        if(istat==FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "Anendaccess failed",
             __FILE__,__LINE__);
            ANend(file_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }
 
        h5_sid       = H5Screate(H5S_SCALAR);

        if (h5_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
            ANend(file_id);
            H5Gclose(h5_root);
            free(ann_buf);
            return FAIL;
        }

        temp_length = ann_length + 1;
        H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
            ANend(file_id);
            H5Sclose(h5_sid);
            H5Gclose(h5_root);
            free(ann_buf);
            return FAIL;
        }

        if((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),
                         H5T_STR_NULLTERM))<0) {
             H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type for memory",
             __FILE__,__LINE__);
             ANend(file_id);
             H5Sclose(h5_sid);
             free(ann_buf);
             return FAIL;
        }
        if(conv_int_str(h4toh5_id,(uint32)i,index_str)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
            ANend(file_id);
            H5Sclose(h5_sid);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;                    
        }

        new_annolabelname = malloc(strlen(HDF4_FILE_LABEL)+strlen(index_str)+2);
        if(new_annolabelname == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation label name",
             __FILE__,__LINE__);
            H5Sclose(h5_sid);
            ANend(file_id);
            free(ann_buf);
            return FAIL; 

        }
        strcpy(new_annolabelname,HDF4_FILE_LABEL);
        strcat(new_annolabelname,"_");
        strcat(new_annolabelname,index_str);
 
        h5_aid = H5Acreate_safe(h4toh5_id, h5_root,new_annolabelname,sh5str_type,
                     h5_sid,H5P_DEFAULT);

        if (h5_aid < 0) {
            if (transattrs_split(h4toh5_id, h5_root, new_annolabelname, h5_sid, ann_buf, temp_length) < 0) {
                H4toH5error_set(temph4toh5id,3,
                    "cannot obtain HDF5 attribute ID",
                       __FILE__,__LINE__);
                ANend(file_id);
                H5Sclose(h5_sid);
                H5Gclose(h5_root);
                free(ann_buf);
                free(new_annolabelname);
                return FAIL;
            }
        }
        else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
            H4toH5error_set(temph4toh5id,3,
                "cannot write HDF5 attribute data",
                __FILE__,__LINE__);
            ANend(file_id);
            free(ann_buf);
            free(new_annolabelname);
            H5Sclose(h5_sid);
            H5Aclose(h5_aid);
            H5Gclose(h5_root);
            return FAIL;
        }

        ret     = H5Sclose(h5_sid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
            H5Aclose(h5_aid);
            free(ann_buf);
            free(new_annolabelname);
            ANend(an_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        if (h5_aid >= 0) {
            ret     = H5Aclose(h5_aid);
            if(ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot close HDF5 data space interface",
                 __FILE__,__LINE__);
                free(ann_buf);
                free(new_annolabelname);
                ANend(an_id);
                H5Gclose(h5_root);
                return FAIL;
            }
        }

        free(ann_buf);
        free(new_annolabelname);

    }

    istat = ANend(an_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
        H5Gclose(h5_root);
        return FAIL;
    }

    ret = H5Gclose(h5_root);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_file_all_descs
 *
 * Purpose:         translate file annotation descriptions into hdf5 attributes of root_group
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                                h4toh5_id: h4toh5  identifier
                    
    *-------------------------------------------------------------------------
 */     

int H4toH5anno_file_all_descs(hid_t h4toh5_id)
{

    hid_t        h5_file; /* HDF5 file id */
    hid_t        h5_root; /* HDF5 root group id */
    int32        an_id; /* AN interface id */
    int32        ann_id; /* annotation id */
    int32        i;
    int32        file_id; /* HDF file id */
    int32        ann_length; /* annotation length */
    uint32   temp_length; /* temporary variable to store annotation length */

    int32        n_file_label = 0; /* number of file labels*/
    int32        n_file_desc    = 0; /* number of file descriptions*/
    int32        n_data_label = 0; /* number of data labels. */
    int32        n_data_desc    = 0; /* number of data descriptions. */

    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/
    char*        ann_buf; /* character array to store annotation buffer. */
    char*        new_annodescname; /* annotation description name. */
    char         index_str[MAXREF_LENGTH]; /* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str1_type; /* HDF5 string data type. */
    hid_t        sh5str1_memtype; /* HDF5 string memory data type. */
    hid_t        ret;  /* a temporary variable to check "return" status of HDF5 interfaces. */

    h4toh5id_t* temph4toh5id; /*pointer to temporary h4toh5 id. */

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

    /* obtain HDF4 annotation information */
    file_id = temph4toh5id->file_id;

    an_id        = ANstart(file_id);
    if(an_id < 0) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(file_id);
        return FAIL;
    }

    /* grab HDF5 file and root group id. */
    h5_file = temph4toh5id->file5_id;
    h5_root = H5GOPEN(h5_file,"/");
    if(h5_root <0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 root group",
             __FILE__,__LINE__);
            ANend(file_id);
            return FAIL;
    }

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

        ann_id       = ANselect(an_id,i,AN_FILE_DESC);
        if(ann_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain annotation id",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        ann_length = ANannlen(ann_id);
        
        if(ann_length == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
            ANend(an_id);
            ANendaccess(ann_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        ann_buf      = malloc((ann_length+1)*sizeof(int8));
        if(ann_buf == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
            ANend(an_id);
            ANendaccess(ann_id);
            H5Gclose(h5_root);
            return FAIL;
        }
        h4toh5_ZeroMemory(ann_buf,(size_t)(ann_length+1));
        istat            = ANreadann(ann_id,ann_buf,ann_length+1);
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
            ANend(an_id);
            ANendaccess(ann_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }

        istat = ANendaccess(ann_id);
        if( istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot close annotation interface",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }

        temp_length = ann_length + 1;
        H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
        if ((sh5str1_type = mkstr(h4toh5_id,(uint32)temp_length,H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }
        
        if((sh5str1_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),
                H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type for memory",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }
        if(conv_int_str(h4toh5_id,(uint32)i,index_str)==FAIL) {
             H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }
        
        new_annodescname = malloc(strlen(HDF4_FILE_DESC)+strlen(index_str)+2);
        if(new_annodescname == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation desc name",
             __FILE__,__LINE__);
            H5Gclose(h5_root);
            ANend(an_id);
            free(ann_buf);
            return FAIL; 

        }
        strcpy(new_annodescname,HDF4_FILE_DESC);
        strcat(new_annodescname,"_");
        strcat(new_annodescname,index_str);

        /* obtain HDF5 space id and write annotation to HDF5 attribute. */
        h5_sid       = H5Screate(H5S_SCALAR);
        if (h5_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
            ANend(an_id);
            free(new_annodescname);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }

        h5_aid = H5Acreate_safe(h4toh5_id,h5_root,new_annodescname,sh5str1_type,
                     h5_sid,H5P_DEFAULT);

        if (h5_aid <0) {
            if (transattrs_split(h4toh5_id, h5_root, new_annodescname, h5_sid, ann_buf, temp_length) < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot obtain HDF5 attribute ID",
                 __FILE__,__LINE__);
                ANend(an_id);
                H5Sclose(h5_sid);
                free(new_annodescname);
                free(ann_buf);
                H5Gclose(h5_root);
                return FAIL;
            }
        }
        else if (H5Awrite(h5_aid,sh5str1_memtype,(void *)ann_buf) < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Sclose(h5_sid);
            H5Aclose(h5_aid);
            free(new_annodescname);
            free(ann_buf);
            H5Gclose(h5_root);
            return FAIL;
        }

        ret     = H5Sclose(h5_sid);
        if(ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
            H5Aclose(h5_aid);
            free(ann_buf);
            free(new_annodescname);
            ANend(an_id);
            H5Gclose(h5_root);
            return FAIL;
        }

        if (h5_aid >= 0) {
            ret     = H5Aclose(h5_aid);
            if(ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot close HDF5 data space interface",
                 __FILE__,__LINE__);
                free(ann_buf);
                free(new_annodescname);
                ANend(an_id);
                H5Gclose(h5_root);
                return FAIL;
            }
        }

        free(ann_buf);
        free(new_annodescname);
    }
    istat = ANend(an_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
        H5Gclose(h5_root);
        return FAIL;
    }
    ret     = H5Gclose(h5_root);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_label
 *
 * Purpose:     translate annotation object into attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        anno_labelname: annotation label name
        label_index: annotation label index
    
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_label(hid_t              h4toh5_id,
            char*            h5groupfullpath,
            char*            h5datasetname,
            uint16       obj_ref, 
            int32            obj_tag,
            char*            anno_labelname,
            int              label_index)
{

    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    if(H4toH5anno_obj_label_new(h4toh5_id,h5groupfullpath,h5datasetname,obj_ref,
                                obj_tag,anno_labelname,label_index,H425_OSPEC_ALLATTRS)
                                                         < 0) {
         H4toH5error_set(temph4toh5id,5,
                                     "cannot obtain the object label",
                                     __FILE__,__LINE__);
         return FAIL;
    }

    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_label_new
 *
 * Purpose:         translate annotation object into attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        anno_labelname: annotation label name
        label_index: annotation label index
        attr_flag : flag to control the output of predefined attributes.
                    This flag is also used to distinguish whether
                    the tool follows creation-order with using HDF5
                    dimension scale APIs or not.
    
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_label_new(hid_t              h4toh5_id,
                     char*          h5groupfullpath,
                     char*          h5datasetname,
                     uint16         obj_ref, 
                     int32          obj_tag,
                     char*          anno_labelname,
                     int                label_index,
                     int                attr_flag)
{

    int32        file_id;/* HDF file id */
    int32        an_id;/* AN interface id */
    int32        ann_id;/* annotation id */
    int32        ann_length;/* annotation length */
    uint32       temp_length;/* temporary variable to store annotation length */

    int32        n_file_label =-1; /* number of file labels*/
    int32        n_file_desc    =-1; /* number of file descriptions*/
    int32        n_data_label =-1; /* number of data labels. */
    int32        n_data_desc    =-1; /* number of data descriptions. */

    int          num_lab_anno; /* number of label annotation */
    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/

    char*        ann_buf; /* character array to store annotation buffer. */
    char*        anno_obj_name; /* annotation object name sorted by object tag. */
    char*        new_annolabelname = NULL; /* annotation object label name sorted by
                             tag plus index string*/
    
    char         index_str[MAXREF_LENGTH];/* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_group; /* HDF5 group id. */
    hid_t        h5dset; /* HDF5 dataset id. */
    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str_type;  /* HDF5 string data type. */
    hid_t        sh5str_memtype;    /* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */
    
    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    file_id = temph4toh5id->file_id;

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

    if(h5datasetname == NULL) {
        H4toH5error_set(temph4toh5id,5,
             "HDF5 dataset name is NULL",
             __FILE__,__LINE__);
        H5Gclose(h5_group);
        return FAIL;
    }
    
    if(obj_tag != DFTAG_VG) {

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

    else {/* it is vgroup. */

        h5dset = H5GOPEN(h5_group,h5datasetname);
        if (h5dset < 0) {                                       
             H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 group",
             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;                                        
        }       
    }

    an_id        = ANstart(file_id);
    if(an_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);
    if(istat == FAIL ) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(an_id);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    num_lab_anno     = ANnumann(an_id,AN_DATA_LABEL,(uint16)obj_tag,(uint16)obj_ref);
     
    if (num_lab_anno == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain number of object label annotation",
             __FILE__,__LINE__);
        ANend(an_id);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
 
    if(num_lab_anno > 0 ) {
        if((label_index < 0) &&(label_index >= num_lab_anno)){
            H4toH5error_set(temph4toh5id,5,
                 "label index is not valid",
             __FILE__,__LINE__);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    if(num_lab_anno > 0) {
        ann_id = ANselect(an_id,label_index,AN_DATA_LABEL);
        if(ann_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation id",
             __FILE__,__LINE__);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ann_length = ANannlen(ann_id);
        if(ann_length == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ann_buf      = malloc((ann_length+1)*sizeof(int8));
        if(ann_buf == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(int8));
        istat = ANreadann(ann_id,ann_buf,ann_length+1);
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        istat  = ANendaccess(ann_id);
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "ANendaccess failed",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        /* write into an HDF5 attribute. */
        h5_sid       = H5Screate(H5S_SCALAR);

        if (h5_sid < 0) {
             H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

         temp_length = ann_length + 1;
         H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
             H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if ((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type for memory",
             __FILE__,__LINE__);
            ANend(an_id);

            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        if(conv_int_str(h4toh5_id,(uint32)label_index,index_str)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        
        /* obtain annotation object name. The name is defined based on object tag
         */
        if(anno_labelname == NULL) {
            anno_obj_name = trans_tag_name(obj_tag,AN_DATA_LABEL);
    
            if(anno_obj_name == NULL) {
                H4toH5error_set(temph4toh5id,5,
                 "cannot obtain annotation object name",
                 __FILE__,__LINE__);
                ANend(an_id);
     
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            new_annolabelname = malloc(strlen(anno_obj_name)+strlen(index_str)+2);
            if(new_annolabelname == NULL) {
                H4toH5error_set(temph4toh5id,1,
                 "cannot allocate memory for annotation label name",
                 __FILE__,__LINE__);
                ANend(an_id);
         
                free(ann_buf);
                free(anno_obj_name);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            strcpy(new_annolabelname,anno_obj_name);
            strcat(new_annolabelname,"_");
            strcat(new_annolabelname,index_str);
            free(anno_obj_name);
        }
        if(anno_labelname != NULL) 
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,anno_labelname,sh5str_type,
             h5_sid,H5P_DEFAULT);
        else 
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,new_annolabelname,sh5str_type,
             h5_sid,H5P_DEFAULT);
        
        if (h5_aid <0) {
            if (transattrs_split(h4toh5_id, h5dset, anno_labelname ? anno_labelname : new_annolabelname, h5_sid, ann_buf, temp_length) < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot obtain HDF5 attribute ID",
                 __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(anno_labelname == NULL)
                    free(new_annolabelname);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
        
                return FAIL;
            }
        }
        else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(anno_labelname == NULL)
                free(new_annolabelname);
            H5Sclose(h5_sid);
            H5Aclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ret     = H5Sclose(h5_sid);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 data space interface",
             __FILE__,__LINE__);
            H5Aclose(h5_aid);
            free(ann_buf);
            if(anno_labelname == NULL)
                 free(new_annolabelname);
            ANend(an_id);
             if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if (h5_aid >= 0) {
            ret     = H5Aclose(h5_aid);
            if(ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot close HDF5 data space interface",
                 __FILE__,__LINE__);
                free(ann_buf);
                if(anno_labelname == NULL)
                    free(new_annolabelname);
                ANend(an_id);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        
        if(anno_labelname == NULL){
            free(new_annolabelname);
        }
        free(ann_buf);
            
    }
    if(obj_tag != DFTAG_VG){
        ret = H5Dclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 dataset interface",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    else {
        ret = H5Gclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 group interface",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    ret = H5Gclose(h5_group);
    if( ret < 0) {
         H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 parent group interface",
             __FILE__,__LINE__);
            ANend(an_id);
            return FAIL;
    }
    istat = ANend(an_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
            return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_desc
 *
 * Purpose:         translate annotation object description into an attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        anno_descname: annotation description name
        desc_index: annotation description index
    
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_desc(hid_t  h4toh5_id,
                     char*  h5groupfullpath,
                     char*  h5datasetname,
                     uint16  obj_ref, 
                     int32  obj_tag,
                     char*  anno_descname,
                     int        desc_index)
{
    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    if(H4toH5anno_obj_desc_new(h4toh5_id,h5groupfullpath,h5datasetname,obj_ref,
                               obj_tag,anno_descname,desc_index,H425_OSPEC_ALLATTRS)
                                                         < 0) {
         H4toH5error_set(temph4toh5id,5,
                         "cannot obtain the object desc",
                         __FILE__,__LINE__);
         return FAIL;
    }

    return SUCCEED;

}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_desc_new
 *
 * Purpose:         translate annotation object description into an attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                                h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        anno_descname: annotation description name
        desc_index: annotation description index
    
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_desc_new(hid_t  h4toh5_id,
                                char*  h5groupfullpath,
                                char*  h5datasetname,
                                uint16  obj_ref, 
                                int32  obj_tag,
                                char*  anno_descname,
                                int      desc_index,
                                int      attr_flag)
{

    int32        file_id; /* HDF4 file id. */
    int32        an_id; /* AN interface id. */
    int32        ann_id; /* annotation id */
    int32        ann_length;/* annotation length */
    uint32       temp_length; /* temporary variable to store annotation length */

    int32        n_file_label =-1; /* number of file labels*/
    int32        n_file_desc    =-1; /* number of file descriptions*/
    int32        n_data_label =-1; /* number of data labels. */
    int32        n_data_desc    =-1; /* number of data descriptions. */

    int          num_des_anno; /* number of description annotation */
    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/

    char*        ann_buf;/* character array to store annotation buffer. */
    char*        anno_obj_name;/* annotation object name sorted by object tag. */
    char*        new_annodescname = NULL;/* annotation object label name sorted by
                             tag plus index string*/
    
    char         index_str[MAXREF_LENGTH];/* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_group;/* HDF5 group id. */
    hid_t        h5dset; /* HDF5 dataset id. */
    hid_t        h5_sid; /* HDF5 space id. */
    hid_t        h5_aid; /* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype; /* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */
    
    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    file_id = temph4toh5id->file_id;

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

    if(obj_tag != DFTAG_VG) {
            
        h5dset = H5DOPEN(h5_group,h5datasetname);        
        if (h5dset < 0) {                                       
             H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 dataset",
             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;                                        
        }           
    }

    else {/* it is vgroup. */

        h5dset = H5GOPEN(h5_group,h5datasetname);
        if (h5dset < 0) {                                       
            H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 group",
             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;                                        
        }       
    }
 
    /* obtain HDF4 annotation information */
    an_id        = ANstart(file_id);
    if(an_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);

    if(istat == FAIL ) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        ANend(an_id);
        return FAIL;
    }

    num_des_anno       = ANnumann(an_id,AN_DATA_DESC,(uint16)obj_tag,
                                  (uint16)obj_ref);
    if (num_des_anno == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain number of object desc annotation",
             __FILE__,__LINE__);
        ANend(an_id);
        H5Dclose(h5dset);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
 
    if(num_des_anno > 0 ) {
        if((desc_index < 0) &&(desc_index >= num_des_anno)){
            H4toH5error_set(temph4toh5id,5,
                 "desc. index is not valid",
             __FILE__,__LINE__);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    if(num_des_anno > 0) {

        ann_id = ANselect(an_id,desc_index,AN_DATA_DESC);

        if(ann_id == FAIL) {
            H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation id",
             __FILE__,__LINE__);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ann_length = ANannlen(ann_id);
        if(ann_length == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot obtain length of annotation",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ann_buf      = malloc((ann_length+1)*sizeof(int8));
        if(ann_buf == NULL) {
            H4toH5error_set(temph4toh5id,1,
             "cannot allocate memory for annotation buffer",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(int8));
        istat = ANreadann(ann_id,ann_buf,ann_length+1);
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot read annotation into memory",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        istat = ANendaccess(ann_id);
        if(istat == FAIL) {
            H4toH5error_set(temph4toh5id,2,
             "cannot close annotation interface",
             __FILE__,__LINE__);
            ANendaccess(ann_id);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
            
        h5_sid       = H5Screate(H5S_SCALAR);
        if (h5_sid < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot create attribute space for annotation",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

         temp_length = ann_length + 1;
         H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
        if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
             H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if ((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),
                H5T_STR_NULLTERM))<0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot make HDF5 string type",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        if(conv_int_str(h4toh5_id,(uint32)desc_index,index_str)== FAIL) {
            H4toH5error_set(temph4toh5id,5,
             "cannot convert integer into HDF5 string",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            H5Sclose(h5_sid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }
        
        /* obtain annotation object name. The name is defined based on object tag
         */
        if(anno_descname == NULL) {
            anno_obj_name = trans_tag_name(obj_tag,AN_DATA_DESC);
            if(anno_obj_name == NULL) {
                H4toH5error_set(temph4toh5id,5,
                         "cannot obtain annotation object name",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            new_annodescname = malloc(strlen(anno_obj_name)+strlen(index_str)+2);
            if(new_annodescname == NULL) {
                H4toH5error_set(temph4toh5id,1,
                    "cannot allocate memory for annotation desc name",
                    __FILE__,__LINE__);
               ANend(an_id);
               free(ann_buf);
               free(anno_obj_name);
               H5Sclose(h5_sid);
               if(obj_tag != DFTAG_VG)
                   H5Dclose(h5dset);
               else 
                   H5Gclose(h5dset);
               H5Gclose(h5_group);
               return FAIL;
           }
           strcpy(new_annodescname,anno_obj_name);
           strcat(new_annodescname,"_");
           strcat(new_annodescname,index_str);
                free(anno_obj_name);
        }
        if(anno_descname != NULL) 
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,anno_descname,sh5str_type,
             h5_sid,H5P_DEFAULT);
        else 
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,new_annodescname,sh5str_type,
             h5_sid,H5P_DEFAULT);
        
        if (h5_aid <0) {
            if (transattrs_split(h4toh5_id, h5dset, anno_descname ? anno_descname : new_annodescname, h5_sid, ann_buf, temp_length) < 0) {
                H4toH5error_set(temph4toh5id,3,
                 "cannot obtain HDF5 attribute ID",
                 __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(anno_descname == NULL){
                    free(new_annodescname);
                }
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        }
        else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(anno_descname == NULL)
                free(new_annodescname);
            H5Sclose(h5_sid);
            H5Aclose(h5_aid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        ret     = H5Sclose(h5_sid);
        if (ret <0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot write HDF5 attribute data",
             __FILE__,__LINE__);
            ANend(an_id);
            free(ann_buf);
            if(anno_descname == NULL)
                free(new_annodescname);
            H5Aclose(h5_aid);
            if(obj_tag != DFTAG_VG)
                H5Dclose(h5dset);
            else 
                H5Gclose(h5dset);
            H5Gclose(h5_group);
            return FAIL;
        }

        if (h5_aid >= 0) {
            ret     = H5Aclose(h5_aid);
            if(ret < 0) {

                if(anno_descname == NULL)
                    free(new_annodescname);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            } 
        }

        if(anno_descname == NULL)
            free(new_annodescname);
        free(ann_buf);
    }

    if(obj_tag != DFTAG_VG){
        ret = H5Dclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 dataset interface",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    else {
        ret = H5Gclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 group interface",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    ret = H5Gclose(h5_group);
    if( ret < 0) {
         H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 parent group interface",
             __FILE__,__LINE__);
            ANend(an_id);
            return FAIL;
    }

    istat = ANend(an_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
            return FAIL;
    }
    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_all_labels
 *
 * Purpose:         translate annotation object into attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                                h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_all_labels(hid_t     h4toh5_id,
                 const char*     h5groupfullpath,
                 const char*     h5datasetname,
                 uint16     obj_ref, 
                 int32   obj_tag)
{

    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    if(H4toH5anno_obj_all_labels_new(h4toh5_id,h5groupfullpath,h5datasetname,obj_ref,
                                                            obj_tag,H425_OSPEC_ALLATTRS)
                                                         < 0) {
         H4toH5error_set(temph4toh5id,5,
                                     "cannot obtain all the object labels.",
                                     __FILE__,__LINE__);
         return FAIL;
    }

    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_all_labels_new
 *
 * Purpose:         translate annotation object into attribute of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                                h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_all_labels_new(hid_t     h4toh5_id,
                 const char*     h5groupfullpath,
                 const char*     h5datasetname,
                 uint16     obj_ref, 
                 int32   obj_tag,
                 int     attr_flag)
{

    int32        file_id; /* HDF4 file id */
    int32        an_id; /* AN interface id */
    int32        ann_id; /* annotation id */
    int32        i; /* temporary index variable */
    int32        ann_length; /* annotation length */
    uint32   temp_length;/* temporary variable to store annotation length */

    int32        n_file_label =-1; /* number of file labels*/
    int32        n_file_desc    =-1; /* number of file descriptions*/
    int32        n_data_label =-1; /* number of data labels. */
    int32        n_data_desc    =-1; /* number of data descriptions. */

    int          num_lab_anno; /* number of label annotation */
    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/

    char*        ann_buf; /* character array to store annotation buffer. */
    char*        anno_obj_name; /* annotation object name sorted by object tag. */
    char*        new_annolabelname;/* annotation object label name sorted by
                             tag plus index string*/
    char         index_str[MAXREF_LENGTH];/* a temporary variable to store the
                             string format of decimal index. */


    hid_t        h5_group;/* HDF5 group id. */
    hid_t        h5dset;/* HDF5 dataset id. */
    hid_t        h5_sid;/* HDF5 space id. */
    hid_t        h5_aid;/* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype;/* HDF5 string memory data type. */
    hid_t        ret; /* a temporary variable to check "return" status of HDF5 interfaces. */
    
    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    /* obtain h5_group id */

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


    if(obj_tag != DFTAG_VG) {
            
        h5dset = H5DOPEN(h5_group,h5datasetname);        
    
        if (h5dset < 0) {                                       
            H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 dataset",
             __FILE__,__LINE__); 
            H5Gclose(h5_group);
            return FAIL;                                        
        }               
    }

    else {/* it is vgroup. */

        h5dset = H5GOPEN(h5_group,h5datasetname);
        if (h5dset < 0) {                                       
             H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 group",
             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;                                        
        }       
    }
                
    /* obtain annotation information */
    an_id        = ANstart(file_id);
    if(an_id == FAIL) {
         H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

/*#if 0*/
    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);

    if(istat == FAIL ) {
         H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(an_id);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    num_lab_anno     = ANnumann(an_id,AN_DATA_LABEL,(uint16)obj_tag,(uint16)obj_ref);
     
    if (num_lab_anno == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain number of object label annotation",
             __FILE__,__LINE__);
        ANend(an_id);
        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
    
    if(num_lab_anno > 0) {

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

            ann_id = ANselect(an_id,i,AN_DATA_LABEL);
            if(ann_id == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation id",
                 __FILE__,__LINE__);
                ANend(an_id);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            ann_length = ANannlen(ann_id);
            if(ann_length == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "cannot obtain length of annotation",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            ann_buf      = malloc((ann_length+1)*sizeof(int8));
            if(ann_buf == NULL) {
                H4toH5error_set(temph4toh5id,1,
                         "cannot allocate memory for annotation buffer",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(int8));
            istat = ANreadann(ann_id,ann_buf,ann_length+1);
            if(istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "cannot read annotation into memory",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            istat = ANendaccess(ann_id);
            
            if(istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "cannot close annotation interface",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            h5_sid       = H5Screate(H5S_SCALAR);
            if (h5_sid < 0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot create attribute space for annotation",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            temp_length = ann_length + 1;
            H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
            if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot make HDF5 string type",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            if ((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot make HDF5 string type for memory",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            if(conv_int_str(h4toh5_id,(uint32)i,index_str)== FAIL) {
                H4toH5error_set(temph4toh5id,5,
                         "cannot convert integer into HDF5 string",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        
            /* obtain annotation object name. The name is defined based on object tag
             */
            anno_obj_name = trans_tag_name(obj_tag,AN_DATA_LABEL);
            if(anno_obj_name == NULL) {
                H4toH5error_set(temph4toh5id,5,
                         "cannot obtain annotation object name",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            new_annolabelname = malloc(strlen(anno_obj_name)+strlen(index_str)+2);
            if(new_annolabelname == NULL) {
                H4toH5error_set(temph4toh5id,1,
                     "cannot allocate memory for annotation label name",
                     __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                free(anno_obj_name);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            strcpy(new_annolabelname,anno_obj_name);
            strcat(new_annolabelname,"_");
            strcat(new_annolabelname,index_str);
            free(anno_obj_name);
            
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,new_annolabelname,sh5str_type,
            h5_sid,H5P_DEFAULT);
            if (h5_aid <0) {
                if (transattrs_split(h4toh5_id, h5dset, new_annolabelname, h5_sid, ann_buf, temp_length) < 0) {
                    H4toH5error_set(temph4toh5id,3,
                             "cannot obtain HDF5 attribute ID",
                             __FILE__,__LINE__);
                    ANend(an_id);
                    free(ann_buf);
                    free(new_annolabelname);
                    H5Sclose(h5_sid);
                    if(obj_tag != DFTAG_VG)
                        H5Dclose(h5dset);
                    else 
                        H5Gclose(h5dset);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }
            else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
                 H4toH5error_set(temph4toh5id,3,
                         "cannot write HDF5 attribute data",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                free(new_annolabelname);
                H5Aclose(h5_aid);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            ret     = H5Sclose(h5_sid);
            if(ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot close HDF5 data space",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                free(new_annolabelname);
                H5Aclose(h5_aid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            if (h5_aid >= 0) {
                ret     = H5Aclose(h5_aid);
                if (ret < 0) {
                    H4toH5error_set(temph4toh5id,3,
                             "cannot close HDF5 data space",
                             __FILE__,__LINE__);
                    ANend(an_id);
                    free(ann_buf);
                    free(new_annolabelname);
                    if(obj_tag != DFTAG_VG)
                        H5Dclose(h5dset);
                    else 
                        H5Gclose(h5dset);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }
            free(new_annolabelname);
            free(ann_buf);
            
        }
    }
/*#endif*/
    if(obj_tag != DFTAG_VG){
        ret = H5Dclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 dataset" ,
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    else {
        ret = H5Gclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 group",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }
    ret = H5Gclose(h5_group);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close HDF5 parent group",
             __FILE__,__LINE__);
        ANend(an_id);
        return FAIL;
    }
    istat= ANend(an_id);
    if(istat == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot close AN interface",
                 __FILE__,__LINE__);
        return FAIL;
    }
    return SUCCEED;
}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_all_descs
 *
 * Purpose:         translate annotation object description into attributes of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
                                h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_all_descs(hid_t h4toh5_id,
                     const char* h5groupfullpath,
                     const char* h5datasetname,
                     uint16 obj_ref, 
                     int32 obj_tag)
{

    h4toh5id_t* temph4toh5id;  /*pointer to temporary h4toh5 id. */

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

    if(H4toH5anno_obj_all_descs_new(h4toh5_id,h5groupfullpath,h5datasetname,obj_ref,
                                                                    obj_tag,H425_OSPEC_ALLATTRS) <0 ) {
         H4toH5error_set(temph4toh5id,5,
                                     "cannot obtain the object label",
                                     __FILE__,__LINE__);
         return FAIL;
    }

    return SUCCEED;

}
/*-------------------------------------------------------------------------
 * Function:    H4toH5anno_obj_all_descs_new
 *
 * Purpose:     translate annotation object description into attributes of hdf5 dataset
 *                          
 * Return:  FAIL if failed, SUCCEED if successful.
 *
 * In :                 
        h4toh5_id: h4toh5 identifier
        h5groupfullpath: the absolute path of hdf5 group
        h5datasetname: hdf5 dataset name
        obj_ref: object reference
        obj_tag: object tag
        
    *-------------------------------------------------------------------------
 */
int H4toH5anno_obj_all_descs_new(hid_t h4toh5_id,
                 const char* h5groupfullpath,
                 const char* h5datasetname,
                 uint16 obj_ref, 
                 int32 obj_tag,
                 int     attr_flag)
{

    int32        file_id; /* HDF4 file id. */
    int32        an_id; /* AN interface id. */
    int32        ann_id; /* annotation id. */
    int32        i; /* temporary index variable */
    int32        ann_length; /* annotation length */
    uint32  temp_length; /* temporary length */

    int32        n_file_label =-1; /* number of file labels */
    int32        n_file_desc    =-1; /* number of file descriptions*/
    int32        n_data_label =-1; /* number of data labels. */
    int32        n_data_desc    =-1; /* number of data descriptions. */

    int          num_desc_anno; /* number of object descriptions. */
    int32        istat; /*a temporary variable to check "return" status of HDF4 interfaces.*/
    char*        ann_buf; /* character array to store annotation buffer. */
    char*        anno_obj_name;/* annotation object name sorted by object tag. */
    char*        new_annodescname;/* annotation object label name sorted by
                             tag plus index string*/
    char         index_str[MAXREF_LENGTH];/* a temporary variable to store the
                             string format of decimal index. */

    hid_t        h5_group; /* HDF5 group id */
    hid_t        h5dset;/* HDF5 dataset id */
    hid_t        h5_sid;/*HDF5 space id */
    hid_t        h5_aid;/* HDF5 attribute id. */
    hid_t        sh5str_type; /* HDF5 string data type. */
    hid_t        sh5str_memtype;/* HDF5 string memory data type. */
    hid_t        ret;/* a temporary variable to check "return" status of HDF5 interfaces. */
    
    h4toh5id_t* temph4toh5id; /*pointer to temporary h4toh5 id. */

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

    file_id = temph4toh5id->file_id;

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

    if(obj_tag != DFTAG_VG) {
            
        h5dset = H5DOPEN(h5_group,h5datasetname);        
    
        if (h5dset < 0) {                                       
             H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 dataset",
             __FILE__,__LINE__); 
            H5Gclose(h5_group);
            return FAIL;                                        
        }               
    }

    else {/* it is vgroup. */

        h5dset = H5GOPEN(h5_group,h5datasetname);
        if (h5dset < 0) {                                       
            H4toH5error_set(temph4toh5id,3,
             "cannot open HDF5 group",
             __FILE__,__LINE__);
            H5Gclose(h5_group);
            return FAIL;                                        
        }       
    }

    an_id        = ANstart(file_id);
    if(an_id == FAIL) {
        H4toH5error_set(temph4toh5id,2,
             "cannot start annotation interface",
             __FILE__,__LINE__);

        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);

        return FAIL;
    }

    istat        = ANfileinfo(an_id,&n_file_label,&n_file_desc,
            &n_data_label,&n_data_desc);

    if(istat == FAIL ) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation file information",
             __FILE__,__LINE__);
        ANend(an_id);


        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }

    num_desc_anno       = ANnumann(an_id,AN_DATA_DESC,(uint16)obj_tag,
                     (uint16)obj_ref);
     
    if (num_desc_anno == FAIL) {
        H4toH5error_set(temph4toh5id,2,
                 "cannot obtain number of object desc annotation",
             __FILE__,__LINE__);
        ANend(an_id);

        if(obj_tag != DFTAG_VG)
            H5Dclose(h5dset);
        else 
            H5Gclose(h5dset);
        H5Gclose(h5_group);
        return FAIL;
    }
    

    if(num_desc_anno > 0) {

        for(i=0; i<num_desc_anno;i++) {
            ann_id = ANselect(an_id,i,AN_DATA_DESC);

            if(ann_id == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                 "cannot obtain annotation id",
                         __FILE__,__LINE__);
                ANend(an_id);

                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);

                H5Gclose(h5_group);
                return FAIL;
            }

            ann_length = ANannlen(ann_id);
            if(ann_length == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "cannot obtain length of annotation",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);

                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);

                H5Gclose(h5_group);
                return FAIL;
            }

            ann_buf      = malloc((ann_length+1)*sizeof(int8));
            if(ann_buf == NULL) {
                H4toH5error_set(temph4toh5id,1,
                         "cannot allocate memory for annotation buffer",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);

                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            h4toh5_ZeroMemory(ann_buf,(ann_length+1)*sizeof(int8));
            istat = ANreadann(ann_id,ann_buf,ann_length+1);
            if(istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "cannot read annotation into memory",
                         __FILE__,__LINE__);
                ANendaccess(ann_id);
                ANend(an_id);
                free(ann_buf);

                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            istat = ANendaccess(ann_id);
            if(istat == FAIL) {
                H4toH5error_set(temph4toh5id,2,
                         "ANendaccess failed",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);

                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            h5_sid       = H5Screate(H5S_SCALAR);

            if (h5_sid < 0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot create attribute space for annotation",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
             temp_length = ann_length + 1;
             H425_CHECK_OVERFLOW(temp_length,uint32,size_t);
            if ((sh5str_type = mkstr(h4toh5_id,(size_t)temp_length,H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot make HDF5 string type",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                H5Dclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            if ((sh5str_memtype = mkstr(h4toh5_id,(ann_length+1)*sizeof(int8),
                    H5T_STR_NULLTERM))<0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot make HDF5 string type for memory",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            if(conv_int_str(h4toh5_id,(uint32)i,index_str)== FAIL) {
                H4toH5error_set(temph4toh5id,5,
                         "cannot convert integer into HDF5 string",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
        
            /* obtain annotation object name. The name is defined based on object tag
             */
            anno_obj_name = trans_tag_name(obj_tag,AN_DATA_DESC);
    
            if(anno_obj_name == NULL) {
                H4toH5error_set(temph4toh5id,5,
                         "cannot obtain annotation object name",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
    
                return FAIL;
            }

            new_annodescname = malloc(strlen(anno_obj_name)+strlen(index_str)+2);
            if(new_annodescname == NULL) {
                 H4toH5error_set(temph4toh5id,1,
                     "cannot allocate memory for annotation label name",
                     __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                free(anno_obj_name);
                H5Sclose(h5_sid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            strcpy(new_annodescname,anno_obj_name);
            strcat(new_annodescname,"_");
            strcat(new_annodescname,index_str);
            free(anno_obj_name);
            
            h5_aid = H5Acreate_safe(h4toh5_id,h5dset,new_annodescname,sh5str_type,
            h5_sid,H5P_DEFAULT);
        
            if (h5_aid <0) {
                if (transattrs_split(h4toh5_id, h5dset, new_annodescname, h5_sid, ann_buf, temp_length) < 0) {
                    H4toH5error_set(temph4toh5id,3,
                             "cannot obtain HDF5 attribute ID",
                             __FILE__,__LINE__);
                    ANend(an_id);
                    free(ann_buf);
                    free(new_annodescname);
                    H5Sclose(h5_sid);
                    if(obj_tag != DFTAG_VG)
                        H5Dclose(h5dset);
                    else 
                        H5Gclose(h5dset);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }
            else if (H5Awrite(h5_aid,sh5str_memtype,(void *)ann_buf) < 0) {
                 H4toH5error_set(temph4toh5id,3,
                         "cannot write HDF5 attribute data",
                         __FILE__,__LINE__);
                ANend(an_id);
                free(ann_buf);
                free(new_annodescname);
                H5Sclose(h5_sid);
                H5Aclose(h5_aid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }

            free(new_annodescname);
            free(ann_buf);
            ret     = H5Sclose(h5_sid);
            if (ret < 0) {
                 H4toH5error_set(temph4toh5id,3,
                         "cannot close dataspace interface",
                         __FILE__,__LINE__);
                ANend(an_id);
                H5Aclose(h5_aid);
                if(obj_tag != DFTAG_VG)
                    H5Dclose(h5dset);
                else 
                    H5Gclose(h5dset);
                H5Gclose(h5_group);
                return FAIL;
            }
            if (h5_aid >= 0) {
                ret     = H5Aclose(h5_aid);
                if (ret < 0) {
                    H4toH5error_set(temph4toh5id,3,
                             "cannot close dataspace interface",
                             __FILE__,__LINE__);
                    ANend(an_id);
                    if(obj_tag != DFTAG_VG)
                        H5Dclose(h5dset);
                    else 
                        H5Gclose(h5dset);
                    H5Gclose(h5_group);
                    return FAIL;
                }
            }
        }
    }

    if(obj_tag != DFTAG_VG){
        ret = H5Dclose(h5dset);
        if (ret < 0) {
                H4toH5error_set(temph4toh5id,3,
                         "cannot close dataset interface",
                         __FILE__,__LINE__);
                ANend(an_id);
                H5Gclose(h5_group);
                return FAIL;
        }
    }
    else {
        ret = H5Gclose(h5dset);
        if (ret < 0) {
            H4toH5error_set(temph4toh5id,3,
             "cannot close group interface",
             __FILE__,__LINE__);
            ANend(an_id);
            H5Gclose(h5_group);
            return FAIL;
        }
    }

    ret = H5Gclose(h5_group);
    if(ret < 0) {
        H4toH5error_set(temph4toh5id,3,
             "cannot close parent group interface",
             __FILE__,__LINE__);
        ANend(an_id);
        return FAIL;
    }

    istat = ANend(an_id);
    if(istat == FAIL) {
         H4toH5error_set(temph4toh5id,2,
             "cannot close AN interface",
             __FILE__,__LINE__);
         return FAIL;
    }
    return SUCCEED;
}

/*-------------------------------------------------------------------------
 * Function:    trans_tag_name
 *
 * Purpose:     in annotation routine,
                translate annotation object tag into corresponding HDF5 object
                name.
   Description: Some annotation does have names, however, HDF5 attribute must
                                have names. 
         
 *                          
 * Return:  NULL    if failed, HDF5 object name if successful.
 *
 * In :                 
        obj_tag: hdf4 object tag
        annot_type: hdf4 annotation type
    
    *-------------------------------------------------------------------------
 */
char* trans_tag_name(int32 obj_tag,ann_type annot_type)
{

    char* obj_name;/* object name */

    obj_name = malloc(strlen(HDF4_VGROUP_LABEL)+1);

    if(obj_name == NULL) {
        return NULL;
    }

    if (obj_tag == DFTAG_NDG || obj_tag == DFTAG_SDG || obj_tag == DFTAG_SD) {
         
        if(annot_type == AN_DATA_LABEL) 
            strcpy(obj_name,HDF4_SDS_LABEL);
        
        else if(annot_type == AN_DATA_DESC)
            strcpy(obj_name,HDF4_SDS_DESC);
        else
            return NULL;
    }

    else if(obj_tag == DFTAG_RIG || obj_tag == DFTAG_RI || obj_tag == DFTAG_RI8)
    {
        if(annot_type == AN_DATA_LABEL) 
            strcpy(obj_name,HDF4_IMAGE_LABEL);
        else if(annot_type == AN_DATA_DESC)
            strcpy(obj_name,HDF4_IMAGE_DESC);
        else
            return NULL;
    }

    else if(obj_tag == DFTAG_VG) {
        if(annot_type == AN_DATA_LABEL) 
            strcpy(obj_name,HDF4_VGROUP_LABEL);
        else if(annot_type == AN_DATA_DESC)
            strcpy(obj_name,HDF4_VGROUP_DESC);
        else
            return NULL;
    }
    
    else if(obj_tag == DFTAG_VS || obj_tag == DFTAG_VH) {
        if(annot_type == AN_DATA_LABEL) 
            strcpy(obj_name,HDF4_VDATA_LABEL);
        else if(annot_type == AN_DATA_DESC)
            strcpy(obj_name,HDF4_VDATA_DESC);
        else
            return NULL;
    }

    else if(obj_tag == DFTAG_LUT) {
        if(annot_type == AN_DATA_LABEL) 
            strcpy(obj_name,HDF4_PAL_LABEL);
        else if(annot_type == AN_DATA_DESC)
            strcpy(obj_name,HDF4_PAL_DESC);
        else
            return NULL;
    }
    return obj_name;
}

/* vim:set ts=8 sw=2 sts=2 cindent: */
