//
//  Trace log and assertions.
//

#ifndef _TRACE_H_
#define _TRACE_H_

//
//  for trace/logging
//

#ifdef __cplusplus
extern "C" {
#endif

void LogSetFilter(const char*);
void LogInitialize(LPCSTR);
void LogCleanup(void);
void LogAttach(HFILE,LPCSTR);
void LogBuffer(const char*,const char*,unsigned);

void __cdecl Log_printf(const char*,...);
void LogString(const char*,const char*);

#ifdef __cplusplus
};
#endif

#ifdef __cplusplus

class CvsTrace {
public:
    CvsTrace(const char*);
    ~CvsTrace();
private:
    const char* m_sOuter;
};

#endif

//
//  Logging calls always compiled into release.
//

#define LOG_API_FN(FN) \
CvsTrace _fn_(#FN)

#define LOG_API_S(S) \
if (S) { LogString("A " #S,(const char*)(S)); }

#define LOG_API_X(X) \
/*if (X)*/ { Log_printf("A " #X " : 0x%lx",(long)(X)); }

#define LOG_API_N(N) \
/*if (N)*/ { Log_printf("A " #N " : %lu",(long)(N)); }

//
//  Trace calls only compiled into DEBUG version.
//

#ifdef NDEBUG
#define qTRACE_FN(FN)
#define qTRACE(L)
#define LOG_BUFFER(A,B,N)
#else
#define qTRACE_FN(FN)       CvsTrace _fn_(#FN)
#define qTRACE(L)           Log_printf L
#define LOG_BUFFER(A,B,N)   LogBuffer(A,B,N)
#endif

#define qTRACE_S(S) \
if (S) { qTRACE(("a " #S " : \"%s\"",(S))); }

#define qTRACE_X(X) \
/*if (X)*/ { qTRACE(("a " #X " : 0x%lx",(long)(X))); }

#define qTRACE_N(N) \
/*if (N)*/ { qTRACE(("a " #N " : %lu",(long)(N))); }

//
//  for debugging
//

#undef ASSERT
#undef VERIFY

#ifdef NDEBUG
#define ASSERT(X)
#define VERIFY(X)   (X)
#else
#define ASSERT(X)   if (!(X)) { __Assert(__FILE__,__LINE__,#X); DebugBreak(); } else 0
#define VERIFY(X)   if (!(X)) { __Assert(__FILE__,__LINE__,#X); DebugBreak(); } else 0

#ifdef _M_IX86
#define DebugBreak()    __asm { int 3 }
#endif

static void __Assert(const char* sFile,unsigned iLine,const char* sExpression)
{
    Log_printf("*%s:%u ASSERT FAILED: %s",sFile,iLine,sExpression);
}
#endif

#endif
