/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at the * * root level of an installed copy of the electronic HDF5 document set and * * is linked from the top-level documents page. It can also be found at * * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * Purpose: Provides error handling in the form of a stack. The * FUNC_ENTER() macro clears the error stack whenever an API * function is entered. When an error is detected, an entry is * pushed onto the stack. As the functions unwind additional * entries are pushed onto the stack. The API function will * return some indication that an error occurred and the * application can print the error stack. * * Certain API functions in the H5E package (such as H5Eprint()) * do not clear the error stack. Otherwise, any function which * doesn't have an underscore immediately after the package name * will clear the error stack. For instance, H5Fopen() clears * the error stack while H5F_open() does not. * * An error stack has a fixed maximum size. If this size is * exceeded then the stack will be truncated and only the * inner-most functions will have entries on the stack. This is * expected to be a rare condition. * * Each thread has its own error stack, but since * multi-threading has not been added to the library yet, this * package maintains a single error stack. The error stack is * statically allocated to reduce the complexity of handling * errors within the H5E package. * */ /* Interface initialization */ #define H5_INTERFACE_INIT_FUNC H5E_init_interface #include "H5private.h" /* Generic Functions */ #include "H5Iprivate.h" /* IDs */ #include "H5Eprivate.h" /* Private error routines */ #include "H5MMprivate.h" /* Memory management */ /* HDF5 error class ID */ hid_t H5E_ERR_CLS_g = FAIL; /* * Predefined errors. These are initialized at runtime in H5E_init_interface() * in this source file. */ /* Include the automatically generated error code definitions */ #include "H5Edefin.h" /* Amount to indent each error */ #define H5E_INDENT 2 #ifdef H5_HAVE_THREADSAFE /* * The per-thread error stack. pthread_once() initializes a special * key that will be used by all threads to create a stack specific to * each thread individually. The association of stacks to threads will * be handled by the pthread library. * * In order for this macro to work, H5E_get_my_stack() must be preceeded * by "H5E_t *estack =". */ static H5E_t * H5E_get_stack(void); #define H5E_get_my_stack() H5E_get_stack() #else /* H5_HAVE_THREADSAFE */ /* * The current error stack. */ H5E_t H5E_stack_g[1]; #define H5E_get_my_stack() (H5E_stack_g+0) #endif /* H5_HAVE_THREADSAFE */ #ifdef H5_HAVE_PARALLEL /* * variables used for MPI error reporting */ char H5E_mpi_error_str[MPI_MAX_ERROR_STRING]; int H5E_mpi_error_str_len; #endif /* Static function declarations */ static H5E_cls_t *H5E_register_class(const char *cls_name, const char *lib_name, const char *version); static herr_t H5E_unregister_class(H5E_cls_t *cls); static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size); static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key); static herr_t H5E_close_msg(H5E_msg_t *err); static H5E_msg_t *H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg); static ssize_t H5E_get_msg(const H5E_msg_t *msg_ptr, H5E_type_t *type, char *msg, size_t size); static H5E_t *H5E_get_current_stack(void); static herr_t H5E_set_current_stack(H5E_t *estack); static herr_t H5E_close_stack(H5E_t *err_stack); static ssize_t H5E_get_num(const H5E_t *err_stack); static herr_t H5E_pop(H5E_t *err_stack, size_t count); static herr_t H5E_clear_entries(H5E_t *estack, size_t nentries); static herr_t H5E_print_stack(const H5E_t *estack, FILE *stream); static herr_t H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, void *client_data); static herr_t H5E_walk_cb(unsigned n, const H5E_error_t *err_desc, void *client_data); static herr_t H5E_get_auto_stack(const H5E_t *estack, hbool_t new_api, void **func, void **client_data); static herr_t H5E_set_auto_stack(H5E_t *estack, hbool_t new_api, void *func, void *client_data); /*------------------------------------------------------------------------- * Function: H5E_init * * Purpose: Initialize the interface from some other layer. * * Return: Success: non-negative * * Failure: negative * * Programmer: Quincey Koziol * Tuesday, June 29, 2004 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_init(void) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_init, FAIL) /* FUNC_ENTER() does all the work */ done: FUNC_LEAVE_NOAPI(ret_value) } /*-------------------------------------------------------------------------- * Function: H5E_init_interface * * Purpose: Initialize interface-specific information * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * *-------------------------------------------------------------------------- */ static herr_t H5E_init_interface(void) { H5E_cls_t *cls; /* Pointer to error class */ H5E_msg_t *msg; /* Pointer to new error message */ char lib_vers[128]; /* Buffer to constructu library version within */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_init_interface) /* Initialize the atom group for the error class IDs */ if(H5I_register_type(H5I_ERROR_CLASS, H5I_ERRCLS_HASHSIZE, H5E_RESERVED_ATOMS, (H5I_free_t)H5E_unregister_class)0 ? "-"H5_VERS_SUBRELEASE : "")); if((cls = H5E_register_class(H5E_CLS_NAME, H5E_CLS_LIB_NAME, lib_vers))==NULL) HGOTO_ERROR (H5E_ERROR, H5E_CANTINIT, FAIL, "class initialization failed") if((H5E_ERR_CLS_g = H5I_register(H5I_ERROR_CLASS, cls))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error class") /* Include the automatically generated error code initialization */ #include "H5Einit.h" done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_term_interface * * Purpose: Terminates the H5E interface * * Return: Success: Positive if anything is done that might * affect other interfaces; zero otherwise. * * Failure: Negative. * * Programmer: Raymond Lu * Tuesday, July 22, 2003 * * Modifications: * *------------------------------------------------------------------------- */ int H5E_term_interface(void) { int ncls, nmsg, nstk, n=0; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_term_interface) if (H5_interface_initialize_g) { /* Check if there are any open error stacks, classes or messages */ ncls = H5I_nmembers(H5I_ERROR_CLASS); nmsg = H5I_nmembers(H5I_ERROR_MSG); nstk = H5I_nmembers(H5I_ERROR_STACK); n = ncls + nmsg + nstk; if(n>0) { /* Clear any outstanding error stacks */ if (nstk>0) H5I_clear_type(H5I_ERROR_STACK, FALSE); /* Clear all the error classes */ if (ncls>0) { H5I_clear_type(H5I_ERROR_CLASS, FALSE); /* Reset the HDF5 error class, if its been closed */ if(H5I_nmembers(H5I_ERROR_CLASS)==0) H5E_ERR_CLS_g = -1; } /* Clear all the error messages */ if (nmsg>0) { H5I_clear_type(H5I_ERROR_MSG, FALSE); /* Reset the HDF5 error messages, if they've been closed */ if(H5I_nmembers(H5I_ERROR_MSG)==0) { /* Include the automatically generated error code termination */ #include "H5Eterm.h" } /* end if */ } /* end if */ } else { /* Destroy the error class, message, and stack id groups */ H5I_dec_type_ref(H5I_ERROR_STACK); H5I_dec_type_ref(H5I_ERROR_CLASS); H5I_dec_type_ref(H5I_ERROR_MSG); /* Mark closed */ H5_interface_initialize_g = 0; n = 1; /*H5I*/ } } FUNC_LEAVE_NOAPI(n) } #ifdef H5_HAVE_THREADSAFE /*------------------------------------------------------------------------- * Function: H5E_get_stack * * Purpose: Support function for H5E_get_my_stack() to initialize and * acquire per-thread error stack. * * Return: Success: error stack (H5E_t *) * * Failure: NULL * * Programmer: Chee Wai LEE * April 24, 2000 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_t * H5E_get_stack(void) { H5E_t *estack; FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_get_stack) estack = pthread_getspecific(H5TS_errstk_key_g); if (!estack) { /* no associated value with current thread - create one */ estack = (H5E_t *)H5MM_malloc(sizeof(H5E_t)); estack->nused = 0; estack->new_api = TRUE; estack->u.func_stack = (H5E_auto_stack_t)H5Eprint_stack; estack->auto_data = NULL; pthread_setspecific(H5TS_errstk_key_g, (void *)estack); } /* Set return value */ FUNC_LEAVE_NOAPI(estack) } #endif /* H5_HAVE_THREADSAFE */ /*------------------------------------------------------------------------- * Function: H5Eregister_class * * Purpose: Registers an error class. * * Return: Non-negative value as class ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ hid_t H5Eregister_class(const char *cls_name, const char *lib_name, const char *version) { H5E_cls_t *cls; /* Pointer to error class */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(H5Eregister_class, FAIL) H5TRACE3("i","sss",cls_name,lib_name,version); /* Check arguments */ if (cls_name==NULL || lib_name==NULL || version==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid string") /* Create the new error class object */ if((cls=H5E_register_class(cls_name, lib_name, version))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error class") /* Register the new error class to get an ID for it */ if((ret_value = H5I_register(H5I_ERROR_CLASS, cls))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error class") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_register_class * * Purpose: Private function to register an error class. * * Return: Non-negative value as class ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_cls_t * H5E_register_class(const char *cls_name, const char *lib_name, const char *version) { H5E_cls_t *cls; /* Pointer to error class */ H5E_cls_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_register_class) /* Check arguments */ assert(cls_name); assert(lib_name); assert(version); /* Allocate space for new error class */ if((cls = H5MM_malloc(sizeof(H5E_cls_t)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Duplicate string information */ if((cls->cls_name = HDstrdup(cls_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if((cls->lib_name = HDstrdup(lib_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if((cls->lib_vers = HDstrdup(version))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the return value */ ret_value=cls; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eunregister_class * * Purpose: Closes an error class. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eunregister_class(hid_t class_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eunregister_class, FAIL) H5TRACE1("e","i",class_id); /* Check arguments */ if (H5I_ERROR_CLASS != H5I_get_type(class_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class") /* * Decrement the counter on the dataset. It will be freed if the count * reaches zero. */ if(H5I_dec_ref(class_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_unregister_class * * Purpose: Private function to close an error class. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_unregister_class(H5E_cls_t *cls) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_unregister_class) /* Check arguments */ assert(cls); /* Iterate over all the messages and delete those in this error class */ /* (Ignore return value, since callback isn't designed to return a particular object) */ (void)H5I_search(H5I_ERROR_MSG, H5E_close_msg_cb, cls); /* Free error class structure */ if(cls->cls_name) H5MM_xfree((void*)cls->cls_name); if(cls->lib_name) H5MM_xfree((void*)cls->lib_name); if(cls->lib_vers) H5MM_xfree((void*)cls->lib_vers); H5MM_xfree((void*)cls); FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Eget_class_name * * Purpose: Retrieves error class name. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ ssize_t H5Eget_class_name(hid_t class_id, char *name, size_t size) { H5E_cls_t *cls; /* Pointer to error class */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Eget_class_name, FAIL) H5TRACE3("Zs","isz",class_id,name,size); /* Get the error class */ if(NULL==(cls = H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID") /* Retrieve the class name */ if((ret_value = H5E_get_class_name(cls, name, size))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get error class name") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_class_name * * Purpose: Private function to retrieve error class name. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static ssize_t H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size) { ssize_t len; /* Length of rror class's name */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_get_class_name) /* Check arguments */ assert(cls); /* Get the class's name */ len = (ssize_t)HDstrlen(cls->cls_name); /* Set the user's buffer, if provided */ if(name) { HDstrncpy(name, cls->cls_name, MIN((size_t)(len+1), size)); if((size_t)len >= size) name[size-1]='\0'; } /* Return the full length */ FUNC_LEAVE_NOAPI(len) } /*------------------------------------------------------------------------- * Function: H5E_close_msg_cb * * Purpose: H5I_search callback function to close error messages in the * error class. * * Programmer: Raymond Lu * July 14, 2003 * * Return: Non-negative value on success/Negative on failure * * Modifications: * *------------------------------------------------------------------------- */ static int H5E_close_msg_cb(void *obj_ptr, hid_t obj_id, void *key) { H5E_msg_t *err_msg = (H5E_msg_t*)obj_ptr; H5E_cls_t *cls = (H5E_cls_t*)key; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_close_msg_cb) /* Check arguments */ assert(err_msg); /* Close the message if it is in the class being closed */ if(err_msg->cls == cls) if(H5I_dec_ref(obj_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclose_msg * * Purpose: Closes a major or minor error. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclose_msg(hid_t err_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eclose_msg, FAIL) H5TRACE1("e","i",err_id); /* Check arguments */ if (H5I_ERROR_MSG != H5I_get_type(err_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error class") /* Decrement the counter. It will be freed if the count reaches zero. */ if(H5I_dec_ref(err_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_close_msg * * Purpose: Private function to close an error messge. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_close_msg(H5E_msg_t *err) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_close_msg) /* Check arguments */ assert(err); if(err->msg) H5MM_xfree((void*)err->msg); /* Don't free err->cls here */ H5MM_xfree((void*)err); FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Ecreate_msg * * Purpose: Creates a major or minor error, returns an ID. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ hid_t H5Ecreate_msg(hid_t class_id, H5E_type_t msg_type, const char *msg_str) { H5E_cls_t *cls; /* Pointer to error class */ H5E_msg_t *msg; /* Pointer to new error message */ hid_t ret_value; /* Return value */ FUNC_ENTER_API(H5Ecreate_msg, FAIL) H5TRACE3("i","iEts",class_id,msg_type,msg_str); /* Check arguments */ if(msg_type!=H5E_MAJOR && msg_type!=H5E_MINOR) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "not a valid message type") if(msg_str==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "message is NULL") /* Get the error class */ if(NULL==(cls = H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error class ID") /* Create the new error message object */ if((msg = H5E_create_msg(cls, msg_type, msg_str))==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error message") /* Register the new error class to get an ID for it */ if((ret_value = H5I_register(H5I_ERROR_MSG, msg))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't register error message") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_create_msg * * Purpose: Private function to create a major or minor error. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_msg_t * H5E_create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg_str) { H5E_msg_t *msg; /* Pointer to new error message */ H5E_msg_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_create_msg) /* Check arguments */ assert(cls); assert(msg_type==H5E_MAJOR || msg_type==H5E_MINOR); assert(msg_str); /* Allocate new message object */ if((msg = H5MM_malloc(sizeof(H5E_msg_t)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Fill new message object */ msg->cls = cls; msg->type = msg_type; if((msg->msg = HDstrdup(msg_str))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set return value */ ret_value = msg; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_major * * Purpose: Retrieves a major error message. * * Return: Returns message if succeeds. * otherwise returns NULL. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ const char * H5Eget_major(H5E_major_t maj) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t size = 0; /* Return value */ H5E_type_t type; char *msg_str; char *ret_value = NULL; FUNC_ENTER_API_NOCLEAR(H5Eget_major,NULL) /* Get the message object */ if((msg = H5I_object_verify(maj, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID") /* Get the message's text */ if((size = H5E_get_msg(msg, &type, NULL, 0))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text"); if(type != H5E_MAJOR) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a major one"); /* Don't know who is going to free it */ msg_str = (char*)H5MM_malloc((size_t)(++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") ret_value = msg_str; done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_minor * * Purpose: Retrieves a minor error message. * * Return: Returns message if succeeds. * otherwise returns NULL. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ const char * H5Eget_minor(H5E_minor_t min) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t size = 0; /* Return value */ H5E_type_t type; char *msg_str; char *ret_value = NULL; FUNC_ENTER_API_NOCLEAR(H5Eget_minor,NULL) /* Get the message object */ if((msg = H5I_object_verify(min, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "not a error message ID") /* Get the message's text */ if((size = H5E_get_msg(msg, &type, NULL, 0))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text"); if(type != H5E_MINOR) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "Error message isn't a minor one"); /* Don't know who is going to free it */ msg_str = (char*)H5MM_malloc((size_t)(++size)*sizeof(char)); if(H5E_get_msg(msg, NULL, msg_str, (size_t)size)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get error message text") ret_value = msg_str; done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_msg * * Purpose: Retrieves an error message. * * Return: Non-negative for message length if succeeds(zero means no message); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ ssize_t H5Eget_msg(hid_t msg_id, H5E_type_t *type, char *msg_str, size_t size) { H5E_msg_t *msg; /* Pointer to error message */ ssize_t ret_value; /* Return value */ FUNC_ENTER_API(H5Eget_msg, FAIL) H5TRACE4("Zs","i*Etsz",msg_id,type,msg_str,size); /* Get the message object */ if((msg = H5I_object_verify(msg_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") /* Get the message's text */ if((ret_value = H5E_get_msg(msg, type, msg_str, size))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get error message text") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_msg * * Purpose: Private function to retrieve an error message. * * Return: Non-negative for name length if succeeds(zero means no name); * otherwise returns negative value. * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static ssize_t H5E_get_msg(const H5E_msg_t *msg, H5E_type_t *type, char *msg_str, size_t size) { ssize_t len; /* Length of rror class's name */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_get_msg) /* Check arguments */ assert(msg); /* Get the length of the message string */ len = (ssize_t)HDstrlen(msg->msg); /* Copy the message into the user's buffer, if given */ if(msg_str) { HDstrncpy(msg_str, msg->msg, MIN((size_t)(len+1), size)); if((size_t)len >= size) msg_str[size-1]='\0'; } /* Give the message type, if asked */ if(type) *type = msg->type; /* Set the return value to the full length of the message */ FUNC_LEAVE_NOAPI(len) } /*------------------------------------------------------------------------- * Function: H5Eget_current_stack * * Purpose: Registers current error stack, returns object handle for it, * clears it. * * Return: Non-negative value as stack ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ hid_t H5Eget_current_stack(void) { H5E_t *stk; /* Error stack */ hid_t ret_value; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eget_current_stack, FAIL) H5TRACE0("i",""); /* Get the current stack */ if((stk=H5E_get_current_stack())==NULL) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "can't create error stack") /* Register the stack */ if((ret_value = H5I_register(H5I_ERROR_STACK, stk))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "can't create error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_current_stack * * Purpose: Private function to register an error stack. * * Return: Non-negative value as class ID on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static H5E_t * H5E_get_current_stack(void) { H5E_t *current_stack; /* Pointer to the current error stack */ H5E_t *estack_copy=NULL; /* Pointer to new error stack to return */ unsigned u; /* Local index variable */ H5E_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_get_current_stack) /* Get a pointer to the current error stack */ if((current_stack = H5E_get_my_stack ())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, NULL, "can't get current error stack") /* Allocate a new error stack */ if((estack_copy = H5MM_malloc(sizeof(H5E_t)))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Make a copy of current error stack */ estack_copy->nused = current_stack->nused; for(u=0; unused; u++) { H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); new_error = &(estack_copy->slot[u]); /* Increment the IDs to indicate that they are used in this stack */ if(H5I_inc_ref(current_error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error class") new_error->cls_id = current_error->cls_id; if(H5I_inc_ref(current_error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message") new_error->maj_num = current_error->maj_num; if(H5I_inc_ref(current_error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, NULL, "unable to increment ref count on error message") new_error->min_num = current_error->min_num; if((new_error->func_name = HDstrdup(current_error->func_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if((new_error->file_name = HDstrdup(current_error->file_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") new_error->line = current_error->line; if((new_error->desc = HDstrdup(current_error->desc))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } /* end for */ /* Empty current error stack */ H5E_clear_stack(current_stack); /* Set the return value */ ret_value = estack_copy; done: if(ret_value==NULL) { if(estack_copy!=NULL) H5MM_xfree((void*)estack_copy); } /* end if */ FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eset_current_stack * * Purpose: Replaces current stack with specified stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_current_stack(hid_t err_stack) { H5E_t *estack; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_current_stack, FAIL) H5TRACE1("e","i",err_stack); if(err_stack != H5E_DEFAULT) { if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Set the current error stack */ if(H5E_set_current_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "unable to set error stack") } /* end if */ done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_set_current_stack * * Purpose: Private function to replace an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_set_current_stack(H5E_t *estack) { H5E_t *current_stack; /* Default error stack */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_set_current_stack) /* Sanity check */ assert(estack); /* Get a pointer to the current error stack */ if((current_stack = H5E_get_my_stack ())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Empty current error stack */ H5E_clear_stack(current_stack); /* Copy new stack to current error stack */ current_stack->nused = estack->nused; for(u=0; unused; u++) { H5E_error_t *current_error, *new_error; /* Pointers to errors on each stack */ /* Get pointers into the current error stack location */ current_error = &(current_stack->slot[u]); new_error = &(estack->slot[u]); /* Increment the IDs to indicate that they are used in this stack */ if(H5I_inc_ref(new_error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->cls_id = new_error->cls_id; if(H5I_inc_ref(new_error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->maj_num = new_error->maj_num; if(H5I_inc_ref(new_error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to decrement ref count on error class") current_error->min_num = new_error->min_num; if((current_error->func_name = HDstrdup(new_error->func_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") if((current_error->file_name = HDstrdup(new_error->file_name))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") current_error->line = new_error->line; if((current_error->desc = HDstrdup(new_error->desc))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclose_stack * * Purpose: Closes an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclose_stack(hid_t stack_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eclose_stack, FAIL) H5TRACE1("e","i",stack_id); if(H5E_DEFAULT != stack_id) { /* * Decrement the counter on the error stack. It will be freed if the count * reaches zero. */ if(H5I_dec_ref(stack_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack") } /* end if */ done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_close_stack * * Purpose: Private function to close an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_close_stack(H5E_t *estack) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_close_stack) /* Sanity check */ assert(estack); /* Release the stack's error information */ H5E_clear_stack(estack); /* Free the stack structure */ H5MM_xfree((void*)estack); FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Eget_num * * Purpose: Retrieves the number of error message. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * Raymond Lu * Monday, May 16, 2005 * Changed return value type from INT to SIZE_T. * *------------------------------------------------------------------------- */ ssize_t H5Eget_num(hid_t error_stack_id) { H5E_t *estack; /* Error stack to operate on */ ssize_t ret_value; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eget_num, FAIL) H5TRACE1("Is","i",error_stack_id); /* Need to check for errors */ if(error_stack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(error_stack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Get the number of errors on stack */ if((ret_value=H5E_get_num(estack))<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get number of errors") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_num * * Purpose: Private function to retrieve number of errors in error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * * Modifications: * Raymond Lu * Monday, May 16, 2005 * Changed return value type from INT to SIZE_T. * *------------------------------------------------------------------------- */ static ssize_t H5E_get_num(const H5E_t *estack) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_get_num) assert(estack); FUNC_LEAVE_NOAPI((ssize_t)estack->nused) } /*------------------------------------------------------------------------- * Function: H5Epop * * Purpose: Deletes some error messages from the top of error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Epop(hid_t err_stack, size_t count) { H5E_t *estack; herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epop, FAIL) H5TRACE2("e","iz",err_stack,count); /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Range limit the number of errors to pop off stack */ if(count > estack->nused) count = estack->nused; /* Pop the errors off the stack */ if(H5E_pop(estack, count)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't pop errors from stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_pop * * Purpose: Private function to delete some error messages from the top * of error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_pop(H5E_t *estack, size_t count) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_pop) /* Sanity check */ assert(estack); assert(estack->nused>=count); /* Remove the entries from the error stack */ if(H5E_clear_entries(estack, count)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "can't remove errors from stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Epush * * Purpose: This function definition is for backward compatibility only. * It doesn't have error stack and error class as parameters. * The old definition of major and minor is casted as HID_T * in H5Epublic.h * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Tuesday, Sep 16, 2003 * * Notes: Basically a public API wrapper around the H5E_push_stack * function. For backward compatibility, it maintains the * same parameter as the old function, in contrary to * H5Epush_stack. * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Epush(const char *file, const char *func, unsigned line, H5E_major_t maj, H5E_minor_t min, const char *str) { H5E_t *estack = NULL; /* Default error stack */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epush, FAIL) H5TRACE6("e","ssIuiis",file,func,line,maj,min,str); /* Push the error on the stack */ if(H5E_push_stack(estack, file, func, line, H5E_ERR_CLS_g, maj, min, str)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't push error on stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Epush_stack * * Purpose: Pushes a new error record onto error stack for the current * thread. The error has major and minor IDs MAJ_ID and * MIN_ID, the name of a function where the error was detected, * the name of the file where the error was detected, the * line within that file, and an error description string. The * function name, file name, and error description strings must * be statically allocated. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Monday, October 18, 1999 * * Notes: Basically a new public API wrapper around the H5E_push_stack * function. * * Modifications: * Raymond Lu * Tuesday, July 15, 2003 * * Added the ID of the error stack to which the error is pushed * on. The error message can be appended more message in the * same control format as printf and fprintf. * *------------------------------------------------------------------------- */ herr_t H5Epush_stack(hid_t err_stack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *fmt, ...) { va_list ap; /* Varargs info */ H5E_t *estack; /* Pointer to error stack to modify */ H5E_msg_t *maj_ptr, *min_ptr; /* Pointer to major and minor error info */ #ifndef H5_HAVE_VASPRINTF int tmp_len; /* Current size of description buffer */ int desc_len; /* Actual length of description when formatted */ #endif /* H5_HAVE_VASPRINTF */ char *tmp=NULL; /* Buffer to place formatted description in */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Epush_stack, FAIL) H5TRACE7("e","issIuiis",err_stack,file,func,line,maj_id,min_id,fmt); if(err_stack == H5E_DEFAULT) estack = NULL; else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); /* Get the error stack to operate on */ if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Check for mis-matches in major & minor error classes */ if((maj_ptr = H5I_object_verify(maj_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") if((min_ptr = H5I_object_verify(min_id, H5I_ERROR_MSG))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error message ID") if(maj_ptr->cls != min_ptr->cls) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "major and minor errors not from same error class") /* Format the description */ va_start(ap, fmt); #ifdef H5_HAVE_VASPRINTF /* Use the vasprintf() routine, since it does what we're trying to do below */ if(HDvasprintf(&tmp,fmt,ap)<0) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") #else /* H5_HAVE_VASPRINTF */ /* Allocate space for the formatted description buffer */ tmp_len=128; if((tmp=H5MM_malloc((size_t)tmp_len))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") /* If the description doesn't fit into the initial buffer size, allocate more space and try again */ while((desc_len=HDvsnprintf(tmp, (size_t)tmp_len, fmt, ap)) #ifdef H5_VSNPRINTF_WORKS > #else /* H5_VSNPRINTF_WORKS */ >= #endif /* H5_VSNPRINTF_WORKS */ (tmp_len-1) #ifndef H5_VSNPRINTF_WORKS || desc_len<0 #endif /* H5_VSNPRINTF_WORKS */ ) { /* shutdown & restart the va_list */ va_end(ap); va_start(ap, fmt); /* Release the previous description, it's too small */ H5MM_xfree(tmp); /* Allocate a description of the appropriate length */ #ifdef H5_VSNPRINTF_WORKS tmp_len = desc_len+1; #else /* H5_VSNPRINTF_WORKS */ tmp_len = 2 * tmp_len; #endif /* H5_VSNPRINTF_WORKS */ if((tmp=H5MM_malloc((size_t)tmp_len))==NULL) HGOTO_ERROR (H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end while */ #endif /* H5_HAVE_VASPRINTF */ va_end(ap); /* Push the error on the stack */ if(H5E_push_stack(estack, file, func, line, cls_id, maj_id, min_id, tmp)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't push error on stack") done: if(tmp) H5MM_xfree(tmp); FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_push_stack * * Purpose: Pushes a new error record onto error stack for the current * thread. The error has major and minor IDs MAJ_ID and * MIN_ID, the name of a function where the error was detected, * the name of the file where the error was detected, the * line within that file, and an error description string. The * function name, file name, and error description strings must * be statically allocated (the FUNC_ENTER() macro takes care of * the function name and file name automatically, but the * programmer is responsible for the description string). * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * Raymond Lu * Tuesday, July 15, 2003 * * Added the ID of the error stack to which the error is pushed * on. The error message can be appended more message in the * same control format as printf and fprintf. * *------------------------------------------------------------------------- */ herr_t H5E_push_stack(H5E_t *estack, const char *file, const char *func, unsigned line, hid_t cls_id, hid_t maj_id, hid_t min_id, const char *desc) { herr_t ret_value=SUCCEED; /* Return value */ /* * WARNING: We cannot call HERROR() from within this function or else we * could enter infinite recursion. Furthermore, we also cannot * call any other HDF5 macro or function which might call * HERROR(). HERROR() is called by HRETURN_ERROR() which could * be called by FUNC_ENTER(). */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_push_stack) /* Sanity check */ assert(cls_id>0); assert(maj_id>0); assert(min_id>0); /* Check for 'default' error stack */ if(estack==NULL) if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_DONE(FAIL) /* * Don't fail if arguments are bad. Instead, substitute some default * value. */ if (!func) func = "Unknown_Function"; if (!file) file = "Unknown_File"; if (!desc) desc = "No description given"; /* * Push the error if there's room. Otherwise just forget it. */ assert (estack); if (estack->nusedslot[estack->nused].cls_id = cls_id; if(H5I_inc_ref(maj_id)<0) HGOTO_DONE(FAIL) estack->slot[estack->nused].maj_num = maj_id; if(H5I_inc_ref(min_id)<0) HGOTO_DONE(FAIL) estack->slot[estack->nused].min_num = min_id; if((estack->slot[estack->nused].func_name = HDstrdup(func))==NULL) HGOTO_DONE(FAIL) if((estack->slot[estack->nused].file_name = HDstrdup(file))==NULL) HGOTO_DONE(FAIL) estack->slot[estack->nused].line = line; if((estack->slot[estack->nused].desc = HDstrdup(desc))==NULL) HGOTO_DONE(FAIL) estack->nused++; } done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclear * * Purpose: This function is for backward compatbility. * Clears the error stack for the specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclear(void) { H5E_t *estack = NULL; /* Default error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eclear, FAIL) H5TRACE0("e",""); /* Clear the error stack */ if(H5E_clear_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eclear_stack * * Purpose: Clears the error stack for the specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eclear_stack(hid_t err_stack) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eclear_stack, FAIL) H5TRACE1("e","i",err_stack); /* Need to check for errors */ if(err_stack == H5E_DEFAULT) estack = NULL; else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Clear the error stack */ if(H5E_clear_stack(estack)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_clear_entries * * Purpose: Private function to clear the error stack entries for the * specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, August 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_clear_entries(H5E_t *estack, size_t nentries) { H5E_error_t *error; /* Pointer to error stack entry to clear */ unsigned u; /* Local index variable */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_clear_entries) /* Sanity check */ assert(estack); assert(estack->nused>=nentries); /* Empty the error stack from the top down */ for(u=0; nentries>0; nentries--,u++) { error = &(estack->slot[estack->nused-(u+1)]); /* Decrement the IDs to indicate that they are no longer used by this stack */ /* (In reverse order that they were incremented, so that reference counts work well) */ if(H5I_dec_ref(error->min_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") if(H5I_dec_ref(error->maj_num)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error message") if(H5I_dec_ref(error->cls_id)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error class") /* Release strings */ if(error->func_name) H5MM_xfree((void*)error->func_name); if(error->file_name) H5MM_xfree((void*)error->file_name); if(error->desc) H5MM_xfree((void*)error->desc); } /* end for */ /* Decrement number of errors on stack */ estack->nused-=u; done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_clear_stack * * Purpose: Private function to clear the error stack for the * specified error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Wednesday, July 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_clear_stack(H5E_t *estack) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_clear_stack, FAIL) /* Check for 'default' error stack */ if(estack==NULL) if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Empty the error stack */ assert(estack); if(estack->nused) if(H5E_clear_entries(estack, estack->nused)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't clear error stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eprint * * Purpose: This function is for backward compatbility. * Prints the error stack in some default way. This is just a * convenience function for H5Ewalk() with a function that * prints error messages. Users are encouraged to write there * own more specific error handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * *------------------------------------------------------------------------- */ herr_t H5Eprint(FILE *stream) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eprint, FAIL) /*NO TRACE*/ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Print error stack */ if(H5E_print_stack(estack, stream)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eprint_stack * * Purpose: Prints the error stack in some default way. This is just a * convenience function for H5Ewalk() with a function that * prints error messages. Users are encouraged to write there * own more specific error handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * * Raymond Lu, 2003/7/16 * Print for specified error stack. A line will appear before the error * messages of each error class. It states the information of library * name, version number and thread ID. * *------------------------------------------------------------------------- */ herr_t H5Eprint_stack(hid_t err_stack, FILE *stream) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Eprint_stack, FAIL) /*NO TRACE*/ /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Print error stack */ if(H5E_print_stack(estack, stream)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_print_stack * * Purpose: Private function to print the error stack in some default * way. This is just a convenience function for H5Ewalk() and * H5Ewalk_stack() with a function that prints error messages. * Users are encouraged to write there own more specific error * handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * Albert Cheng, 2000/12/02 * Show MPI process rank id if applicable. * Albert Cheng, 2001/07/14 * Show HDF5 library version information string too. * * Raymond Lu, 2003/7/16 * Print for specified error stack. A line will appear before the error * messages of each error class. It states the information of library * name, version number and thread ID. * *------------------------------------------------------------------------- */ static herr_t H5E_print_stack(const H5E_t *estack, FILE *stream) { H5E_print_t eprint; /* Callback information to pass to H5E_walk_cb() */ herr_t ret_value = SUCCEED; /* Don't clear the error stack! :-) */ FUNC_ENTER_NOAPI_NOINIT(H5E_print_stack) /* Sanity check */ assert(estack); /* If no stream was given, use stderr */ if (!stream) eprint.stream = stderr; else eprint.stream = stream; /* Reset the original error class information */ HDmemset(&eprint.cls,0,sizeof(H5E_cls_t)); /* Walk the error stack */ if(H5E_walk_stack(estack, H5E_WALK_DOWNWARD, H5E_walk_cb, (void*)&eprint)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Ewalk * * Purpose: This function is for backward compatbility. * Walks the error stack for the current thread and calls some * function for each error along the way. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Ewalk(H5E_direction_t direction, H5E_walk_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Ewalk, FAIL) /*NO TRACE*/ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Walk the error stack */ if(H5E_walk_stack(estack, direction, func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Ewalk_stack * * Purpose: Walks the error stack for the current thread and calls some * function for each error along the way. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * * Raymond Lu * Wednesday, July 16, 2003 * Let it walk through specified error stack. * *------------------------------------------------------------------------- */ herr_t H5Ewalk_stack(hid_t err_stack, H5E_direction_t direction, H5E_walk_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5Ewalk_stack, FAIL) /*NO TRACE*/ /* Need to check for errors */ if(err_stack == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else { /* Only clear the error stack if it's not the default stack */ H5E_clear_stack(NULL); if((estack = H5I_object_verify(err_stack, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Walk the error stack */ if(H5E_walk_stack(estack, direction, func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_walk_stack * * Purpose: Private function for H5Ewalk. * Walks the error stack, calling the specified function for * each error on the stack. The DIRECTION argument determines * whether the stack is walked from the inside out or the * outside in. The value H5E_WALK_UPWARD means begin with the * most specific error and end at the API; H5E_WALK_DOWNWARD * means to start at the API and end at the inner-most function * where the error was first detected. * * The function pointed to by FUNC will be called for each error * in the error stack. It's arguments will include an index * number (beginning at zero regardless of stack traversal * direction), an error stack entry, and the CLIENT_DATA pointer * passed to H5E_print. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * * Raymond Lu * Wednesday, July 16, 2003 * Let it walk through specified error stack. * *------------------------------------------------------------------------- */ static herr_t H5E_walk_stack(const H5E_t *estack, H5E_direction_t direction, H5E_walk_t func, void *client_data) { int i; /* Local index variable */ herr_t status; /* Status from callback function */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT(H5E_walk_stack) /* Sanity check */ assert (estack); /* check args, but rather than failing use some default value */ if (direction!=H5E_WALK_UPWARD && direction!=H5E_WALK_DOWNWARD) direction = H5E_WALK_UPWARD; /* Walk the stack if a callback function was given */ if(func) { status=SUCCEED; if (H5E_WALK_UPWARD==direction) { for (i=0; i<(int)estack->nused && status>=0; i++) status = (func)((unsigned)i, estack->slot+i, client_data); } else { H5_CHECK_OVERFLOW(estack->nused-1,size_t,int); for (i=(int)(estack->nused-1); i>=0 && status>=0; i--) status = (func)((unsigned)(estack->nused-(size_t)(i+1)), estack->slot+i, client_data); } if(status<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't walk error stack") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_walk_cb * * Purpose: This is a default error stack traversal callback function * that prints error messages to the specified output stream. * It is not meant to be called directly but rather as an * argument to the H5Ewalk() function. This function is called * also by H5Eprint(). Application writers are encouraged to * use this function as a model for their own error stack * walking functions. * * N is a counter for how many times this function has been * called for this particular traversal of the stack. It always * begins at zero for the first error on the stack (either the * top or bottom error, or even both, depending on the traversal * direction and the size of the stack). * * ERR_DESC is an error description. It contains all the * information about a particular error. * * CLIENT_DATA is the same pointer that was passed as the * CLIENT_DATA argument of H5Ewalk(). It is expected to be a * file pointer (or stderr if null). * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, December 12, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_walk_cb(unsigned n, const H5E_error_t *err_desc, void *client_data) { H5E_print_t *eprint = (H5E_print_t *)client_data; FILE *stream; /* I/O stream to print output to */ H5E_cls_t *cls_ptr; /* Pointer to error class */ H5E_msg_t *maj_ptr; /* Pointer to major error info */ H5E_msg_t *min_ptr; /* Pointer to minor error info */ const char *maj_str = "No major description"; /* Major error description */ const char *min_str = "No minor description"; /* Minor error description */ unsigned have_desc=1; /* Flag to indicate whether the error has a "real" description */ FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_walk_cb) /* Check arguments */ assert (err_desc); /* If no client data was passed, output to stderr */ if (!client_data) stream = stderr; else stream = eprint->stream; /* Get descriptions for the major and minor error numbers */ maj_ptr = H5I_object_verify(err_desc->maj_num, H5I_ERROR_MSG); min_ptr = H5I_object_verify(err_desc->min_num, H5I_ERROR_MSG); assert(maj_ptr && min_ptr); if(maj_ptr->msg) maj_str = maj_ptr->msg; if(min_ptr->msg) min_str = min_ptr->msg; /* Get error class info */ cls_ptr = maj_ptr->cls; /* Print error class header if new class */ if(eprint->cls.lib_name==NULL || HDstrcmp(cls_ptr->lib_name, eprint->cls.lib_name)) { /* update to the new class information */ if(cls_ptr->cls_name) eprint->cls.cls_name = cls_ptr->cls_name; if(cls_ptr->lib_name) eprint->cls.lib_name = cls_ptr->lib_name; if(cls_ptr->lib_vers) eprint->cls.lib_vers = cls_ptr->lib_vers; fprintf (stream, "%s-DIAG: Error detected in %s (%s) ", cls_ptr->cls_name, cls_ptr->lib_name, cls_ptr->lib_vers); /* try show the process or thread id in multiple processes cases*/ #ifdef H5_HAVE_PARALLEL { int mpi_rank, mpi_initialized; MPI_Initialized(&mpi_initialized); if (mpi_initialized){ MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank); fprintf (stream, "MPI-process %d", mpi_rank); }else fprintf (stream, "thread 0"); } #elif defined(H5_HAVE_THREADSAFE) fprintf (stream, "thread %lu", (unsigned long)pthread_self()); #else fprintf (stream, "thread 0"); #endif fprintf (stream, ":\n"); } /* Check for "real" error description - used to format output more nicely */ if(err_desc->desc==NULL || HDstrlen(err_desc->desc)==0) have_desc=0; /* Print error message */ fprintf (stream, "%*s#%03u: %s line %u in %s()%s%s\n", H5E_INDENT, "", n, err_desc->file_name, err_desc->line, err_desc->func_name, (have_desc ? ": " : ""), (have_desc ? err_desc->desc : "")); fprintf (stream, "%*smajor: %s\n", H5E_INDENT*2, "", maj_str); fprintf (stream, "%*sminor: %s\n", H5E_INDENT*2, "", min_str); FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Eget_auto * * Purpose: This function is for backward compatbility. * Returns the current settings for the automatic error stack * traversal function and its data for specific error stack. * Either (or both) arguments may be null in which case the * value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eget_auto(H5E_auto_t *func, void **client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eget_auto, FAIL) H5TRACE2("e","*xx",func,client_data); /* Retrieve default error stack */ if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Get the automatic error reporting information */ if(H5E_get_auto_stack(estack, FALSE, (void **)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eget_auto_stack * * Purpose: Returns the current settings for the automatic error stack * traversal function and its data for specific error stack. * Either (or both) arguments may be null in which case the * value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Saturday, February 28, 1998 * * Modifications: * Raymond Lu * July 18, 2003 * Added error stack in the parameters. It returns the * traversal function and data for that error stack. * *------------------------------------------------------------------------- */ herr_t H5Eget_auto_stack(hid_t estack_id, H5E_auto_stack_t *func, void **client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eget_auto_stack, FAIL) H5TRACE3("e","i*xx",estack_id,func,client_data); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Get the automatic error reporting information */ if(H5E_get_auto_stack(estack, TRUE, (void **)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_get_auto_stack * * Purpose: Private function to return the current settings for the * automatic error stack traversal function and its data * for specific error stack. Either (or both) arguments may * be null in which case the value is not returned. * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * July 18, 2003 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_get_auto_stack(const H5E_t *estack, hbool_t new_api, void * *func, void **client_data) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_get_auto_stack) assert (estack); /* Retrieve the requested information */ if(func) *func = new_api ? (void *)estack->u.func_stack : (void *)estack->u.func; if(client_data) *client_data = estack->auto_data; FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5Eset_auto * * Purpose: This function is for backward compatbility. * Turns on or off automatic printing of errors for certain * error stack. When turned on (non-null FUNC pointer) any * API function which returns an error indication will first * call FUNC passing it CLIENT_DATA as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Raymond Lu * Sep 16, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_auto(H5E_auto_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_auto, FAIL) H5TRACE2("e","xx",func,client_data); if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") /* Set the automatic error reporting information */ if(H5E_set_auto_stack(estack, FALSE, (void *)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eset_auto_stack * * Purpose: Turns on or off automatic printing of errors for certain * error stack. When turned on (non-null FUNC pointer) any * API function which returns an error indication will first * call FUNC passing it CLIENT_DATA as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eset_auto_stack(hid_t estack_id, H5E_auto_stack_t func, void *client_data) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eset_auto_stack, FAIL) H5TRACE3("e","ixx",estack_id,func,client_data); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Set the automatic error reporting information */ if(H5E_set_auto_stack(estack, TRUE, (void *)func, client_data)<0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") done: FUNC_LEAVE_API(ret_value) } /*------------------------------------------------------------------------- * Function: H5E_set_auto_stack * * Purpose: Private function to turn on or off automatic printing of * errors for certain error stack. When turned on (non-null * FUNC pointer) any API function which returns an error * indication will first call FUNC passing it CLIENT_DATA * as an argument. * * The default values before this function is called are * H5Eprint() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * See Also: H5Ewalk() * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t H5E_set_auto_stack(H5E_t *estack, hbool_t new_api, void *func, void *client_data) { FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5E_set_auto_stack) assert(estack); /* Set the automatic error reporting info */ estack->new_api = new_api; if(new_api) estack->u.func_stack = (H5E_auto_stack_t)func; else estack->u.func = (H5E_auto_t)func; estack->auto_data = client_data; FUNC_LEAVE_NOAPI(SUCCEED) } /*------------------------------------------------------------------------- * Function: H5E_dump_api_stack * * Purpose: Private function to dump the error stack during an error in * an API function if a callback function is defined for the * current error stack. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, August 6, 2003 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5E_dump_api_stack(int is_api) { herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(H5E_dump_api_stack, FAIL) /* Only dump the error stack during an API call */ if(is_api) { H5E_t *estack = H5E_get_my_stack(); assert(estack); if(estack->new_api) { if (estack->u.func_stack) (void)((estack->u.func_stack)(H5E_DEFAULT, estack->auto_data)); } /* end if */ else { if (estack->u.func) (void)((estack->u.func)(estack->auto_data)); } /* end else */ } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /*------------------------------------------------------------------------- * Function: H5Eauto_is_stack * * Purpose: Determines if the error auto reporting function for an * error stack conforms to the H5E_auto_stack_t typedef * or the H5E_auto_t typedef. The IS_STACK parameter is set * to 1 for the first case and 0 for the latter case. * * Return: Non-negative on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, September 8, 2004 * * Modifications: * *------------------------------------------------------------------------- */ herr_t H5Eauto_is_stack(hid_t estack_id, unsigned *is_stack) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value=SUCCEED; /* Return value */ FUNC_ENTER_API(H5Eauto_is_stack, FAIL) H5TRACE2("e","i*Iu",estack_id,is_stack); if(estack_id == H5E_DEFAULT) { if((estack = H5E_get_my_stack())==NULL) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get current error stack") } /* end if */ else if((estack = H5I_object_verify(estack_id, H5I_ERROR_STACK))==NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* Check if the error stack reporting function is the "newer" stack type */ if(is_stack) *is_stack=estack->new_api; done: FUNC_LEAVE_API(ret_value) } /* end H5Eauto_is_stack() */