// ****************************************************************************
//  Project:        libguytools
// ****************************************************************************
//  Programmer:     Guy Voncken
//                  Police Grand-Ducale
//                  Service de Police Judiciaire
//                  Section Nouvelles Technologies
// ****************************************************************************
//  Module:         Error handling
// ****************************************************************************

// Copyright 2008, 2009, 2010, 2011, 2012 Guy Voncken
//
// This file is part of libguytools.
//
// libguytools is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// libguytools is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with libguytools. If not, see <http://www.gnu.org/licenses/>.

#ifndef __TOOLERROR_H__
#define __TOOLERROR_H__

#ifndef __FFL__
   #define __FFL__ __FILE__, __FUNCTION__, __LINE__
#endif

// -----------
//  Constants
// -----------

#define NO_ERROR 0

// ---------------------------------------
//  Macros for comfortable error checking
// ---------------------------------------

#define CHK(Func)                              \
/*lint -save -e506 -e774*/   /*Warning 506: Constant value Boolean; Info 774: Boolean within 'if' always evaluates to True */ \
   {                                           \
      APIRET ec;                               \
      if ((ec = Func) != NO_ERROR)             \
      {                                        \
         (void)ToolErrorCheck (__FFL__, ec);   \
         return ec;                            \
      }                                        \
   }                                           \
/*lint -restore*/


#define CHK_CONST(ec)                          \
   {                                           \
      (void)ToolErrorCheck (__FFL__, ec);      \
      return ec;                               \
   }                                           \


#define CHK_RET(Func)                          \
   {                                           \
      APIRET ec;                               \
      if ((ec = Func) != NO_ERROR)             \
         return ec;                            \
   }


#define CHK_NORET(Func)                        \
   {                                           \
      APIRET ec;                               \
      if ((ec = Func) != NO_ERROR)             \
         (void)ToolErrorCheck (__FFL__, ec);   \
   }



#define TOOL_CHK(Fn)        \
{                           \
   APIRET ec;               \
   if ((ec=Fn) != NO_ERROR) \
      return ec;            \
}

// ------------------
//  Type definitions
// ------------------

typedef long    APIRET;
typedef long * pAPIRET;

// -----------------------------
//  ToolError's own error codes
// -----------------------------

enum
{
   TOOL_ERROR_ENTRY_NOT_FOUND     = ERROR_BASE_TOOL_ERROR + 1,
   TOOL_ERROR_DUPLICATE_ENTRY     ,
   TOOL_ERROR_NOT_INITIALISED     ,
   TOOL_ERROR_ALREADY_INITIALISED
};

// -------------------------------
//  Prototypes and wrapper macros
// -------------------------------

typedef void (* t_pToolErrorLogFn)(const char *pFileName, const char *pFunctionName, int LineNr, const char *pFormat, va_list pArguments);

APIRET      ToolErrorSetLogFn       (t_pToolErrorLogFn pLogFn);
APIRET      ToolErrorRegisterError  (int ErrorCode, const char *pErrorMsg);
APIRET      ToolErrorGetMessage     (int ErrorCode, const char **ppMessage);
const char *ToolErrorMessage        (int ErrorCode);
const char *ToolErrorTranslateErrno (int Errno);


APIRET ToolErrorInit          (int MaxErrors);
APIRET ToolErrorDeInit        (void);

APIRET ToolErrorCheck         (char const *pFileName, char const *pFunctionName, int LineNr, int ErrorCode);
APIRET ToolErrorLog           (char const *pFileName, char const *pFunctionName, int LineNr, const char * pFormat, ...) __attribute__ ((format (printf, 4, 5)));

#define TOOL_ERROR_REGISTER_CODE(ErrorCode) ToolErrorRegisterError(ErrorCode, #ErrorCode)

#endif

