/* Copyright (C) 1994 - 2001 by Telelogic AB.
Copyright (C) 1991, 1992, 1993, 1994 by Telelogic Malmoe AB.
Copyright (C) 1990, 1991, 1999 by Telesoft Europe AB.
This Program is owned by Telelogic and is protected by national
copyright laws and international copyright treaties. Telelogic
grants you the right to use this Program on one computer or in
one local computer network at any one time.
Under this License you may only modify the source code for the purpose
of adapting it to your environment. You must reproduce and include
any copyright and trademark notices on all copies of the source code.
You may not use, copy, merge, modify or transfer the Program except as
provided in this License.
Telelogic does not warrant that the Program will meet your
requirements or that the operation of the Program will be
uninterrupted and error free. You are solely responsible that the
selection of the Program and the modification of the source code
will achieve your intended result and that the results are actually
obtained. */

#ifndef __ems_h
#define __ems_h

/************************
 *     Error messages
 */

#define CUCF_ERROR(errorcode, errormessage) errorcode,

enum
{
#include "ems/errors.h"
LAST_ERROR_CODE
};
#undef CUCF_ERROR

typedef int tEMSErrorCode;
typedef const char* tEMSErrorMessage;

extern const tEMSErrorMessage ErrorMessageArray[];

/************************
 *     Error catcher
 */
#define CUCFSetErrorCatcher(coder, retcode) \
{ \
  retcode = setjmp((coder)->EMS.ReturnPoint); \
  (coder)->EMS.IsAssigned = 1; \
  if (retcode == 0) \
    (coder)->EMS.ErrorCode = ec_SUCCESS; \
  else \
    MMSRelease(coder); \
}

/************************
 *       Error path
 */

#ifndef CODER_REMOVE_PATH
#define EPInit(coder, type) \
 (coder)->EMS.ErrorPath.Fields[0] = (void*)type; \
 (coder)->EMS.ErrorPath.NumOfFields = 1

#define EP_VARIABLE(var) var

#define EPSetField(coder, field) \
{INTERNAL_ERROR_HANDLER_EXP((coder)->EMS.ErrorPath.NumOfFields >= CODER_PATH_DEEP, \
                            (coder), ec_INT_InternalError, \
                            ERR_ARG(__FILE__) ERR_ARG(__LINE__)); \
 (coder)->EMS.ErrorPath.Fields[(coder)->EMS.ErrorPath.NumOfFields] = (void*)(field); \
 (coder)->EMS.ErrorPath.NumOfFields++;}

#define EPDelField(coder) \
(coder)->EMS.ErrorPath.NumOfFields--;

#define EPIncIndex(coder) \
(*(tVMSULong*)((coder)->EMS.ErrorPath.Fields[(coder)->EMS.ErrorPath.NumOfFields - 1]))++;

#if defined(CODER_EO_USER)
char* EPGetPath(tCoder* Coder);
#elif defined(CODER_EO_DEBUG)
char* EPGetPath(tCoder* Coder, unsigned long* Length);
#endif

#else

#define EPInit(coder, type)
#define EP_VARIABLE(var)
#define EPSetField(coder, fieldinfo)
#define EPDelField(coder)
#define EPIncIndex(coder)
#if defined(CODER_EO_USER)
#define EPGetPath(coder) (char*)"undef"
#elif defined(CODER_EO_DEBUG)
#define EPGetPath(coder,length) (char*)"undef"
#endif

#endif /* CODER_REMOVE_PATH */

/************************
 *     Error handler
 */
extern void CUCFErrorHandler(tCoder* Coder, int ErrorCode, ...);
extern void EPErrorHandler(tCoder* Coder, int ErrorCode, ...);

/************************
 *  Error hander macros
 */

#define NO_ARGS
#define ARGS(args) args
#define ERR_ARG(errarg) ,errarg
#define NO_ACTION

#ifdef CODER_EO_USER
#define EP_PARAM(param) ,param
#else
#define EP_PARAM(param)
#endif

#if !defined(CODER_CHECK_NONE) && !defined(CODER_CHECK_NONE_INNER)
#define INTERNAL_ERROR_HANDLER_EXP(exp, coder, errorcode, args) \
  if (exp) CUCFErrorHandler(coder, errorcode args);
#define INTERNAL_ERROR_HANDLER(coder, errorcode, args) \
  CUCFErrorHandler(coder, errorcode args);
#else
#define INTERNAL_ERROR_HANDLER_EXP(exp, coder, errorcode, args)
#define INTERNAL_ERROR_HANDLER(coder, errorcode, args)
#endif

#if !defined(CODER_CHECK_NONE) && !defined(CODER_CHECK_NONE_MEMORY)
#define MEMORY_ERROR_HANDLER_EXP(exp, coder, action, errorcode, args) \
  if (exp) \
    { \
      CUCFErrorHandler(coder, errorcode args); \
      action; \
    }
#define MEMORY_ERROR_HANDLER(coder, action, errorcode, args) \
  { \
    CUCFErrorHandler(coder, errorcode args); \
    action; \
  }
#else
#define MEMORY_ERROR_HANDLER_EXP(exp, coder, action, errorcode, args)
#define MEMORY_ERROR_HANDLER(coder, action, errorcode, args)
#endif

#if !defined(CODER_CHECK_NONE) && !defined(CODER_CHECK_NONE_BUFFER)
#define BASEBUF_ERROR_HANDLER_EXP(exp, coder, action, errorcode, args) \
  if (exp) \
    { \
      CUCFErrorHandler(coder, errorcode args); \
      action; \
    }
#define BASEBUF_ERROR_HANDLER(coder, action, errorcode, args) \
  { \
    CUCFErrorHandler(coder, errorcode args); \
    action; \
  }
#else
#define BASEBUF_ERROR_HANDLER_EXP(exp, coder, action, errorcode, args)
#define BASEBUF_ERROR_HANDLER(coder, action, errorcode, args)
#endif

#if !defined(CODER_CHECK_NONE) && !defined(CODER_CHECK_NONE_VALUE)
#define VALUE_ERROR_HANDLER_EXP(exp, coder, errorcode, args) \
  if (exp) EPErrorHandler(coder, errorcode \
                          EP_PARAM(GetASN1TypeClass((coder)->VMS.Type)) \
                          EP_PARAM(GetASN1TypeName((coder)->VMS.Type)) \
                          EP_PARAM(EPGetPath(coder)) \
                          args);
#define VALUE_ERROR_HANDLER(coder, errorcode, args) \
  EPErrorHandler(coder, errorcode \
                 EP_PARAM(GetASN1TypeClass((coder)->VMS.Type)) \
                 EP_PARAM(GetASN1TypeName((coder)->VMS.Type)) \
                 EP_PARAM(EPGetPath(coder)) \
                 args);
#else
#define VALUE_ERROR_HANDLER_EXP(exp, coder, errorcode, args)
#define VALUE_ERROR_HANDLER(coder, errorcode, args)
#endif

#if !defined(CODER_CHECK_NONE) && !defined(CODER_CHECK_NONE_DECODING)
#define DECODING_ERROR_HANDLER_EXP(exp, coder, errorcode, args) \
  if (exp) EPErrorHandler(coder, errorcode \
                          EP_PARAM(GetASN1TypeClass((coder)->VMS.Type)) \
                          EP_PARAM(GetASN1TypeName((coder)->VMS.Type)) \
                          EP_PARAM(EPGetPath(coder)) \
                          args);
#define DECODING_ERROR_HANDLER(coder, errorcode, args) \
  EPErrorHandler(coder, errorcode \
                 EP_PARAM(GetASN1TypeClass((coder)->VMS.Type)) \
                 EP_PARAM(GetASN1TypeName((coder)->VMS.Type)) \
                 EP_PARAM(EPGetPath(coder)) \
                 args);
#else
#define DECODING_ERROR_HANDLER_EXP(exp, coder, errorcode, args)
#define DECODING_ERROR_HANDLER(coder, errorcode, args)
#endif

#if defined(CODER_VMS_SDT) && !defined(CODER_REMOVE_ASCII)

#if !defined(CODER_CHECK_NONE)
#define ASCII_ERROR_HANDLER_EXP(exp, coder, errorcode, args) \
  if (exp) CUCFErrorHandler(coder, errorcode args);
#define ASCII_ERROR_HANDLER(coder, errorcode, args) \
  CUCFErrorHandler(coder, errorcode args);
#else
#define ASCII_ERROR_HANDLER_EXP(exp, coder, errorcode, args)
#define ASCII_ERROR_HANDLER(coder, errorcode, args)
#endif

#endif /* CODER_VMS_SDT && !CODER_REMOVE_ASCII */

/*******************************
 *  Error output configuration
 */

extern char* CUCFGetErrorMessage(int ErrorCode);

extern void CUCFErrorOutput(FILE *File, int ErrorCode, ...);

#if defined(CODER_EO_USER)

extern void USERErrorOutputFunc(FILE* File, int ErrorCode, va_list ap);

#elif !defined(CODER_EO_DEBUG) && !defined(CODER_EO_NONE)

#ifndef CODER_EO_SDT
#define CODER_EO_SDT
#endif

#include "ems/ems_eo_sdt.h"
extern void xCoderError(char*, char*);

#endif

#endif /* __ems_h */
