/** @file  psError.h
 *
 *  @brief Contains the declarations for the error reporting functions
 *
 *  Error reporting functions shall be used to create log entries in the
 *  event errors are detected.  The messages shall give enough information
 *  to allow the user to know where the error has occurred and the type
 *  of error detected.
 *
 *  @ingroup ErrorHandling
 *
 *  @author Eric Van Alst, MHPCC
 *
 *  @version $Revision: 1.22 $ $Name: not supported by cvs2svn $
 *  @date $Date: 2005-06-09 19:26:48 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */

#ifndef PS_ERROR_H
#define PS_ERROR_H

#include<stdio.h>
#include<stdbool.h>
#include<stdarg.h>

#include "psErrorCodes.h"

/** @addtogroup ErrorHandling
 *  @{
 */

/** Error message object */
typedef struct
{
    char* name;                        ///< category of code that caused the error
    psErrorCode code;                  ///< class of error
    char* msg;                         ///< the message associated with the error
}
psErr;

/** Get a error from the error stack
 *
 *  Previous errors on the stack are returned by psErrorGet (a value of 0
 *  passed to psErrorGet is equivalent to a call to psErrorLast).
 *
 *  if no error is at the which position, a non-NULL psErr is returned with
 *  code PS_ERR_NONE.
 *
 *  @return    Error message object at 'which'
 */
psErr* psErrorGet(
    psS32 which                          ///< position in the error stack. 0 is last error on stack.
);

/** Get last error put on the error stack
 *
 *  The last error reported is available from psErrorLast; if no errors are
 *  current, a non-NULL psErr is returned with code PS_ERR_NONE.
 *
 *  @return psErr*     Reference to last error message on error stack
 */
psErr* psErrorLast(void);

/** Clears the error stack.
 *
 *  The error stack may be completely cleared with psErrorClear.
 *
 */
void psErrorClear(void);

/** Get the error stack depth
 *
 *  @return psS32   The number of items on the error stack
 */
psS32 psErrorGetStackSize();

/** Prints error stack to specified open file descriptor
 *
 *  The entire error stack may be printed to an open file descriptor by
 *  calling psErrorStackPrint; if and only if there are current errors, the
 *  printf-style string fmt is first printed to the file descriptor fd. In
 *  this printout, error codes are replaced by their string equivalents.
 *
 */
void psErrorStackPrint(
    FILE* fd,                          ///< destination file descriptor
    const char* fmt,                   ///< printf-style format of header line
    ...                                ///< any parameters required in fmt
);

#ifndef SWIG
/** Prints error stack to specified open file descriptor
 *
 *  The entire error stack may be printed to an open file descriptor by
 *  calling psErrorStackPrintV; if and only if there are current errors, the
 *  vprintf-style string fmt is first printed to the file descriptor fd. In
 *  this printout, error codes are replaced by their string equivalents.
 *
 */
void psErrorStackPrintV(
    FILE* fd,                          ///< destination file descriptor
    const char* fmt,                   ///< printf-style format of header line
    va_list va                         ///< any parameters required in fmt
);
#endif // #ifndef SWIG

#ifdef DOXYGEN
/** Reports an error message to the logging facility
 *
 *  This function will invoke the psLogMsg function with a level of
 *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
 *  log message.
 *
 *  This function modifies the error stack.
 *
 *  @return psErrorCode    the given error code
 */
psErrorCode psError(
    psErrorCode code,                  ///< Error class code
    psBool new,                        ///< true if error originates at this location
    const char* fmt,                   ///< printf-style format of header line
    ...                                ///< any parameters required in fmt
);

/** Logs a warning message.
 *
 *  This procedure logs a message to the destination set by a prior
 *  call to psLogSetDestination(), This is equivalent to calling
 *  psLogMsg with a level of PS_LOG_WARN.
 *
 */
void psWarning(
    const char* fmt,                   ///< printf-style format of header line
    ...                                ///< any parameters required in fmt
);
#else // #ifdef DOXYGEN

/** Reports an error message to the logging facility
 *  
 *  This function will invoke the psLogMsg function with a level of
 *  PS_LOG_ERROR and pass the parameters name and fmt to generate a proper
 *  log message.  This function is used to check a specific code location.
 *  
 *  This function modifies the error stack.
 *
 *  @return psErrorcode    the given error code
 */
psErrorCode p_psError(
    const char* file,                  ///< file name
    int lineno,                        ///< line number in file
    const char* func,                  ///< function name
    psErrorCode code,                  ///< Error class code
    psBool new,                        ///< true if error originates at this location
    const char* fmt,                   ///< printf-style format of header line
    ...                                ///< any parameters required in fmt
);

/** Logs a warning message.
 *  
 *  This procedure logs a message to the destination set by a prior call to
 *  psLogSetDestination().  This is equivalent to calling psLogMsg with a level of 
 *  PS_LOG_WARN.  This function is used to check a specific code location.
 *  
*/
void p_psWarning(
    const char* file,                  ///< file name
    int lineno,                        ///< line number in file
    const char* func,                  ///< function name
    const char* fmt,                   ///< printf-style format of header line
    ...                                ///< any parameters required in fmt
);


#ifndef SWIG
#define psError(code,new,...) p_psError(__FILE__,__LINE__,__func__,code,new,__VA_ARGS__)
#define psWarning(...) p_psWarning(__FILE__,__LINE__,__func__,__VA_ARGS__)
#endif // #ifndef SWIG

#endif // ! DOXYGEN

/** Create a new psErr struct
 *
 *  Creates a new psErr struct, making a copy of the parameters.
 *
 *  @return psErr*     new psErr object
 */
psErr* psErrAlloc(
    const char* name,                  ///< Name of error in the form aaa.bbb.ccc
    psErrorCode code,                  ///< Error class code
    const char* msg                    ///< Error message
);

/* @} */// End of SysUtils Functions

#endif
