#ifndef __SAL_ERROR_DEFINES_HEADER
#define __SAL_ERROR_DEFINES_HEADER

/*
 * libsal/error/all-systems/defines.h
 * Macros and stuff for error-handling library
 * 
 * Part of the System Abstraction Layer
 */

/* -------------------------------------------------------------------------
 * ERROR_CHECK()
 * Checks the return value from a call to see if an error has occured.
 * If so, automatically calls sal_error_handle() to report the error.
 * If the error is only a warning, then this returns, and you can then
 * process the error yourself.
 */

#define ERROR_CHECK(x, y) \
  (y) = (x); \
  if ((y).ulErrorCode != 0) \
    sal_error_Handle((y));

/* -------------------------------------------------------------------------
 * ERROR_HANDLE()
 * Checks the return value from a call to see if an error has occured
 * If so, automatically calls sal_error_handle() to report the error.
 */

#define ERROR_HANDLE(x) \
{ \
  sal_error __sal_error_check = (x); \
  \
  if (__sal_error_check.ulErrorCode != 0) \
    sal_error_Handle(__sal_error_check); \
}

/* -------------------------------------------------------------------------
 * RETURN_ERROR()
 * Builds and returns a sal_error structure to your exact specifications.
 * One advantage about this macro is that it ensures that information
 * about *WHERE* the error was reported is correctly put into place.
 */

#define RETURN_ERROR(x, y) \
{ \
  sal_error __sal_error_check; \
  \
  __sal_error_check.ulErrorApi = (x); \
  __sal_error_check.ulErrorCode = (y); \
  __sal_error_check.ulLine = __LINE__ ; \
  __sal_error_check.szFile = __FILE__ ; \
  __sal_error_check.boCaught = FALSE; \
  \
  return __sal_error_check; \
}

/* -------------------------------------------------------------------------
 * RETURN_NO_ERROR()
 * Builds and returns a sal_error structure which states that there is no
 * error code at all.
 */

#define RETURN_NO_ERROR \
{ \
  sal_error __sal_error_check; \
  \
  __sal_error_check.ulErrorApi = 0; \
  __sal_error_check.ulErrorCode = 0; \
  __sal_error_check.boCaught = TRUE; \
  return __sal_error_check; \
}

/* -------------------------------------------------------------------------
 * ERROR_TABLE()
 * Create an entry in a static error table.
 */

#define ERROR_TABLE(a,b,c,d) \
{ a, SAL_DEBUG_MSG_ ## b, c, #a, d }

/* -------------------------------------------------------------------------
 * END_ERROR_TABLE()
 * End an error table
 */

#define END_ERROR_TABLE  \
{ 0, 0, 0, NULL, NULL }

/* -------------------------------------------------------------------------
 * ERROR_API()
 * Define and register an error API
 */

#define ERROR_API(a,b,c) \
{ \
  sal_error_api __stErrorApi; \
  __stErrorApi.ulErrorApi = a; \
  __stErrorApi.szDesc = b; \
  __stErrorApi.pstErrorTable = &c[0]; \
  sal_error_RegisterApi(&__stErrorApi); \
}

/* -------------------------------------------------------------------------
 * SAL_ERROR_SYSTEM
 * System Errors API
 */

#define SAL_ERROR_SYSTEM 0

#if 0
/* -------------------------------------------------------------------------
 * TRY()
 * Call a function, and prepare to check for errors on the result
 */

#define TRY(x) \
{ \
  sal_error __stError; \
  __stError = (x); \
  \
  if (__stError.ulErrorApi != 0 && __stError.ulErrorCode != 0) \
    switch(__stError.ulErrorApi) \
    {
#endif 
/* -------------------------------------------------------------------------
 * CATCH_API()
 * Check for errors on the result of a TRY() macro
 */

#define CATCH_API(x) \
  case (x) : \
  switch(__stError.ulErrorCode) \
  {
      
/* -------------------------------------------------------------------------
 * CATCH_CODE()
 * Check for errors on the result of a TRY() macro
 */

#define CATCH_CODE(y) \
  case (y): \
    __stError.boCaught = TRUE;
    
/* -------------------------------------------------------------------------
 */

#define END_CATCH_API \
  }

#define END_TRY \
  } \
  if (!__stError.boCaught) return __stError; \
}

#define THROW(x) \
  (x).boCaught = FALSE; \
  return (x)

#endif /* __SAL_ERROR_DEFINES_HEADER */
