/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * 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 LICENSE 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.                                                        *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#ifndef H5Eprivate_H
#define H5Eprivate_H

#include "H5Epublic.h"

#include "H5private.h"

#define H5E_PAUSE_ERRORS H5E_pause_stack();

#define H5E_RESUME_ERRORS H5E_resume_stack();

#define HERROR(maj_id, min_id, ...)                                                                          \
    do {                                                                                                     \
        H5E_printf_stack(__FILE__, __func__, __LINE__, maj_id, min_id, __VA_ARGS__);                         \
    } while (0)

#define HCOMMON_ERROR(maj, min, ...)                                                                         \
    do {                                                                                                     \
        HERROR(maj, min, __VA_ARGS__);                                                                       \
        err_occurred = true;                                                                                 \
        err_occurred = err_occurred;                                              \
    } while (0)

#define HDONE_ERROR(maj, min, ret_val, ...)                                                                  \
    do {                                                                                                     \
        HCOMMON_ERROR(maj, min, __VA_ARGS__);                                                                \
        ret_value = ret_val;                                                                                 \
    } while (0)

#define HGOTO_ERROR(maj, min, ret_val, ...)                                                                  \
    do {                                                                                                     \
        HCOMMON_ERROR(maj, min, __VA_ARGS__);                                                                \
        HGOTO_DONE(ret_val);                                                                                 \
    } while (0)

#define HGOTO_ERROR_TAG(maj, min, ret_val, ...)                                                              \
    do {                                                                                                     \
        H5AC_tag(prv_tag, NULL);                                                                             \
        HCOMMON_ERROR(maj, min, __VA_ARGS__);                                                                \
        HGOTO_DONE(ret_val);                                                                                 \
    } while (0)

#define HGOTO_DONE(ret_val)                                                                                  \
    do {                                                                                                     \
        ret_value = ret_val;                                                                                 \
        goto done;                                                                                           \
    } while (0)

#define HGOTO_DONE_TAG(ret_val)                                                                              \
    do {                                                                                                     \
        H5AC_tag(prv_tag, NULL);                                                                             \
        HGOTO_DONE(ret_val);                                                                                 \
    } while (0)

#ifndef H5_HAVE_WIN32_API
#define HSYS_DONE_ERROR(majorcode, minorcode, retcode, str)                                                  \
    {                                                                                                        \
        int myerrno = errno;                                                                                 \
                                                                                                          \
        HDONE_ERROR(majorcode, minorcode, retcode, "%s, errno = %d, error message = '%s'", str, myerrno,     \
                    strerror(myerrno));                                                                      \
    }
#define HSYS_GOTO_ERROR(majorcode, minorcode, retcode, str)                                                  \
    {                                                                                                        \
        int myerrno = errno;                                                                                 \
                                                                                                          \
        HGOTO_ERROR(majorcode, minorcode, retcode, "%s, errno = %d, error message = '%s'", str, myerrno,     \
                    strerror(myerrno));                                                                      \
    }
#else 

#define HSYS_DONE_ERROR(majorcode, minorcode, retcode, str)                                                  \
    {                                                                                                        \
        int   myerrno   = errno;                                                                             \
        DWORD win_error = GetLastError();                                                                    \
                                                                                                          \
        HDONE_ERROR(majorcode, minorcode, retcode,                                                           \
                    "%s, errno = %d, error message = '%s', Win32 GetLastError() = %" PRIu32 "", str,         \
                    myerrno, strerror(myerrno), win_error);                                                  \
    }
#define HSYS_GOTO_ERROR(majorcode, minorcode, retcode, str)                                                  \
    {                                                                                                        \
        int   myerrno   = errno;                                                                             \
        DWORD win_error = GetLastError();                                                                    \
                                                                                                          \
        HGOTO_ERROR(majorcode, minorcode, retcode,                                                           \
                    "%s, errno = %d, error message = '%s', Win32 GetLastError() = %" PRIu32 "", str,         \
                    myerrno, strerror(myerrno), win_error);                                                  \
    }
#endif 

#ifdef H5_HAVE_PARALLEL

#define HMPI_DONE_ERROR(retcode, str, mpierr)                                                                \
    {                                                                                                        \
        char H5E_mpi_error_str[MPI_MAX_ERROR_STRING];                                                        \
        int  H5E_mpi_error_str_len;                                                                          \
                                                                                                             \
        MPI_Error_string(mpierr, H5E_mpi_error_str, &H5E_mpi_error_str_len);                                 \
        HDONE_ERROR(H5E_INTERNAL, H5E_MPI, retcode, "%s: MPI error string is '%s'", str, H5E_mpi_error_str); \
    }
#define HMPI_GOTO_ERROR(retcode, str, mpierr)                                                                \
    {                                                                                                        \
        char H5E_mpi_error_str[MPI_MAX_ERROR_STRING];                                                        \
        int  H5E_mpi_error_str_len;                                                                          \
                                                                                                             \
        MPI_Error_string(mpierr, H5E_mpi_error_str, &H5E_mpi_error_str_len);                                 \
        HGOTO_ERROR(H5E_INTERNAL, H5E_MPI, retcode, "%s: MPI error string is '%s'", str, H5E_mpi_error_str); \
    }
#endif 

typedef struct H5E_user_cb_state_t {
#ifndef H5_NO_DEPRECATED_SYMBOLS
    unsigned vers; 
    union {
        H5E_auto1_t func1;
        H5E_auto2_t func2;
    } u;
#else           
    H5E_auto2_t func2;
#endif          
    void *data; 
} H5E_user_cb_state_t;

H5_DLL herr_t H5E_init(void);
H5_DLL herr_t H5E_get_default_auto_func(H5E_auto2_t *func);
H5_DLL herr_t H5E_printf_stack(const char *file, const char *func, unsigned line, hid_t maj_idx,
                               hid_t min_idx, const char *fmt, ...);
H5_DLL herr_t H5E_clear_stack(void);
H5_DLL herr_t H5E_dump_api_stack(void);
H5_DLL void   H5E_pause_stack(void);
H5_DLL void   H5E_resume_stack(void);
H5_DLL herr_t H5E_user_cb_prepare(H5E_user_cb_state_t *state);
H5_DLL herr_t H5E_user_cb_restore(const H5E_user_cb_state_t *state);

#endif 
