/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * 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 COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * 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 H5Eprint2()) * 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. * */ /****************/ /* Module Setup */ /****************/ #include "H5Emodule.h" /* This source code file is part of the H5E module */ /***********/ /* Headers */ /***********/ #include "H5private.h" /* Generic Functions */ #include "H5Epkg.h" /* Error handling */ #include "H5FLprivate.h" /* Free lists */ #include "H5Iprivate.h" /* IDs */ #include "H5MMprivate.h" /* Memory management */ /****************/ /* Local Macros */ /****************/ /* HDF5 error class */ #define H5E_CLS_NAME "HDF5" #define H5E_CLS_LIB_NAME "HDF5" /******************/ /* Local Typedefs */ /******************/ /********************/ /* Package Typedefs */ /********************/ /********************/ /* Local Prototypes */ /********************/ /* Static function declarations */ static herr_t H5E__set_default_auto(H5E_t *stk); 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 *udata); 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 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__print2(hid_t err_stack, FILE *stream); /*********************/ /* Package Variables */ /*********************/ /* Package initialization variable */ hbool_t H5_PKG_INIT_VAR = FALSE; /*****************************/ /* Library Private Variables */ /*****************************/ /*******************/ /* Local Variables */ /*******************/ /* Declare a free list to manage the H5E_t struct */ H5FL_DEFINE_STATIC(H5E_t); /* Declare a free list to manage the H5E_cls_t struct */ H5FL_DEFINE_STATIC(H5E_cls_t); /* Declare a free list to manage the H5E_msg_t struct */ H5FL_DEFINE_STATIC(H5E_msg_t); /* Error class ID class */ static const H5I_class_t H5I_ERRCLS_CLS[1] = {{ H5I_ERROR_CLASS, /* ID class value */ 0, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E__unregister_class /* Callback routine for closing objects of this class */ }}; /* Error message ID class */ static const H5I_class_t H5I_ERRMSG_CLS[1] = {{ H5I_ERROR_MSG, /* ID class value */ 0, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E__close_msg /* Callback routine for closing objects of this class */ }}; /* Error stack ID class */ static const H5I_class_t H5I_ERRSTK_CLS[1] = {{ H5I_ERROR_STACK, /* ID class value */ 0, /* Class flags */ 0, /* # of reserved IDs for class */ (H5I_free_t)H5E__close_stack /* Callback routine for closing objects of this class */ }}; /*------------------------------------------------------------------------- * Function: H5E_init * * Purpose: Initialize the interface from some other layer. * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * Tuesday, June 29, 2004 * *------------------------------------------------------------------------- */ herr_t H5E_init(void) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) /* FUNC_ENTER() does all the work */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E_init() */ /*-------------------------------------------------------------------------- * Function: H5E__init_package * * Purpose: Initialize interface-specific information * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *-------------------------------------------------------------------------- */ herr_t H5E__init_package(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_PACKAGE /* Initialize the atom group for the error class IDs */ if (H5I_register_type(H5I_ERRCLS_CLS) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") /* Initialize the atom group for the major error IDs */ if (H5I_register_type(H5I_ERRMSG_CLS) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") /* Initialize the atom group for the error stacks */ if (H5I_register_type(H5I_ERRSTK_CLS) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize ID group") #ifndef H5_HAVE_THREADSAFE H5E_stack_g[0].nused = 0; H5E__set_default_auto(H5E_stack_g); #endif /* H5_HAVE_THREADSAFE */ /* Allocate the HDF5 error class */ HDassert(H5E_ERR_CLS_g == (-1)); HDsnprintf(lib_vers, sizeof(lib_vers), "%u.%u.%u%s", H5_VERS_MAJOR, H5_VERS_MINOR, H5_VERS_RELEASE, (HDstrlen(H5_VERS_SUBRELEASE) > 0 ? "-" H5_VERS_SUBRELEASE : "")); if (NULL == (cls = H5E__register_class(H5E_CLS_NAME, H5E_CLS_LIB_NAME, lib_vers))) HGOTO_ERROR(H5E_ERROR, H5E_CANTINIT, FAIL, "class initialization failed") if ((H5E_ERR_CLS_g = H5I_register(H5I_ERROR_CLASS, cls, FALSE)) < 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) } /* end H5E__init_package() */ /*------------------------------------------------------------------------- * Function: H5E_term_package * * 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 * *------------------------------------------------------------------------- */ int H5E_term_package(void) { int n = 0; FUNC_ENTER_NOAPI_NOINIT_NOERR if (H5_PKG_INIT_VAR) { int64_t ncls, nmsg, nstk; /* 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); if ((ncls + nmsg + nstk) > 0) { /* Clear the default error stack. Note that * the following H5I_clear_type calls do not * force the clears and will not be able to * clear any error message IDs that are still * in use by the default error stack unless we * clear that stack manually. * * Error message IDs will typically still be * in use by the default error stack when the * application does H5E_BEGIN/END_TRY cleanup * at the very end. */ H5E_clear_stack(NULL); /* Clear any outstanding error stacks */ if (nstk > 0) (void)H5I_clear_type(H5I_ERROR_STACK, FALSE, FALSE); /* Clear all the error classes */ if (ncls > 0) { (void)H5I_clear_type(H5I_ERROR_CLASS, FALSE, FALSE); /* Reset the HDF5 error class, if its been closed */ if (H5I_nmembers(H5I_ERROR_CLASS) == 0) H5E_ERR_CLS_g = -1; } /* end if */ /* Clear all the error messages */ if (nmsg > 0) { (void)H5I_clear_type(H5I_ERROR_MSG, FALSE, 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 */ n++; /*H5I*/ } /* end if */ else { /* Destroy the error class, message, and stack id groups */ n += (H5I_dec_type_ref(H5I_ERROR_STACK) > 0); n += (H5I_dec_type_ref(H5I_ERROR_CLASS) > 0); n += (H5I_dec_type_ref(H5I_ERROR_MSG) > 0); /* Mark closed */ if (0 == n) H5_PKG_INIT_VAR = FALSE; } /* end else */ } /* end if */ FUNC_LEAVE_NOAPI(n) } /* end H5E_term_package() */ /*-------------------------------------------------------------------------- * Function: H5E__set_default_auto * * Purpose: Initialize "automatic" error stack reporting info to library * default * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * Thursday, November 1, 2007 * *-------------------------------------------------------------------------- */ static herr_t H5E__set_default_auto(H5E_t *stk) { FUNC_ENTER_STATIC_NOERR #ifndef H5_NO_DEPRECATED_SYMBOLS #ifdef H5_USE_16_API_DEFAULT stk->auto_op.vers = 1; #else /* H5_USE_16_API */ stk->auto_op.vers = 2; #endif /* H5_USE_16_API_DEFAULT */ stk->auto_op.func1 = stk->auto_op.func1_default = (H5E_auto1_t)H5Eprint1; stk->auto_op.func2 = stk->auto_op.func2_default = (H5E_auto2_t)H5E__print2; stk->auto_op.is_default = TRUE; #else /* H5_NO_DEPRECATED_SYMBOLS */ stk->auto_op.func2 = (H5E_auto2_t)H5E__print2; #endif /* H5_NO_DEPRECATED_SYMBOLS */ stk->auto_data = NULL; FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5E__set_default_auto() */ #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: Pointer to an error stack struct (H5E_t *) * * Failure: NULL * * Programmer: Chee Wai LEE * April 24, 2000 * *------------------------------------------------------------------------- */ H5E_t * H5E__get_stack(void) { H5E_t *estack = NULL; FUNC_ENTER_PACKAGE_NOERR estack = (H5E_t *)H5TS_get_thread_local_value(H5TS_errstk_key_g); if (!estack) { /* No associated value with current thread - create one */ #ifdef H5_HAVE_WIN_THREADS /* Win32 has to use LocalAlloc to match the LocalFree in DllMain */ estack = (H5E_t *)LocalAlloc(LPTR, sizeof(H5E_t)); #else /* Use HDmalloc here since this has to match the HDfree in the * destructor and we want to avoid the codestack there. */ estack = (H5E_t *)HDmalloc(sizeof(H5E_t)); #endif /* H5_HAVE_WIN_THREADS */ HDassert(estack); /* Set the thread-specific info */ estack->nused = 0; H5E__set_default_auto(estack); /* (It's not necessary to release this in this API, it is * released by the "key destructor" set up in the H5TS * routines. See calls to pthread_key_create() in H5TS.c -QAK) */ H5TS_set_thread_local_value(H5TS_errstk_key_g, (void *)estack); } /* end if */ /* Set return value */ FUNC_LEAVE_NOAPI(estack) } /* end H5E__get_stack() */ #endif /* H5_HAVE_THREADSAFE */ /*------------------------------------------------------------------------- * Function: H5E__free_class * * Purpose: Private function to free an error class. * * Return: SUCCEED/FAIL * * Programmer: Quincey Koziol * Friday, January 22, 2009 * *------------------------------------------------------------------------- */ static herr_t H5E__free_class(H5E_cls_t *cls) { FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(cls); /* Free error class structure */ cls->cls_name = (char *)H5MM_xfree((void *)cls->cls_name); cls->lib_name = (char *)H5MM_xfree((void *)cls->lib_name); cls->lib_vers = (char *)H5MM_xfree((void *)cls->lib_vers); cls = H5FL_FREE(H5E_cls_t, cls); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5E__free_class() */ /*------------------------------------------------------------------------- * Function: H5Eregister_class * * Purpose: Registers an error class. * * Return: Success: An ID for the error class * Failure: H5I_INVALID_HID * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ 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 = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE3("i", "*s*s*s", cls_name, lib_name, version); /* Check arguments */ if (cls_name == NULL || lib_name == NULL || version == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid string") /* Create the new error class object */ if (NULL == (cls = H5E__register_class(cls_name, lib_name, version))) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "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, TRUE)) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register error class") done: FUNC_LEAVE_API(ret_value) } /* end H5Eregister_class() */ /*------------------------------------------------------------------------- * Function: H5E__register_class * * Purpose: Private function to register an error class. * * Return: Success: Pointer to an error class struct * Failure: NULL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ static H5E_cls_t * H5E__register_class(const char *cls_name, const char *lib_name, const char *version) { H5E_cls_t *cls = NULL; /* Pointer to error class */ H5E_cls_t *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(cls_name); HDassert(lib_name); HDassert(version); /* Allocate space for new error class */ if (NULL == (cls = H5FL_CALLOC(H5E_cls_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Duplicate string information */ if (NULL == (cls->cls_name = H5MM_xstrdup(cls_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if (NULL == (cls->lib_name = H5MM_xstrdup(lib_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if (NULL == (cls->lib_vers = H5MM_xstrdup(version))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set the return value */ ret_value = cls; done: if (!ret_value) if (cls && H5E__free_class(cls) < 0) HDONE_ERROR(H5E_ERROR, H5E_CANTRELEASE, NULL, "unable to free error class") FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__register_class() */ /*------------------------------------------------------------------------- * Function: H5Eunregister_class * * Purpose: Closes an error class. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ herr_t H5Eunregister_class(hid_t class_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(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_app_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) } /* end H5Eunregister_class() */ /*------------------------------------------------------------------------- * Function: H5E__unregister_class * * Purpose: Private function to close an error class. * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ static herr_t H5E__unregister_class(H5E_cls_t *cls) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(cls); /* Iterate over all the messages and delete those in this error class */ if (H5I_iterate(H5I_ERROR_MSG, H5E__close_msg_cb, cls, FALSE) < 0) HGOTO_ERROR(H5E_ERROR, H5E_BADITER, FAIL, "unable to free all messages in this error class") /* Free error class structure */ if (H5E__free_class(cls) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTRELEASE, FAIL, "unable to free error class") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__unregister_class() */ /*------------------------------------------------------------------------- * Function: H5Eget_class_name * * Purpose: Retrieves error class name. * * Return: Success: Name length (zero means no name) * Failure: -1 * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ 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 = -1; /* Return value */ FUNC_ENTER_API((-1)) H5TRACE3("Zs", "i*sz", class_id, name, size); /* Get the error class */ if (NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "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, (-1), "can't get error class name") done: FUNC_LEAVE_API(ret_value) } /* end H5Eget_class_name() */ /*------------------------------------------------------------------------- * Function: H5E__get_class_name * * Purpose: Private function to retrieve error class name. * * Return: Success: Name length (zero means no name) * Failure: -1 * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ static ssize_t H5E__get_class_name(const H5E_cls_t *cls, char *name, size_t size) { ssize_t len = -1; /* Length of error class's name */ FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(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, size); if ((size_t)len >= size) name[size - 1] = '\0'; } /* end if */ /* Return the full length */ FUNC_LEAVE_NOAPI(len) } /* end H5E__get_class_name() */ /*------------------------------------------------------------------------- * Function: H5E__close_msg_cb * * Purpose: H5I_iterate callback function to close error messages in the * error class. * * Return: Success: H5_ITER_CONT (0) * Failure: H5_ITER_ERROR (-1) * * Programmer: Raymond Lu * July 14, 2003 * *------------------------------------------------------------------------- */ static int H5E__close_msg_cb(void *obj_ptr, hid_t obj_id, void *udata) { H5E_msg_t *err_msg = (H5E_msg_t *)obj_ptr; H5E_cls_t *cls = (H5E_cls_t *)udata; int ret_value = H5_ITER_CONT; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(err_msg); /* Close the message if it is in the class being closed */ if (err_msg->cls == cls) { if (H5E__close_msg(err_msg) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTCLOSEOBJ, H5_ITER_ERROR, "unable to close error message") if (NULL == H5I_remove(obj_id)) HGOTO_ERROR(H5E_ERROR, H5E_CANTREMOVE, H5_ITER_ERROR, "unable to remove error message") } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__close_msg_cb() */ /*------------------------------------------------------------------------- * Function: H5Eclose_msg * * Purpose: Closes a major or minor error. * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ herr_t H5Eclose_msg(hid_t err_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(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_app_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) } /* end H5Eclose_msg() */ /*------------------------------------------------------------------------- * Function: H5E__close_msg * * Purpose: Private function to close an error message. * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ static herr_t H5E__close_msg(H5E_msg_t *err) { FUNC_ENTER_STATIC_NOERR /* Check arguments */ HDassert(err); /* Release message */ err->msg = (char *)H5MM_xfree((void *)err->msg); /* Don't free err->cls here */ err = H5FL_FREE(H5E_msg_t, err); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5E__close_msg() */ /*------------------------------------------------------------------------- * Function: H5Ecreate_msg * * Purpose: Creates a major or minor error, returns an ID. * * Return: Success: An error ID * Failure: H5I_INVALID_HID * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ 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 = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE3("i", "iEt*s", class_id, msg_type, msg_str); /* Check arguments */ if (msg_type != H5E_MAJOR && msg_type != H5E_MINOR) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "not a valid message type") if (msg_str == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "message is NULL") /* Get the error class */ if (NULL == (cls = (H5E_cls_t *)H5I_object_verify(class_id, H5I_ERROR_CLASS))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not an error class ID") /* Create the new error message object */ if (NULL == (msg = H5E__create_msg(cls, msg_type, msg_str))) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "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, TRUE)) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't register error message") done: FUNC_LEAVE_API(ret_value) } /* end H5Ecreate_msg() */ /*------------------------------------------------------------------------- * Function: H5E__create_msg * * Purpose: Private function to create a major or minor error. * * Return: Success: Pointer to a message struct * Failure: NULL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ static H5E_msg_t * H5E__create_msg(H5E_cls_t *cls, H5E_type_t msg_type, const char *msg_str) { H5E_msg_t *msg = NULL; /* Pointer to new error message */ H5E_msg_t *ret_value = NULL; /* Return value */ FUNC_ENTER_STATIC /* Check arguments */ HDassert(cls); HDassert(msg_type == H5E_MAJOR || msg_type == H5E_MINOR); HDassert(msg_str); /* Allocate new message object */ if (NULL == (msg = H5FL_MALLOC(H5E_msg_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Fill new message object */ msg->cls = cls; msg->type = msg_type; if (NULL == (msg->msg = H5MM_xstrdup(msg_str))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") /* Set return value */ ret_value = msg; done: if (!ret_value) if (msg && H5E__close_msg(msg) < 0) HDONE_ERROR(H5E_ERROR, H5E_CANTCLOSEOBJ, NULL, "unable to close error message") FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__create_msg() */ /*------------------------------------------------------------------------- * Function: H5Eget_msg * * Purpose: Retrieves an error message. * * Return: Success: Message length (zero means no message) * Failure: -1 * * Programmer: Raymond Lu * Friday, July 14, 2003 * *------------------------------------------------------------------------- */ 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 = -1; /* Return value */ FUNC_ENTER_API_NOCLEAR((-1)) H5TRACE4("Zs", "i*Et*sz", msg_id, type, msg_str, size); /* Get the message object */ if (NULL == (msg = (H5E_msg_t *)H5I_object_verify(msg_id, H5I_ERROR_MSG))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "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, (-1), "can't get error message text") done: FUNC_LEAVE_API(ret_value) } /* end H5Eget_msg() */ /*------------------------------------------------------------------------- * Function: H5Ecreate_stack * * Purpose: Creates a new, empty, error stack. * * Return: Success: An error stack ID * Failure: H5I_INVALID_HID * * Programmer: Quincey Koziol * Thursday, November 1, 2007 * *------------------------------------------------------------------------- */ hid_t H5Ecreate_stack(void) { H5E_t *stk; /* Error stack */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ FUNC_ENTER_API(H5I_INVALID_HID) H5TRACE0("i", ""); /* Allocate a new error stack */ if (NULL == (stk = H5FL_CALLOC(H5E_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed") /* Set the "automatic" error reporting info to the library default */ H5E__set_default_auto(stk); /* Register the stack */ if ((ret_value = H5I_register(H5I_ERROR_STACK, stk, TRUE)) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't create error stack") done: FUNC_LEAVE_API(ret_value) } /* end H5Ecreate_stack() */ /*------------------------------------------------------------------------- * Function: H5Eget_current_stack * * Purpose: Registers current error stack, returns object handle for it, * clears it. * * Return: Success: An error stack ID * Failure: H5I_INVALID_HID * * Programmer: Raymond Lu * Friday, July 14, 2003 * *------------------------------------------------------------------------- */ hid_t H5Eget_current_stack(void) { H5E_t *stk; /* Error stack */ hid_t ret_value = H5I_INVALID_HID; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(H5I_INVALID_HID) H5TRACE0("i", ""); /* Get the current stack */ if (NULL == (stk = H5E__get_current_stack())) HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, H5I_INVALID_HID, "can't create error stack") /* Register the stack */ if ((ret_value = H5I_register(H5I_ERROR_STACK, stk, TRUE)) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, H5I_INVALID_HID, "can't create error stack") done: FUNC_LEAVE_API(ret_value) } /* end H5Eget_current_stack() */ /*------------------------------------------------------------------------- * Function: H5E__get_current_stack * * Purpose: Private function to register an error stack. * * Return: Success: Pointer to an error class struct * Failure: NULL * * Programmer: Raymond Lu * Friday, July 11, 2003 * *------------------------------------------------------------------------- */ 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 = NULL; /* Return value */ FUNC_ENTER_STATIC /* Get a pointer to the current error stack */ if (NULL == (current_stack = H5E__get_my_stack())) /*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 (NULL == (estack_copy = H5FL_CALLOC(H5E_t))) 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; u < current_stack->nused; u++) { H5E_error2_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, FALSE) < 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, FALSE) < 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, FALSE) < 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 (NULL == (new_error->func_name = H5MM_xstrdup(current_error->func_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") if (NULL == (new_error->file_name = H5MM_xstrdup(current_error->file_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") new_error->line = current_error->line; if (NULL == (new_error->desc = H5MM_xstrdup(current_error->desc))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed") } /* end for */ /* Copy the "automatic" error reporting information */ estack_copy->auto_op = current_stack->auto_op; estack_copy->auto_data = current_stack->auto_data; /* 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) estack_copy = H5FL_FREE(H5E_t, estack_copy); FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__get_current_stack() */ /*------------------------------------------------------------------------- * Function: H5Eset_current_stack * * Purpose: Replaces current stack with specified stack. This closes the * stack ID also. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 15, 2003 * *------------------------------------------------------------------------- */ herr_t H5Eset_current_stack(hid_t err_stack) { H5E_t *estack; herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", err_stack); if (err_stack != H5E_DEFAULT) { if (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) 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") /* * Decrement the counter on the error stack. It will be freed if the count * reaches zero. */ if (H5I_dec_app_ref(err_stack) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTDEC, FAIL, "unable to decrement ref count on error stack") } /* end if */ done: FUNC_LEAVE_API(ret_value) } /* end H5Eset_current_stack() */ /*------------------------------------------------------------------------- * Function: H5E__set_current_stack * * Purpose: Private function to replace an error stack. * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 15, 2003 * *------------------------------------------------------------------------- */ 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_STATIC /* Sanity check */ HDassert(estack); /* Get a pointer to the current error stack */ if (NULL == (current_stack = H5E__get_my_stack())) /*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; u < current_stack->nused; u++) { H5E_error2_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, FALSE) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class") current_error->cls_id = new_error->cls_id; if (H5I_inc_ref(new_error->maj_num, FALSE) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class") current_error->maj_num = new_error->maj_num; if (H5I_inc_ref(new_error->min_num, FALSE) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTINC, FAIL, "unable to increment ref count on error class") current_error->min_num = new_error->min_num; if (NULL == (current_error->func_name = H5MM_xstrdup(new_error->func_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") if (NULL == (current_error->file_name = H5MM_xstrdup(new_error->file_name))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") current_error->line = new_error->line; if (NULL == (current_error->desc = H5MM_xstrdup(new_error->desc))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed") } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__set_current_stack() */ /*------------------------------------------------------------------------- * Function: H5Eclose_stack * * Purpose: Closes an error stack. * * Return: Non-negative value on success/Negative on failure * * Programmer: Raymond Lu * Friday, July 14, 2003 * *------------------------------------------------------------------------- */ herr_t H5Eclose_stack(hid_t stack_id) { herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE1("e", "i", stack_id); if (H5E_DEFAULT != stack_id) { /* Check arguments */ if (H5I_ERROR_STACK != H5I_get_type(stack_id)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") /* * Decrement the counter on the error stack. It will be freed if the count * reaches zero. */ if (H5I_dec_app_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) } /* end H5Eclose_stack() */ /*------------------------------------------------------------------------- * Function: H5E__close_stack * * Purpose: Private function to close an error stack. * * Return: SUCCEED/FAIL * * Programmer: Raymond Lu * Friday, July 14, 2003 * *------------------------------------------------------------------------- */ static herr_t H5E__close_stack(H5E_t *estack) { FUNC_ENTER_STATIC_NOERR /* Sanity check */ HDassert(estack); /* Release the stack's error information */ H5E_clear_stack(estack); /* Free the stack structure */ estack = H5FL_FREE(H5E_t, estack); FUNC_LEAVE_NOAPI(SUCCEED) } /* end H5E__close_stack() */ /*------------------------------------------------------------------------- * Function: H5Eget_num * * Purpose: Retrieves the number of error messages. * * Return: Success: The number of errors * Failure: -1 * * Programmer: Raymond Lu * Friday, July 15, 2003 * *------------------------------------------------------------------------- */ 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((-1)) H5TRACE1("Zs", "i", error_stack_id); /* Need to check for errors */ if (error_stack_id == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*lint !e506 !e774 Make lint 'constant value Boolean' in non-threaded case */ HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, (-1), "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 (NULL == (estack = (H5E_t *)H5I_object_verify(error_stack_id, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not an 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, (-1), "can't get number of errors") done: FUNC_LEAVE_API(ret_value) } /* end H5Eget_num() */ /*------------------------------------------------------------------------- * Function: H5E__get_num * * Purpose: Private function to retrieve number of errors in error stack. * * Return: Success: The number of errors * Failure: -1 (can't fail at this time) * * Programmer: Raymond Lu * Friday, July 15, 2003 * *------------------------------------------------------------------------- */ static ssize_t H5E__get_num(const H5E_t *estack) { FUNC_ENTER_STATIC_NOERR HDassert(estack); FUNC_LEAVE_NOAPI((ssize_t)estack->nused) } /* end H5E__get_num() */ /*------------------------------------------------------------------------- * 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 * *------------------------------------------------------------------------- */ 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(FAIL) H5TRACE2("e", "iz", err_stack, count); /* Need to check for errors */ if (err_stack == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) 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) } /* end H5Epop() */ /*------------------------------------------------------------------------- * Function: H5Epush2 * * 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. * *------------------------------------------------------------------------- */ H5_ATTR_FORMAT(printf, 8, 9) herr_t H5Epush2(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 */ char * tmp = NULL; /* Buffer to place formatted description in */ hbool_t va_started = FALSE; /* Whether the variable argument list is open */ herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(FAIL) H5TRACE8("e", "i*s*sIuiii*s", err_stack, file, func, line, cls_id, 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 (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Note that the variable-argument parsing for the format is identical in * the H5E_printf_stack() routine - correct errors and make changes in both * places. -QAK */ /* Format the description */ HDva_start(ap, fmt); va_started = TRUE; /* 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") /* 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 (va_started) HDva_end(ap); /* Memory was allocated with HDvasprintf so it needs to be freed * with HDfree */ if (tmp) HDfree(tmp); FUNC_LEAVE_API(ret_value) } /* end H5Epush2() */ /*------------------------------------------------------------------------- * Function: H5Eclear2 * * 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 * *------------------------------------------------------------------------- */ herr_t H5Eclear2(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(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 (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) 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) } /* end H5Eclear2() */ /*------------------------------------------------------------------------- * Function: H5Eprint2 * * 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 their * own more specific error handlers. * * Return: Non-negative on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * *------------------------------------------------------------------------- */ herr_t H5Eprint2(hid_t err_stack, FILE *stream) { herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(FAIL) /*NO TRACE*/ /* Print error stack */ if ((ret_value = H5E__print2(err_stack, stream)) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_API(ret_value) } /* end H5Eprint2() */ /*------------------------------------------------------------------------- * Function: H5E__print2 * * Purpose: Internal helper routine for H5Eprint2. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ static herr_t H5E__print2(hid_t err_stack, FILE *stream) { H5E_t *estack; /* Error stack to operate on */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_STATIC /* Need to check for errors */ if (err_stack == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Print error stack */ if (H5E__print(estack, stream, FALSE) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "can't display error stack") done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5E__print2() */ /*------------------------------------------------------------------------- * Function: H5Ewalk2 * * 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 * *------------------------------------------------------------------------- */ herr_t H5Ewalk2(hid_t err_stack, H5E_direction_t direction, H5E_walk2_t stack_func, void *client_data) { H5E_t * estack; /* Error stack to operate on */ H5E_walk_op_t op; /* Operator for walking error stack */ herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(FAIL) /*NO TRACE*/ /* Need to check for errors */ if (err_stack == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(err_stack, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Walk the error stack */ op.vers = 2; op.u.func2 = stack_func; if ((ret_value = H5E__walk(estack, direction, &op, client_data)) < 0) HERROR(H5E_ERROR, H5E_CANTLIST, "can't walk error stack"); done: FUNC_LEAVE_API(ret_value) } /* end H5Ewalk2() */ /*------------------------------------------------------------------------- * Function: H5Eget_auto2 * * 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 value on success/Negative on failure * * Programmer: Robb Matzke * Saturday, February 28, 1998 * *------------------------------------------------------------------------- */ herr_t H5Eget_auto2(hid_t estack_id, H5E_auto2_t *func, void **client_data) { H5E_t * estack; /* Error stack to operate on */ H5E_auto_op_t op; /* Error stack function */ herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(FAIL) H5TRACE3("e", "i*x**x", estack_id, func, client_data); if (estack_id == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Get the automatic error reporting information */ if (H5E__get_auto(estack, &op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") #ifndef H5_NO_DEPRECATED_SYMBOLS /* Fail if the printing function isn't the default(user-set) and set through H5Eset_auto1 */ if (!op.is_default && op.vers == 1) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "wrong API function, H5Eset_auto1 has been called") #endif /* H5_NO_DEPRECATED_SYMBOLS */ if (func) *func = op.func2; done: FUNC_LEAVE_API(ret_value) } /* end H5Eget_auto2() */ /*------------------------------------------------------------------------- * Function: H5Eset_auto2 * * 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 * H5Eprint2() with client data being the standard error stream, * stderr. * * Automatic stack traversal is always in the H5E_WALK_DOWNWARD * direction. * * Return: Non-negative value on success/Negative on failure * * Programmer: Robb Matzke * Friday, February 27, 1998 * *------------------------------------------------------------------------- */ herr_t H5Eset_auto2(hid_t estack_id, H5E_auto2_t func, void *client_data) { H5E_t * estack; /* Error stack to operate on */ H5E_auto_op_t op; /* Error stack operator */ herr_t ret_value = SUCCEED; /* Return value */ /* Don't clear the error stack! :-) */ FUNC_ENTER_API_NOCLEAR(FAIL) H5TRACE3("e", "ix*x", estack_id, func, client_data); if (estack_id == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ #ifndef H5_NO_DEPRECATED_SYMBOLS /* Get the automatic error reporting information */ if (H5E__get_auto(estack, &op, NULL) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTGET, FAIL, "can't get automatic error info") /* Set the automatic error reporting information */ if (func != op.func2_default) op.is_default = FALSE; else op.is_default = TRUE; op.vers = 2; #endif /* H5_NO_DEPRECATED_SYMBOLS */ /* Set the automatic error reporting function */ op.func2 = func; if (H5E__set_auto(estack, &op, client_data) < 0) HGOTO_ERROR(H5E_ERROR, H5E_CANTSET, FAIL, "can't set automatic error info") done: FUNC_LEAVE_API(ret_value) } /* end H5Eset_auto2() */ /*------------------------------------------------------------------------- * Function: H5Eauto_is_v2 * * 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 value on success/Negative on failure * * Programmer: Quincey Koziol * Wednesday, September 8, 2004 * *------------------------------------------------------------------------- */ herr_t H5Eauto_is_v2(hid_t estack_id, unsigned *is_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(FAIL) H5TRACE2("e", "i*Iu", estack_id, is_stack); if (estack_id == H5E_DEFAULT) { if (NULL == (estack = H5E__get_my_stack())) /*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 (NULL == (estack = (H5E_t *)H5I_object_verify(estack_id, H5I_ERROR_STACK))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a error stack ID") } /* end else */ /* Check if the error stack reporting function is the "newer" stack type */ if (is_stack) #ifndef H5_NO_DEPRECATED_SYMBOLS *is_stack = estack->auto_op.vers > 1; #else *is_stack = 1; #endif done: FUNC_LEAVE_API(ret_value) } /* end H5Eauto_is_v2() */