/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::   Module      :   Native Error Code Construction
::   Copyright   :   (C)2002-20099 Woodward
::   Platform(s) :   Any   
::   Limitations :   None
::
::------------------------------------------------------------------------------------------------------------
::
::   Defines the Signed Error format.
::   All errors are defined to fit into the signed integer format for the chosen platform. The error code
::     is constructed with a number of fields. The size of the fields and their members is dependant upon what
::     the platform's native integer size is and how the information is to be employed
::
::   Always use the SUCCESS and FAILURE macros to test on an error
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

#ifndef __NATIVEERROR_H
#define __NATIVEERROR_H

/*----- INCLUDES ------------------------------------------------------------------------------------------*/
#include <typedefn.h>

/*----- DEFINES -------------------------------------------------------------------------------------------*/
#pragma pack(1)

#ifdef PLATFORM_WORD_SIZE
    #if (PLATFORM_WORD_SIZE == 4)
    #else
        /* Don't Have a WORD SIZE DEFINITION for our Errors */
        #error Defined WORD_SIZE is not compatible with the defined Signed Error system

    #endif /* PLATFORM_WORD_SIZE == 4 */
#else
    #error PLATFORM_WORD_SIZE is undefined...
#endif /* #ifdef PLATFORM_WORD_SIZE */


/***********************************************************************************************************/
/* Code Definition                                                                                         */
/***********************************************************************************************************/
/* 4 Byte Native Error code                                                                                */
/*--------------------------                                                                               */
/* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0         */
/* Error      |  Field1   |  Field2               |  Error Code                                            */

/* Field allocation allows the fields to be identified easily when viewed as HEX numbers in a debugger     */
typedef struct
{
    uint4 m_ErrorStatus : 4;
    uint4 m_SubSystem   : 4;
    uint4 m_Module      : 8;
    uint4 m_ErrorCode   : 16;
} S_NativeError;

typedef union
{
    S_NativeError m_Members;
    sint4         m_Parent;
} U_NativeError;

#define FIELD1_ALLOCATED_BITS 4
#define FIELD2_ALLOCATED_BITS 8
#define CODE_ALLOCATED_BITS   16

#define FIELD2_MULTIPLIER     (1 << CODE_ALLOCATED_BITS)
#define FIELD1_MULTIPLIER     (1 << (CODE_ALLOCATED_BITS + FIELD2_ALLOCATED_BITS))

/* Create the native error type using the target machine's word size */
typedef sint4 NativeError_S;

/* Macros to extract the fields                                                                            */
#define ERROR_CODE_MASK  ((1<<CODE_ALLOCATED_BITS) -1 )
#define ERROR_MODULE_MASK  ((1 << (FIELD2_ALLOCATED_BITS+CODE_ALLOCATED_BITS))-1)
#define ERROR_SUBSYSTEM_MASK  ((1 << (FIELD1_ALLOCATED_BITS+FIELD2_ALLOCATED_BITS+CODE_ALLOCATED_BITS))-1)

#define GetErrorCode(a) (a & ERROR_CODE_MASK)
#define GetErrorModule(a) ((a & ERROR_MODULE_MASK)>> CODE_ALLOCATED_BITS)
#define GetErrorSubSystem(a) ((a & ERROR_SUBSYSTEM_MASK)>> (CODE_ALLOCATED_BITS+FIELD1_ALLOCATED_BITS))

/***********************************************************************************************************/
/* Field Validation defines                                                                                */
/***********************************************************************************************************/
#define VALID_FIELD1(a)      (a < (1<< FIELD1_ALLOCATED_BITS)) 
#define VALID_FIELD2(a)      (a < (1<< FIELD2_ALLOCATED_BITS))
#define VALID_CODE(a)        (a < (1<< CODE_ALLOCATED_BITS))

/***********************************************************************************************************/
/* Code Construction                                                                                       */
/***********************************************************************************************************/
/* Extern this value to allow a truncation warning to result should the fields be illegally sized          */
/* NativeErrorSupport.c must exist within the framework to avoid an unresolved link error, even though it  */
/* is not expected that this variable is ever written to                                                   */
extern uint1 ErrorFieldsOutOfRange;

#define CREATE_NATIVE_CODE_VALUE(Type,Field1,Field2,Code)               \
    ((VALID_FIELD1(Field1) && VALID_FIELD2(Field2) && VALID_CODE(Code)) \
    /* Generate the ErrorCode          */         ? (Type + (Field1*FIELD1_MULTIPLIER)+(Field2*FIELD2_MULTIPLIER)+Code) \
    /* generate a compiler warning    */          : (ErrorFieldsOutOfRange = 256)) 

/***********************************************************************************************************/
/* Supported Type Defines                                                                                  */
/***********************************************************************************************************/
#define IS_ERROR_TYPE        0x80000000             /* Must set the MSBit of the native integer type       */
#define IS_SUCCESS_TYPE      0                      /* Must not set the MSBit of the native integer type   */
#define IS_WARNING_TYPE      0x40000000             /* Must not set the MSBit of the native integer type   */
#define CREATE_ERROR_DEFINE_VALUE(Field1,Field2,Code)   CREATE_NATIVE_CODE_VALUE(IS_ERROR_TYPE,Field1,Field2,Code)
#define CREATE_SUCCESS_DEFINE_VALUE(Field1,Field2,Code) CREATE_NATIVE_CODE_VALUE(IS_SUCCESS_TYPE,Field1,Field2,Code)
#define CREATE_WARNING_DEFINE_VALUE(Field1,Field2,Code) CREATE_NATIVE_CODE_VALUE(IS_WARNING_TYPE,Field1,Field2,Code)

/***********************************************************************************************************/
/* FIELD1 is reserved for use internally by a module so its definition may vary. For modules without a use */
/* UNUSED_FIELD define can be used                                                                         */
/***********************************************************************************************************/
#define UNUSED_FIELD (0)

/***********************************************************************************************************/
/* Define the Modules that we want to identify within the codes                                            */
/* This will use FIELD2                                                                                    */
/***********************************************************************************************************/
typedef enum
{
    UNDEFINED_MODULE  = 0,
    FRAMEWORK_GLUE_MODULE,
    OS_SUBPROJECT_MODULE,
    BEC_LIB_MODULE,
    MOTOTRON_PROTOCOL,
    FRAMEWORK_BOOTSTRAP,
    TPUUCODE_MODULE,
    SMARTCRAFT_PROTOCOL,
    APPLICATON_MODULE,
    MOTOTRON_SPECIFIC,
    SMARTTALK_PROTOCOL,
    SOFTWARE_BOOTSTRAP,
    DIALOG_FILE_UTILITIES,

    NUM_ERROR_MODULES
} E_ErrorModule;

/* Name: FrameworkGlueErrors CType:S_SetDisplayInfo ClassID:ENUMVAR StorageID:RAM Access:RO4+RO3+NA2+NA1 
   TypeID:UINT2 Gain:1 Min:0 Max:65535 Format:3.0 UpdateID:BACKGND Struct:FWModulesSetDisplayInfo.DisplayVar 
   EnumDec:E_NativeFWError Group:"System | Status | Framework" Help:"This indicates the currently Active "
   "Errors within the Framework Glue module." VardecSig:6C */

/* Name: OSSubProjectErrors CType:S_SetDisplayInfo ClassID:ENUMVAR StorageID:RAM Access:RO4+RO3+NA2+NA1 
   TypeID:UINT2 Gain:1 Min:0 Max:65535 Format:3.0 UpdateID:BACKGND 
   Struct:OSSubProjectSetDisplayInfo.DisplayVar EnumDec:E_NativeError Group:"System | Status" Help:"This "
   "indicates the currently Active Errors within the Os Sub-System module." VardecSig:6C */


/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  :: Define the General Purpose Codes - ERRORS
  :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/* ERROR_FAIL:
   The general failure error code for an operation that returns a Native signed error code                 */
#define ERROR_FAIL                              CREATE_ERROR_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,0)

/* ERROR_FIND_ITEM:
   A requested search for an item within a group/list failed because the item was not in the list */
#define ERROR_FIND_ITEM                         CREATE_ERROR_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,1)

/* ERROR_Q_EMPTY
   An attempt was made to access the data of a Q that was empty */
#define ERROR_Q_EMPTY                           CREATE_ERROR_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,2)

/* ERROR_ARCHIVE_NOT_REGISTERED
   An attempt was made to access an archive function prior to having registered that archive for use */
#define ERROR_ARCHIVE_NOT_REGISTERED            CREATE_ERROR_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,3)
/* ERROR_ARCHIVE_REGISTERED
   An attempt was made to register the same archive a second or more time */
#define ERROR_ARCHIVE_REGISTERED                CREATE_ERROR_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,4)

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
  :: Define the General Purpose Codes - SUCCESS INFORMATIONALS
  :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
/* SUCCESS_OK:                                                                                             */
/* The general success code for an operation that returns a Native signed error code                       */
#define SUCCESS_OK                              CREATE_SUCCESS_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,0)

/* SUCCESS_Q_EMPTY
   Success indicating that the Q is empty. Whether the Q was empty or is now empty depends upon the context
   of the call */
#define SUCCESS_Q_EMPTY                         CREATE_SUCCESS_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,1)

/* SUCCESS_Q_FULL
   Success indicating that the Q is full. Whether the Q was full or is now full depends upon the context
   of the call */
#define SUCCESS_Q_FULL                          CREATE_SUCCESS_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,2)

/* SUCCESS_Q_HALF_FULL
   Success indicating that a Q was now half full. Whether the Q was full or is now full depends upon the context
   of the call */
#define SUCCESS_Q_HALF_FULL                     CREATE_SUCCESS_DEFINE_VALUE(UNUSED_FIELD,UNDEFINED_MODULE,3)

#pragma pack()
/*----- TYPEDEFS ------------------------------------------------------------------------------------------*/


/*----- FUNCTION PROTOTYPES -------------------------------------------------------------------------------*/

#define SUCCESS(a) ((a) >= 0)

#define FAILED(a) ((a) < 0)

#define WARNING(a) (((uint4)a) > IS_WARNING_TYPE)

#define FAILED_OR_WARNING(a) ((((uint4)a) > IS_WARNING_TYPE) || ((a) < 0))

/* In order to use the LogNativeError, you need to call StartNativeErrorLoggingService to start that service
   first within the framework. */
NativeError_S LogNativeError(NativeError_S in_NativeError);

#endif /* __NATIVEERROR_H */

/*----- END OF FILE ---------------------------------------------------------------------------------------*/
