summaryrefslogtreecommitdiffstats
path: root/src/H5E.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5E.c')
-rw-r--r--src/H5E.c792
1 files changed, 458 insertions, 334 deletions
diff --git a/src/H5E.c b/src/H5E.c
index f738caa..f7d9fd2 100644
--- a/src/H5E.c
+++ b/src/H5E.c
@@ -1,13 +1,22 @@
/****************************************************************************
-* NCSA HDF *
-* Software Development Group *
-* National Center for Supercomputing Applications *
-* University of Illinois at Urbana-Champaign *
-* 605 E. Springfield, Champaign IL 61820 *
-* *
-* For conditions of distribution and use, see the accompanying *
-* hdf/COPYING file. *
-* *
+* NCSA HDF *
+* Software Development Group *
+* National Center for Supercomputing Applications *
+* University of Illinois at Urbana-Champaign *
+* 605 E. Springfield, Champaign IL 61820 *
+* *
+* For conditions of distribution and use, see the accompanying *
+* hdf/COPYING file. *
+ *
+ * Notes: It is safe to call HRETURN_ERROR(), HGOTO_ERROR(), HERROR(), and
+ * H5ECLEAR within any of these functions except H5E_push() (see
+ * comments in H5E_push()). However, some of the H5E API functions
+ * don't call H5ECLEAR the the error stack on which they're operating
+ * is the thread's global error stack. If the thread's global error
+ * stack isn't defined yet, then HRETURN_ERROR(), HGOTO_ERROR(), and
+ * HERROR() don't push an error message and H5ECLEAR just returns
+ * without doing anything.
+* *
****************************************************************************/
#ifdef RCSID
@@ -16,82 +25,65 @@ static char RcsId[] = "@(#)$Revision$";
/* $Id$ */
-/*LINTLIBRARY */
-/*+
- FILE
- hdf5err.c
- HDF error reporting routines
-
- EXPORTED ROUTINES
- H5Enew_err_stack -- Create a new error stack to push values on
- H5Epush -- Push an error value on an error stack
-
- LIBRARY-SCOPED ROUTINES
-
- LOCAL ROUTINES
- H5E_init_interface -- initialize the H5E interface
- + */
-
-#include <H5private.h> /* Generic Functions */
-#include <H5Aprivate.h> /* Atoms */
-#include <H5Eprivate.h> /* Private error routines */
+#include <H5private.h> /* Generic Functions */
+#include <H5Aprivate.h> /* Atoms */
+#include <H5Eprivate.h> /* Private error routines */
+#include <H5MMprivate.h> /* Memory management */
#define PABLO_MASK H5E_mask
/*-------------------- Locally scoped variables -----------------------------*/
-static const hdf_maj_error_messages_t hdf_maj_error_messages[] =
-{
- {H5E_NONE_MAJOR, "No error"},
- {H5E_ARGS, "Invalid arguments to routine"},
- {H5E_RESOURCE, "Resource unavailable"},
- {H5E_INTERNAL, "Internal HDF5 error (too specific to document in detail)"},
- {H5E_FILE, "File Accessability"},
- {H5E_IO, "Low-level I/O"},
- {H5E_FUNC, "Function Entry/Exit"},
- {H5E_ATOM, "Object Atom"},
+static const H5E_major_mesg_t H5E_major_mesg_g[] = {
+ {H5E_NONE_MAJOR, "No error"},
+ {H5E_ARGS, "Invalid arguments to routine"},
+ {H5E_RESOURCE, "Resource unavailable"},
+ {H5E_INTERNAL, "Internal HDF5 error"},
+ {H5E_FILE, "File Accessability"},
+ {H5E_IO, "Low-level I/O"},
+ {H5E_FUNC, "Function Entry/Exit"},
+ {H5E_ATOM, "Object Atom"},
{H5E_CACHE, "Object Cache"},
{H5E_BTREE, "B-Tree Node"},
{H5E_SYM, "Symbol Table"},
{H5E_HEAP, "Heap"},
{H5E_OHDR, "Object Header"},
- {H5E_DATATYPE, "Datatype"},
+ {H5E_DATATYPE, "Datatype"},
{H5E_DATASPACE, "Dataspace"},
- {H5E_DATASET, "Dataset"},
- {H5E_STORAGE, "Data Storage"},
- {H5E_TEMPLATE, "Template"},
+ {H5E_DATASET, "Dataset"},
+ {H5E_STORAGE, "Data Storage"},
+ {H5E_TEMPLATE, "Template"},
};
-static const hdf_min_error_messages_t hdf_min_error_messages[] =
-{
- {H5E_NONE_MINOR, "No error"},
+static const H5E_minor_mesg_t H5E_minor_mesg_g[] = {
+ {H5E_NONE_MINOR, "No error"},
{H5E_UNINITIALIZED, "Information is uninitialized"},
- {H5E_UNSUPPORTED, "Feature is unsupported"},
- {H5E_BADTYPE, "Incorrect type found"},
- {H5E_BADRANGE, "Argument out of range"},
- {H5E_BADVALUE, "Bad value for argument"},
- {H5E_NOSPACE, "No space available for allocation"},
- {H5E_FILEEXISTS, "File already exists"},
- {H5E_FILEOPEN, "File already open"},
- {H5E_CANTCREATE, "Can't create file"},
- {H5E_CANTOPENFILE, "Can't open file"},
- {H5E_CANTOPENOBJ, "Can't open object"},
- {H5E_NOTHDF5, "Not an HDF5 format file"},
- {H5E_BADFILE, "Bad file ID accessed"},
+ {H5E_UNSUPPORTED, "Feature is unsupported"},
+ {H5E_BADTYPE, "Incorrect type found"},
+ {H5E_BADRANGE, "Argument out of range"},
+ {H5E_BADVALUE, "Bad value for argument"},
+ {H5E_NOSPACE, "No space available for allocation"},
+ {H5E_FILEEXISTS, "File already exists"},
+ {H5E_FILEOPEN, "File already open"},
+ {H5E_CANTCREATE, "Can't create file"},
+ {H5E_CANTOPENFILE, "Can't open file"},
+ {H5E_CANTOPENOBJ, "Can't open object"},
+ {H5E_NOTHDF5, "Not an HDF5 format file"},
+ {H5E_BADFILE, "Bad file ID accessed"},
{H5E_TRUNCATED, "File has been truncated"},
- {H5E_SEEKERROR, "Seek failed"},
- {H5E_READERROR, "Read failed"},
- {H5E_WRITEERROR, "Write failed"},
- {H5E_CLOSEERROR, "Close failed"},
- {H5E_CANTINIT, "Can't initialize interface"},
- {H5E_ALREADYINIT, "Object already initialized"},
- {H5E_BADATOM, "Can't find atom information"},
- {H5E_CANTREGISTER, "Can't register new atom"},
+ {H5E_SEEKERROR, "Seek failed"},
+ {H5E_READERROR, "Read failed"},
+ {H5E_WRITEERROR, "Write failed"},
+ {H5E_CLOSEERROR, "Close failed"},
+ {H5E_CANTINIT, "Can't initialize interface"},
+ {H5E_ALREADYINIT, "Object already initialized"},
+ {H5E_BADATOM, "Can't find atom information"},
+ {H5E_CANTREGISTER, "Can't register new atom"},
{H5E_CANTFLUSH, "Can't flush object from cache"},
{H5E_CANTLOAD, "Can't load object into cache"},
{H5E_PROTECT, "Protected object error"},
- {H5E_NOTCACHED, "Object not currently cached"},
+ {H5E_NOTCACHED, "Object not currently cached"},
{H5E_NOTFOUND, "Object not found"},
{H5E_EXISTS, "Object already exists"},
{H5E_CANTENCODE, "Can't encode value"},
@@ -104,7 +96,7 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
{H5E_ALIGNMENT, "Alignment error"},
{H5E_BADMESG, "Unrecognized message"},
{H5E_COMPLEN, "Name component is too long"},
- {H5E_CWG, "Problem with current working group"},
+ {H5E_CWG, "Problem with current working group"},
{H5E_LINK, "Link count failure"},
};
@@ -112,9 +104,9 @@ static const hdf_min_error_messages_t hdf_min_error_messages[] =
static intn interface_initialize_g = FALSE;
#define INTERFACE_INIT H5E_init_interface
static herr_t H5E_init_interface(void);
+static void H5E_term_interface (void);
-
-int32 thrderrid; /* Thread-specific "global" error-handler ID */
+hid_t H5E_thrdid_g = FAIL; /* Thread-specific "global" error-handler ID */
/*--------------------------------------------------------------------------
@@ -133,17 +125,21 @@ Modifications:
Changed the pablo mask from H5_mask to H5E_mask
--------------------------------------------------------------------------*/
-static herr_t H5E_init_interface(void)
+static herr_t
+H5E_init_interface (void)
{
- herr_t ret_value = SUCCEED;
- FUNC_ENTER (H5E_init_interface, FAIL);
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER (H5E_init_interface, FAIL);
- /* Initialize the atom group for the error stacks */
- if((ret_value=H5Ainit_group(H5_ERR,H5A_ERRSTACK_HASHSIZE,0,NULL))!=FAIL)
- ret_value=H5_add_exit(&H5E_term_interface);
+ /* Initialize the atom group for the error stacks */
+ if ((ret_value=H5Ainit_group (H5_ERR, H5A_ERRSTACK_HASHSIZE, 0,
+ (herr_t (*)(void*))H5E_close))!=FAIL) {
+ ret_value = H5_add_exit (H5E_term_interface);
+ }
- FUNC_LEAVE(ret_value);
-} /* H5E_init_interface */
+ FUNC_LEAVE (ret_value);
+}
/*--------------------------------------------------------------------------
NAME
@@ -162,17 +158,18 @@ static herr_t H5E_init_interface(void)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-void H5E_term_interface (void)
+static void
+H5E_term_interface (void)
{
- H5Adestroy_group(H5_ERR);
-} /* end H5E_term_interface() */
+ H5Adestroy_group(H5_ERR);
+}
/*--------------------------------------------------------------------------
NAME
- H5Enew_err_stack -- Create a new error stack
+ H5Ecreate -- Create a new error stack
USAGE
- int32 H5Enew_err_stack(initial_stack_size);
- uintn initial_stack_size; IN: Starting size of the error stack
+ hid_t H5Ecreate (initial_stack_size);
+ uintn initial_stack_size; IN: Starting size of the error stack
RETURNS
The ID of the error stack created on success, FAIL on failure.
@@ -181,47 +178,42 @@ DESCRIPTION
Dynamically creates a new error stack to push error values onto.
--------------------------------------------------------------------------*/
-int32 H5Enew_err_stack(uintn initial_stack_size)
+hid_t
+H5Ecreate (uintn initial_stack_nelmts)
{
- H5E_errstack_t *new_stack=NULL; /* Pointer to the new error stack */
- int32 ret_value = FAIL;
-
- FUNC_ENTER(H5Enew_err_stack, FAIL);
+ H5E_t *new_stack=NULL; /* Pointer to the new error stack */
+ hid_t ret_value = FAIL;
- /* Allocate the stack header */
- if((new_stack=HDmalloc(sizeof(H5E_errstack_t)))==NULL)
- HGOTO_DONE(FAIL);
+ FUNC_ENTER (H5Ecreate, FAIL);
+ H5ECLEAR;
- /* Initialize the stack header */
- new_stack->stack_size=initial_stack_size;
- new_stack->stack_top=0;
- if((new_stack->err_stack=HDcalloc(initial_stack_size,sizeof(H5E_error_t)))==NULL)
- {
- HDfree(new_stack);
- HGOTO_DONE(FAIL);
- } /* end if */
- new_stack->push=H5E_store; /* Set the default error handler */
+ /* check args */
+ initial_stack_nelmts = MAX (10, MIN (initial_stack_nelmts, 1000));
- /* Get an atom for the error stack */
- ret_value=H5Aregister_atom(H5_ERR, new_stack);
+ /* Allocate the stack header */
+ new_stack = H5MM_xmalloc (sizeof(H5E_t));
-done:
- if(ret_value == FAIL)
- { /* Error condition cleanup */
+ /* Initialize the stack header */
+ new_stack->nelmts = initial_stack_nelmts;
+ new_stack->top = 0;
+ new_stack->stack = H5MM_xcalloc (initial_stack_nelmts, sizeof(H5E_error_t));
+ new_stack->push = H5E_push; /* Set the default error handler */
- } /* end if */
+ /* Get an atom for the error stack */
+ if ((ret_value = H5Aregister_atom (H5_ERR, new_stack))<0) {
+ HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL,
+ "unable to register error stack");
+ }
- /* Normal function cleanup */
-
- FUNC_LEAVE(ret_value);
-} /* H5Enew_err_stack */
+ FUNC_LEAVE (ret_value);
+}
/*--------------------------------------------------------------------------
NAME
- H5Edelete_err_stack -- Destroy an error stack
+ H5Eclose -- Destroy an error stack
USAGE
- intn H5Edelete_err_stack(err_stack);
- int32 err_stack; IN: Error stack to delete
+ herr_t H5Eclose (err_stack);
+ hid_t err_stack; IN: Error stack to delete
RETURNS
SUCCEED/FAIL
@@ -230,51 +222,108 @@ DESCRIPTION
Destroys an error stack, releasing memory allocated, etc.
--------------------------------------------------------------------------*/
-intn H5Edelete_err_stack(int32 err_stack)
+herr_t
+H5Eclose (hid_t estack_id)
{
- H5E_errstack_t *old_stack=NULL; /* Pointer to the new error stack */
- intn ret_value = SUCCEED;
-
- FUNC_ENTER(H5Edelete_err_stack, FAIL);
-
- /* Clear errors and check args and all the boring stuff. */
- if (H5Aatom_group(err_stack)!=H5_ERR)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack");
-
- /* Get the error stack to put the error on */
- if((old_stack=H5Aremove_atom(err_stack))==NULL)
- HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't remove atom");
-
- /* Clear the error descriptions and reset the stack top */
- for(; old_stack->stack_top>0; old_stack->stack_top--)
- {
- if (old_stack->err_stack[old_stack->stack_top-1].desc)
- {
- HDfree(old_stack->err_stack[old_stack->stack_top-1].desc);
- old_stack->err_stack[old_stack->stack_top-1].desc=NULL;
- } /* end if */
- } /* end if */
-
- HDfree(old_stack->err_stack);
- HDfree(old_stack);
-
-done:
- if(ret_value == FAIL)
- { /* Error condition cleanup */
-
- } /* end if */
-
- /* Normal function cleanup */
-
- FUNC_LEAVE(ret_value);
-} /* H5Edelete_err_stack */
+ FUNC_ENTER (H5Eclose, FAIL);
+ H5ECLEAR;
+
+ /* check args */
+ if (H5_ERR!=H5Aatom_group (estack_id)) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack");
+ }
+
+ /*
+ * Decrement the reference count. When it reaches zero the error stack
+ * will be freed.
+ */
+ H5A_dec_ref (estack_id);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Epush
+ *
+ * Purpose: Pushes a new error record onto error stack ESTACK_ID. The
+ * error has major and minor numbers MAJ_NUM and MIN_NUM, the
+ * name of a function where the error was detected, the name of
+ * the file where the error was detected, and the line within
+ * that file. An error description string is also passed to
+ * this function.
+ *
+ * The FUNCTION_NAME is copied (and possibly truncated) into a
+ * fixed length character buffer; the FILE_NAME is pointed to
+ * without copying it (we assume it's statically allocated from
+ * __FILE__); and the DESC argument is strdup'd.
+ *
+ * It is safe to call this function before the thread global
+ * error stack is initialized.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Epush (hid_t estack_id, H5E_major_t maj_num, H5E_minor_t min_num,
+ const char *function_name, const char *file_name, intn line,
+ const char *desc)
+{
+
+ H5E_t *estack = NULL; /* Ptr to the stack to put value on */
+
+ /*
+ * WARNING WARNING WARNING: We cannot call HERROR() from within this
+ * function if ESTACK_ID is the thread global error stack or else we may
+ * enter infinite recursion. Furthermore, we also cannot call any other
+ * HDF5 macro or function which might call HERROR(). HERROR() is called
+ * by HRETURN_ERROR() which could be called by FUNC_ENTER().
+ */
+
+ /*
+ * Clear the thread global error stack only if it isn't the error stack on
+ * which we're pushing the new error.
+ */
+ if (estack_id!=H5E_thrdid_g) H5ECLEAR;
+
+ /*
+ * check args, but don't call error functions if ESTACK_ID is the thread
+ * global error handler.
+ */
+ if (H5_ERR!=H5Aatom_group (estack_id) ||
+ NULL==(estack=H5Aatom_object (estack_id))) {
+ HRETURN (FAIL);
+ }
+ if (!function_name || !file_name || !desc) {
+ HRETURN (FAIL);
+ }
+ if (!estack->push) {
+ HRETURN (FAIL);
+ }
+
+ /* Push the new error. It must be safe to call the push function. */
+ if ((estack->push)(estack, maj_num, min_num, function_name, file_name,
+ line, desc)<0) {
+ HRETURN (FAIL);
+ }
+
+ return SUCCEED; /*don't use FUNC_LEAVE() here*/
+}
/*--------------------------------------------------------------------------
NAME
H5Eclear -- Clear an error stack for later error entries
USAGE
void H5Eclear(int32 err_hand)
- int32 err_hand; IN: The ID of the error stack to push the error onto.
+ int32 err_hand; IN: The ID of the error stack to push the error onto.
RETURNS
SUCCEED/FAIL
@@ -283,200 +332,275 @@ DESCRIPTION
--------------------------------------------------------------------------*/
herr_t
-H5Eclear (int32 err_hand)
+H5Eclear (hid_t estack_id)
{
- H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER (H5Eclear, FAIL);
-
- /* Get the error stack for this error handler, initialized earlier in H5Enew_err_stack */
- if (H5Aatom_group(err_hand)!=H5_ERR)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack");
-
- /* Get the error stack to put the error on */
- if((err_stack=H5Aatom_object(err_hand))==NULL)
- HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL, "not an error stack");
-
- /* Clear the error descriptions and reset the stack top */
- for(; err_stack->stack_top>0; err_stack->stack_top--)
- {
- if (err_stack->err_stack[err_stack->stack_top-1].desc)
- {
- HDfree(err_stack->err_stack[err_stack->stack_top-1].desc);
- err_stack->err_stack[err_stack->stack_top-1].desc=NULL;
- } /* end if */
- } /* end if */
-
-done:
- if(ret_value == FAIL)
- { /* Error condition cleanup */
-
- } /* end if */
-
- /* Normal function cleanup */
-
- FUNC_LEAVE (ret_value);
-} /* H5Eclear */
-
-/*--------------------------------------------------------------------------
-NAME
- H5E_store -- Push an error value on an error stack
-USAGE
- void H5E_store(hdf_err_code_t err, const char *function_name, const char *file_name, intn line)
- hdf_err_code_t err; IN: The error code which occurred.
- const char *function_name; IN: Name of the function the error occurred within.
- const char *file_name; IN: Name of the file the error occurred within.
- intn line; IN: Line # in the file the error occurred on.
+ H5E_t *estack = NULL;
+
+ FUNC_ENTER (H5Eclear, FAIL);
+
+ /*
+ * Normally we would clear the thread error stack since we're entering an
+ * API function, but we have to be careful here to not get into an
+ * infinite recursion.
+ */
+ if (estack_id != H5E_thrdid_g) H5ECLEAR;
+
+ /* check args */
+ if (H5_ERR!=H5Aatom_group (estack_id) ||
+ NULL==(estack=H5Aatom_object (estack_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack");
+ }
+
+ if (H5E_clear (estack)<0) {
+ HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL,
+ "unable to clear error stack");
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5Eprint
+ *
+ * Purpose: Prints the current contents of error stack ESTACK_ID to the
+ * stream FILE.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5Eprint (hid_t estack_id, FILE *file)
+{
+ H5E_t *estack = NULL;
-RETURNS
- SUCCESS/FAIL
-DESCRIPTION
- Pushes an error onto an error stack for this thread. (This is the default
- action when errors occur, but can be overridden by user's code)
-
---------------------------------------------------------------------------*/
+ FUNC_ENTER (H5Eprint, FAIL);
+ /*
+ * Don't clear the thread error stack if it's the one we're about to
+ * print.
+ */
+ if (estack_id!=H5E_thrdid_g) H5ECLEAR;
+
+ /* check args */
+ if (H5_ERR!=H5Aatom_group (estack_id) ||
+ NULL==(estack=H5Aatom_object (estack_id))) {
+ HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not an error stack");
+ }
+ if (!file) file = stderr;
+
+ /* print it */
+ if (H5E_print (estack, file)<0) {
+ HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL,
+ "can't print error stack");
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5E_close
+ *
+ * Purpose: Frees resources associated with an error stack.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5E_store(int32 errid, H5E_major_t maj, H5E_minor_t min, const char *function_name, const char *file_name, intn line)
+H5E_close (H5E_t *estack)
{
- H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER(H5E_store, FAIL);
-
- /* Clear errors and check args and all the boring stuff. */
- H5Eclear(errid);
-
- /* Get the error stack to put the error on */
- if((err_stack=H5Aatom_object(errid))==NULL)
- HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL, "not an error stack");
-
- /* Check if we need to expand the stack */
- if(err_stack->stack_top>=err_stack->stack_size)
- {
- H5E_error_t *old_stack=err_stack->err_stack; /* in case realloc fails */
-
- /* Ask for new stack that's twice as large */
- if((err_stack->err_stack=HDrealloc(old_stack,2*err_stack->stack_size))==NULL)
- {
- err_stack->err_stack=old_stack;
- HGOTO_DONE(FAIL);
- } /* end if */
- err_stack->stack_size *= 2; /* increase the size of the stack */
- } /* end if */
-
- /* Push the error onto the error stack */
- err_stack->err_stack[err_stack->stack_top].maj=maj;
- err_stack->err_stack[err_stack->stack_top].min=min;
- HDstrncpy(err_stack->err_stack[err_stack->stack_top].function_name,function_name,MAX_FUNC_NAME_LEN);
- err_stack->err_stack[err_stack->stack_top].file_name=file_name;
- err_stack->err_stack[err_stack->stack_top].line=line;
-
- /* Increment the top of the error stack */
- err_stack->stack_top++;
-
-done:
- if(ret_value == FAIL)
- { /* Error condition cleanup */
-
- } /* end if */
-
- /* Normal function cleanup */
+ FUNC_ENTER (H5E_close, FAIL);
+
+ /* check args */
+ assert (estack);
+
+ /* clear error stack, then free it */
+ H5E_clear (estack);
+ H5MM_xfree (estack->stack);
+ H5MM_xfree (estack);
+
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5E_clear
+ *
+ * Purpose: Clears an error stack but does not release the stack.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5E_clear (H5E_t *estack)
+{
+ int i;
+
+ FUNC_ENTER (H5E_clear, FAIL);
- FUNC_LEAVE (ret_value);
-} /* H5E_store */
+ /* check args */
+ assert (estack);
-/*--------------------------------------------------------------------------
-NAME
- H5Epush -- Push an error value on an error stack
-USAGE
- void H5Epush(hdf_err_code_t err, const char *function_name, const char *file_name, intn line)
- hdf_err_code_t err; IN: The error code which occurred.
- const char *function_name; IN: Name of the function the error occurred within.
- const char *file_name; IN: Name of the file the error occurred within.
- intn line; IN: Line # in the file the error occurred on.
+ /* Clear the error descriptions and reset the stack top */
+ for (i=0; i<estack->top; i++) {
+ H5MM_xfree (estack->stack[i].desc);
+ estack->stack[i].desc = NULL;
+ }
+ estack->top = 0;
-RETURNS
- SUCCEED/FAIL
-DESCRIPTION
- Pushes an error onto an error stack for this thread.
-
---------------------------------------------------------------------------*/
+ FUNC_LEAVE (SUCCEED);
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5E_push
+ *
+ * Purpose: Push an error onto an error stack. The FUNCTION_NAME is
+ * copied (and possibly truncated) into the error record. The
+ * FILE_NAME pointer is used directly since we assume it came
+ * from the __FILE__ construct and is thus static data. The
+ * description, DESC, is strdup'd into the error record.
+ *
+ * Note: Warning: to prevent infinite recursivion this function must
+ * not call any other HDF5 function and especially not
+ * the HDF5 error handling macros.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
herr_t
-H5Epush(H5E_major_t maj, H5E_minor_t min, const char *function_name, const char *file_name, intn line)
+H5E_push (H5E_t *estack, H5E_major_t maj_num, H5E_minor_t min_num,
+ const char *function_name, const char *file_name, intn line,
+ const char *desc)
{
- H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
- herr_t ret_value = SUCCEED;
-
- FUNC_ENTER(H5Epush, FAIL);
-
- /* Clear errors and check args and all the boring stuff. */
- if (function_name==NULL || file_name==NULL || H5Aatom_group(thrderrid)!=H5_ERR)
- HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "wrong arguments");
-
- /* Get the error stack to put the error on */
- if((err_stack=H5Aatom_object(thrderrid))==NULL)
- HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL, "not an error stack");
- (err_stack->push)(thrderrid, maj, min, function_name, file_name, line);
-
-done:
- if(ret_value == FAIL)
- { /* Error condition cleanup */
-
- } /* end if */
-
- /* Normal function cleanup */
-
- FUNC_LEAVE (ret_value);
-} /* H5Epush */
-
-#ifdef H5_ERROR_DEBUG
-/*--------------------------------------------------------------------------
-NAME
- H5Eset_push -- Set the function to call when an error value is reported
-USAGE
- H5E_push_func_t H5Eset_push(H5E_push_func_t func)
- H5E_push_func_t func; IN: New function to call when an error occurs.
+ /* FUNC_ENTER (H5E_push, FAIL); -- can't do this here! */
+
+ /* check args */
+ assert (estack);
+ assert (function_name);
+ assert (file_name);
+
+ /* Check if we need to expand the stack */
+ if (estack->top >= estack->nelmts) {
+ /*
+ * Ask for new stack that's twice as large. Do not use hdf5 functions
+ * to allocate the memory!
+ */
+ estack->nelmts *= 2;
+ estack->stack = realloc (estack->stack,
+ estack->nelmts * sizeof(H5E_error_t));
+ assert (estack->stack);
+ }
-RETURNS
- The function pointer to the previous error function on success, NULL on
- failure.
-DESCRIPTION
- Changes the function which is called for errors on this thread. The thread
- ID is implicit, ie. this function must be called within each thread whose
- error function is to be changed.
-
---------------------------------------------------------------------------*/
-H5E_push_func_t H5Eset_push(H5E_push_func_t func)
+ /* Push the error onto the error stack */
+ estack->stack[estack->top].maj_num = maj_num;
+ estack->stack[estack->top].min_num = min_num;
+ HDstrncpy (estack->stack[estack->top].func_name, function_name,
+ MAX_FUNC_NAME);
+ estack->stack[estack->top].func_name[MAX_FUNC_NAME-1] = '\0';
+ estack->stack[estack->top].file_name = file_name;
+ estack->stack[estack->top].line = line;
+
+ /* strdup the description but don't use H5MM_xstrdup() */
+ estack->stack[estack->top].desc = malloc (strlen (desc) + 1);
+ assert (estack->stack[estack->top].desc);
+ strcpy (estack->stack[estack->top].desc, desc);
+
+ /* Increment the top of the error stack */
+ estack->top++;
+
+ return SUCCEED; /*don't use FUNC_LEAVE() here*/
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: H5E_print
+ *
+ * Purpose: Prints an error stack ESTACK to the stream FILE.
+ *
+ * Return: Success: SUCCEED
+ *
+ * Failure: FAIL
+ *
+ * Programmer: Robb Matzke
+ * Friday, December 12, 1997
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+herr_t
+H5E_print (H5E_t *estack, FILE *file)
{
- CONSTR(FUNC, "H5Eset_push"); /* For HERROR */
- H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */
- H5E_push_func_t ret_value = NULL;
-
- FUNC_ENTER(H5Eset_push, NULL);
-
- /* Clear errors and check args and all the boring stuff. */
- H5ECLEAR;
- if (func==NULL)
- HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL);
-
- /* Get the error stack to put the error on */
- if((err_stack=H5Aatom_object(thrderrid))==NULL)
- HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, NULL);
-
- ret_value=err_stack->push;
- err_stack->push=func;
-
-done:
- if(ret_value == NULL)
- { /* Error condition cleanup */
-
- } /* end if */
-
- /* Normal function cleanup */
+ intn i, j;
+ const char *maj_str = NULL;
+ const char *min_str = NULL;
+
+ FUNC_ENTER (H5E_print, FAIL);
- FUNC_LEAVE(ID_H5Eset_push, ret_value);
-} /* H5Eset_push */
-#endif /* H5_ERROR_DEBUG */
+ /* check args */
+ assert (estack);
+ assert (file);
+ if (0==estack->top) HRETURN (SUCCEED);
+
+ fprintf (file, "HDF5-DIAG: error stack:\n");
+ for (i=0; i<estack->top; i++) {
+
+ /* Find major and minor error strings */
+ for (j=0, maj_str="??"; j<NELMTS (H5E_major_mesg_g); j++) {
+ if (H5E_major_mesg_g[j].error_code==estack->stack[i].maj_num) {
+ maj_str = H5E_major_mesg_g[j].str;
+ break;
+ }
+ }
+ for (j=0, min_str="??"; j<NELMTS (H5E_minor_mesg_g); j++) {
+ if (H5E_minor_mesg_g[j].error_code==estack->stack[i].min_num) {
+ min_str = H5E_minor_mesg_g[j].str;
+ break;
+ }
+ }
+
+ /* Print error message */
+ fprintf (file, " #%03d: %s:%d in %s() error %02d/%02d: %s\n",
+ i, estack->stack[i].file_name, estack->stack[i].line,
+ estack->stack[i].func_name, estack->stack[i].maj_num,
+ estack->stack[i].min_num, estack->stack[i].desc);
+ fprintf (file, " %s (%s)\n", maj_str, min_str);
+ }
+
+ FUNC_LEAVE (SUCCEED);
+}