summaryrefslogtreecommitdiff
path: root/src/H5E.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5E.c')
-rw-r--r--src/H5E.c1742
1 files changed, 1742 insertions, 0 deletions
diff --git a/src/H5E.c b/src/H5E.c
new file mode 100644
index 0000000..741f0dd
--- /dev/null
+++ b/src/H5E.c
@@ -0,0 +1,1742 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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://support.hdfgroup.org/ftp/HDF5/releases. *
+ * 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 "H5Iprivate.h" /* IDs */
+#include "H5Epkg.h" /* Error handling */
+#include "H5FLprivate.h" /* Free lists */
+#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);
+
+
+/*********************/
+/* 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: Success: non-negative
+ *
+ * Failure: negative
+ *
+ * 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: Non-negative on success/Negative on failure
+ *
+ * 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 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: Non-negative on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, November 1, 2007
+ *
+ *--------------------------------------------------------------------------
+ */
+static herr_t
+H5E_set_default_auto(H5E_t *stk)
+{
+ FUNC_ENTER_NOAPI_NOINIT_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)H5Eprint2;
+ stk->auto_op.is_default = TRUE;
+#else /* H5_NO_DEPRECATED_SYMBOLS */
+ stk->auto_op.func2 = (H5E_auto2_t)H5Eprint2;
+#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: error stack (H5E_t *)
+ *
+ * Failure: NULL
+ *
+ * Programmer: Chee Wai LEE
+ * April 24, 2000
+ *
+ *-------------------------------------------------------------------------
+ */
+H5E_t *
+H5E_get_stack(void)
+{
+ H5E_t *estack = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT_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: Non-negative value on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Friday, January 22, 2009
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5E_free_class(H5E_cls_t *cls)
+{
+ FUNC_ENTER_NOAPI_NOINIT_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: Non-negative value as class ID on success/Negative on failure
+ *
+ * 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; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ 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, FAIL, "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, 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, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "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: Non-negative value as class ID on success/Negative on failure
+ *
+ * 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_NOAPI_NOINIT
+
+ /* 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: Non-negative value on success/Negative on failure
+ *
+ * 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_NOAPI_NOINIT
+
+ /* 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: Non-negative for name length if succeeds(zero means no name);
+ * otherwise returns negative value.
+ *
+ * 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; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ 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, 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)
+} /* end H5Eget_class_name() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ *
+ *-------------------------------------------------------------------------
+ */
+static ssize_t
+H5E_get_class_name(const H5E_cls_t *cls, char *name, size_t size)
+{
+ ssize_t len = 0; /* Length of error class's name */
+
+ FUNC_ENTER_NOAPI_NOINIT_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, MIN((size_t)(len + 1), 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: Non-negative value on success/Negative on failure
+ *
+ * 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;
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* 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, FAIL, "unable to close error message")
+ if(NULL == H5I_remove(obj_id))
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREMOVE, FAIL, "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: Non-negative value on success/Negative on failure
+ *
+ * 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 messge.
+ *
+ * Return: Non-negative value on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Friday, July 11, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5E_close_msg(H5E_msg_t *err)
+{
+ FUNC_ENTER_NOAPI_NOINIT_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: Non-negative value on success/Negative on failure
+ *
+ * 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; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ 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, 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 = (H5E_cls_t *)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(NULL == (msg = H5E_create_msg(cls, msg_type, msg_str)))
+ 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, TRUE)) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTREGISTER, FAIL, "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: Non-negative value on success/Negative on failure
+ *
+ * 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_NOAPI_NOINIT
+
+ /* 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: Non-negative for message length if succeeds(zero means no message);
+ * otherwise returns negative value.
+ *
+ * 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; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ 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, 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)
+} /* end H5Eget_msg() */
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Ecreate_stack
+ *
+ * Purpose: Creates a new, empty, error stack.
+ *
+ * Return: Non-negative value as stack ID on success/Negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Thursday, November 1, 2007
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5Ecreate_stack(void)
+{
+ H5E_t *stk; /* Error stack */
+ hid_t ret_value; /* Return value */
+
+ FUNC_ENTER_API(FAIL)
+ H5TRACE0("i","");
+
+ /* Allocate a new error stack */
+ if(NULL == (stk = H5FL_CALLOC(H5E_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "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, FAIL, "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: Non-negative value as stack ID on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Friday, July 14, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+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(FAIL)
+ H5TRACE0("i","");
+
+ /* Get the current stack */
+ if(NULL == (stk = H5E_get_current_stack()))
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTCREATE, FAIL, "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, FAIL, "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: Non-negative value as class ID on success/Negative on failure
+ *
+ * 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_NOAPI_NOINIT
+
+ /* 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
+ *
+ * Modification:
+ * Raymond Lu
+ * 7 September 2010
+ * Also closes the stack to avoid potential problem (bug 1799)
+ *
+ *-------------------------------------------------------------------------
+ */
+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: Non-negative value on success/Negative on failure
+ *
+ * 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_NOAPI_NOINIT
+
+ /* 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: Non-negative value on success/Negative on failure
+ *
+ * Programmer: Raymond Lu
+ * Friday, July 14, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5E_close_stack(H5E_t *estack)
+{
+ FUNC_ENTER_NOAPI_NOINIT_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 message.
+ *
+ * Return: Non-negative value on success/Negative on failure
+ *
+ * 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(FAIL)
+ 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, 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(error_stack_id, H5I_ERROR_STACK)))
+ 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)
+} /* end H5Eget_num() */
+
+
+/*-------------------------------------------------------------------------
+ * 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
+ *
+ *-------------------------------------------------------------------------
+ */
+static ssize_t
+H5E_get_num(const H5E_t *estack)
+{
+ FUNC_ENTER_NOAPI_NOINIT_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.
+ *
+ *-------------------------------------------------------------------------
+ */
+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 */
+#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 */
+ 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 */
+ va_start(ap, fmt);
+ va_started = TRUE;
+
+#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(NULL == (tmp = H5MM_malloc((size_t)tmp_len)))
+ 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)) > (tmp_len - 1)) {
+ /* 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 */
+ tmp_len = desc_len + 1;
+ if(NULL == (tmp = H5MM_malloc((size_t)tmp_len)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed")
+ } /* end while */
+#endif /* H5_HAVE_VASPRINTF */
+
+ /* 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)
+ va_end(ap);
+#ifdef H5_HAVE_VASPRINTF
+ /* Memory was allocated with HDvasprintf so it needs to be freed
+ * with HDfree
+ */
+ if(tmp)
+ HDfree(tmp);
+#else /* H5_HAVE_VASPRINTF */
+ if(tmp)
+ H5MM_xfree(tmp);
+#endif /* H5_HAVE_VASPRINTF */
+
+ 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 there
+ * 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)
+{
+ 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)
+ /*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 */
+
+ /* 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_API(ret_value)
+} /* end H5Eprint2() */
+
+
+/*-------------------------------------------------------------------------
+ * 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(H5E_walk(estack, direction, &op, client_data) < 0)
+ HGOTO_ERROR(H5E_ERROR, H5E_CANTLIST, FAIL, "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 on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Saturday, February 28, 1998
+ *
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the printing function isn't the default H5Eprint1 or 2,
+ * and H5Eset_auto1 has been called to set the old style
+ * printing function, a call to H5Eget_auto2 should fail.
+ *-------------------------------------------------------------------------
+ */
+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 */
+
+ FUNC_ENTER_API(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
+ 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")
+
+ /* 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 on success/Negative on failure
+ *
+ * Programmer: Robb Matzke
+ * Friday, February 27, 1998
+ *
+ * Modification:Raymond Lu
+ * 4 October 2010
+ * If the FUNC is H5Eprint2, put the IS_DEFAULT flag on.
+ *-------------------------------------------------------------------------
+ */
+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
+ 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")
+
+#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 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 */
+
+ FUNC_ENTER_API(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
+ 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")
+
+ /* 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() */
+