/* Macros.h - Usefull macros for the T1 Modem Bank software. */

#ifndef Macros_h
#define Macros_h

#define	ElementCount(pobj)		(sizeof (pobj) / sizeof (pobj)[0])

#define	SetBit(b, v)			((v) !=  (1 << (b)))
#define	ClrBit(b, v)			((v) &= ~(1 << (b)))
#define	GetBit(b, v)			(!!((v) >> (b)))

#define	LoNibble(b)				((BYTE)(((BYTE) (b)) & 0xF))
#define	HiNibble(b)				(LoNibble(((BYTE) (w)) >> 4))
#define	LoByte(w)				((BYTE)(((WORD) (w)) & 0xFF))
#define	HiByte(w)				(LoByte(((WORD) (w)) >> 8))
#define	LoWord(dw)				((WORD)(((DWORD) (dw)) & 0xFFFF))
#define	HiWord(dw)				(LoWord(((DWORD) (dw)) >> 16))

#define	MakeByte(hn, ln)		((		 LoNibble(hn)	<< 4)	|		 LoNibble(ln))
#define	MakeWord(hb, lb)		(((WORD) LoByte(hb)		<< 8)	| (WORD) LoByte(lb))
#define	MakeDWord(hw, lw)		(((DWORD)LoWord(hw)		<< 16)	| (DWORD)LoWord(lw))

#define	MILLISECONDS_PER_SECOND		1000
#define	SECONDS_PER_MINUTE			60
#define	MINUTES_PER_HOUR			60

#define	SecondsToMilliseconds(s)		((DWORD) ((s) * MILLISECONDS_PER_SECOND))
#define	MinutesToMilliseconds(m)		SecondsToMilliseconds((m) * SECONDS_PER_MINUTE)
#define	HoursToMilliseconds(h)			MinutesToMilliseconds((h) * MINUTES_PER_HOUR)

// Debug Reporting

#if defined(_DEBUG)
#define DEBUG_REPORTING
#define DEBUG_MSVC
#elif defined(BETA) || defined(DEBUG_TESTING)
#define DEBUG_REPORTING
#endif

#if defined(DEBUG_MSVC)

#include <crtdbg.h>

#else

/* From crtdbg.h: */

typedef void *_HFILE; /* file handle pointer */

#define _CRT_WARN           0
#define _CRT_ERROR          1
#define _CRT_ASSERT         2

#define _CRTDBG_MODE_FILE      0x1
#define _CRTDBG_MODE_DEBUG     0x2
#define _CRTDBG_MODE_WNDW      0x4
#define _CRTDBG_REPORT_MODE    -1

typedef int (__cdecl * _CRT_REPORT_HOOK)(int, char *, int *);

#if defined(_CrtDbgBreak)
#undef _CrtDbgBreak
#endif
#define	_CrtDbgBreak()	DebugBreak()

#if defined(_CrtDbgReport)
#undef _CrtDbgReport
#endif
int __cdecl _CrtDbgReport(int reportType, const char * filename, int linenumber, const char * moduleName, const char * format, ...);

#if defined(_CrtSetReportMode)
#undef _CrtSetReportMode
#endif
int __cdecl _CrtSetReportMode(int reportType, int reportMode);

#if defined(_CrtSetReportFile)
#undef _CrtSetReportFile
#endif
_HFILE __cdecl _CrtSetReportFile(int reportType, _HFILE reportFile);

#if defined(_CrtSetReportHook)
#undef _CrtSetReportHook
#endif
_CRT_REPORT_HOOK __cdecl _CrtSetReportHook(_CRT_REPORT_HOOK reportHook);

#endif

#if defined(DEBUG_REPORTING)

#define	DebugReportMode(warn, error, assert)				\
	(void)	(	_CrtSetReportMode(_CRT_WARN,	(warn)),	\
				_CrtSetReportMode(_CRT_ERROR,	(error)),	\
				_CrtSetReportMode(_CRT_ASSERT,	(assert))	\
			)

#define	DebugReportFile(warn, error, assert)				\
	(void)	(	_CrtSetReportFile(_CRT_WARN,	(warn)),	\
				_CrtSetReportFile(_CRT_ERROR,	(error)),	\
				_CrtSetReportFile(_CRT_ASSERT,	(assert))	\
			)

#define DebugReportHook(fn)	_CrtSetReportHook(fn)

#define	THIS_FILE			__FILE__

#define	HERE				THIS_FILE, __LINE__, NULL

#define	DebugReport(type)									DebugReport0((type), "")
															
#define	DebugReport0(type, format)										do { if (1 == _CrtDbgReport((type), HERE, (format)))														_CrtDbgBreak(); } while (0)
#define	DebugReport1(type, format, p1)									do { if (1 == _CrtDbgReport((type), HERE, (format), (p1)))													_CrtDbgBreak(); } while (0)
#define	DebugReport2(type, format, p1, p2)								do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2)))											_CrtDbgBreak(); } while (0)
#define	DebugReport3(type, format, p1, p2, p3)							do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3)))										_CrtDbgBreak(); } while (0)
#define	DebugReport4(type, format, p1, p2, p3, p4)						do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4)))								_CrtDbgBreak(); } while (0)
#define	DebugReport5(type, format, p1, p2, p3, p4, p5)					do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4), (p5)))							_CrtDbgBreak(); } while (0)
#define	DebugReport6(type, format, p1, p2, p3, p4, p5, p6)				do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4), (p5), (p6)))					_CrtDbgBreak(); } while (0)
#define	DebugReport7(type, format, p1, p2, p3, p4, p5, p6, p7)			do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7)))				_CrtDbgBreak(); } while (0)
#define	DebugReport8(type, format, p1, p2, p3, p4, p5, p6, p7, p8)		do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8)))		_CrtDbgBreak(); } while (0)
#define	DebugReport9(type, format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	do { if (1 == _CrtDbgReport((type), HERE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9)))	_CrtDbgBreak(); } while (0)

#else

#define DebugReportMode(warn, error, assert)				(void) (NULL)
#define DebugReportFile(warn, error, assert)				(void) (NULL)
#define DebugReportHook(fn)									(void) (NULL)

#define	DebugReport(type)												((void) NULL)
#define	DebugReport0(type, format)										((void) NULL)
#define	DebugReport1(type, format, p1)									((void) NULL)
#define	DebugReport2(type, format, p1, p2)								((void) NULL)
#define	DebugReport3(type, format, p1, p2, p3)							((void) NULL)
#define	DebugReport4(type, format, p1, p2, p3, p4)						((void) NULL)
#define	DebugReport5(type, format, p1, p2, p3, p4, p5)					((void) NULL)
#define	DebugReport6(type, format, p1, p2, p3, p4, p5, p6)				((void) NULL)
#define	DebugReport7(type, format, p1, p2, p3, p4, p5, p6, p7)			((void) NULL)
#define	DebugReport8(type, format, p1, p2, p3, p4, p5, p6, p7, p8)		((void) NULL)
#define	DebugReport9(type, format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	((void) NULL)

#endif

#define _CRT_MESSAGE	_CRT_WARN

#define	DebugMessage()												DebugReport(_CRT_MESSAGE)
#define	DebugMessage0(format)										DebugReport0(_CRT_MESSAGE, (format))
#define	DebugMessage1(format, p1)									DebugReport1(_CRT_MESSAGE, (format), (p1))
#define	DebugMessage2(format, p1, p2)								DebugReport2(_CRT_MESSAGE, (format), (p1), (p2))
#define	DebugMessage3(format, p1, p2, p3)							DebugReport3(_CRT_MESSAGE, (format), (p1), (p2), (p3))
#define	DebugMessage4(format, p1, p2, p3, p4)						DebugReport4(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4))
#define	DebugMessage5(format, p1, p2, p3, p4, p5)					DebugReport5(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4), (p5))
#define	DebugMessage6(format, p1, p2, p3, p4, p5, p6)				DebugReport6(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4), (p5), (p6))
#define	DebugMessage7(format, p1, p2, p3, p4, p5, p6, p7)			DebugReport7(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7))
#define	DebugMessage8(format, p1, p2, p3, p4, p5, p6, p7, p8)		DebugReport8(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8))
#define	DebugMessage9(format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	DebugReport9(_CRT_MESSAGE, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9))
															
#define	DebugWarning()												DebugReport(_CRT_WARN)
#define	DebugWarning0(format)										DebugReport0(_CRT_WARN, (format))
#define	DebugWarning1(format, p1)									DebugReport1(_CRT_WARN, (format), (p1))
#define	DebugWarning2(format, p1, p2)								DebugReport2(_CRT_WARN, (format), (p1), (p2))
#define	DebugWarning3(format, p1, p2, p3)							DebugReport3(_CRT_WARN, (format), (p1), (p2), (p3))
#define	DebugWarning4(format, p1, p2, p3, p4)						DebugReport4(_CRT_WARN, (format), (p1), (p2), (p3), (p4))
#define	DebugWarning5(format, p1, p2, p3, p4, p5)					DebugReport5(_CRT_WARN, (format), (p1), (p2), (p3), (p4), (p5))
#define	DebugWarning6(format, p1, p2, p3, p4, p5, p6)				DebugReport6(_CRT_WARN, (format), (p1), (p2), (p3), (p4), (p5), (p6))
#define	DebugWarning7(format, p1, p2, p3, p4, p5, p6, p7)			DebugReport7(_CRT_WARN, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7))
#define	DebugWarning8(format, p1, p2, p3, p4, p5, p6, p7, p8)		DebugReport8(_CRT_WARN, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8))
#define	DebugWarning9(format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	DebugReport9(_CRT_WARN, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9))
															
#define	DebugError()												DebugReport(_CRT_ERROR)
#define	DebugError0(format)											DebugReport0(_CRT_ERROR, (format))
#define	DebugError1(format, p1)										DebugReport1(_CRT_ERROR, (format), (p1))
#define	DebugError2(format, p1, p2)									DebugReport2(_CRT_ERROR, (format), (p1), (p2))
#define	DebugError3(format, p1, p2, p3)								DebugReport3(_CRT_ERROR, (format), (p1), (p2), (p3))
#define	DebugError4(format, p1, p2, p3, p4)							DebugReport4(_CRT_ERROR, (format), (p1), (p2), (p3), (p4))
#define	DebugError5(format, p1, p2, p3, p4, p5)						DebugReport5(_CRT_ERROR, (format), (p1), (p2), (p3), (p4), (p5))
#define	DebugError6(format, p1, p2, p3, p4, p5, p6)					DebugReport6(_CRT_ERROR, (format), (p1), (p2), (p3), (p4), (p5), (p6))
#define	DebugError7(format, p1, p2, p3, p4, p5, p6, p7)				DebugReport7(_CRT_ERROR, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7))
#define	DebugError8(format, p1, p2, p3, p4, p5, p6, p7, p8)			DebugReport8(_CRT_ERROR, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8))
#define	DebugError9(format, p1, p2, p3, p4, p5, p6, p7, p8, p9)		DebugReport9(_CRT_ERROR, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9))

#define	DebugFailure()												DebugReport(_CRT_ASSERT)
#define	DebugFailure0(format)										DebugReport0(_CRT_ASSERT, (format))
#define	DebugFailure1(format, p1)									DebugReport1(_CRT_ASSERT, (format), (p1))
#define	DebugFailure2(format, p1, p2)								DebugReport2(_CRT_ASSERT, (format), (p1), (p2))
#define	DebugFailure3(format, p1, p2, p3)							DebugReport3(_CRT_ASSERT, (format), (p1), (p2), (p3))
#define	DebugFailure4(format, p1, p2, p3, p4)						DebugReport4(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4))
#define	DebugFailure5(format, p1, p2, p3, p4, p5)					DebugReport5(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4), (p5))
#define	DebugFailure6(format, p1, p2, p3, p4, p5, p6)				DebugReport6(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4), (p5), (p6))
#define	DebugFailure7(format, p1, p2, p3, p4, p5, p6, p7)			DebugReport7(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7))
#define	DebugFailure8(format, p1, p2, p3, p4, p5, p6, p7, p8)		DebugReport8(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8))
#define	DebugFailure9(format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	DebugReport9(_CRT_ASSERT, (format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9))

#define	DebugAssert(cond)												if (!(cond)) DebugFailure()
#define	DebugAssert0(cond, format)										if (!(cond)) DebugFailure0((format))
#define	DebugAssert1(cond, format, p1)									if (!(cond)) DebugFailure1((format), (p1))
#define	DebugAssert2(cond, format, p1, p2)								if (!(cond)) DebugFailure2((format), (p1), (p2))
#define	DebugAssert3(cond, format, p1, p2, p3)							if (!(cond)) DebugFailure3((format), (p1), (p2), (p3))
#define	DebugAssert4(cond, format, p1, p2, p3, p4)						if (!(cond)) DebugFailure4((format), (p1), (p2), (p3), (p4))
#define	DebugAssert5(cond, format, p1, p2, p3, p4, p5)					if (!(cond)) DebugFailure5((format), (p1), (p2), (p3), (p4), (p5))
#define	DebugAssert6(cond, format, p1, p2, p3, p4, p5, p6)				if (!(cond)) DebugFailure6((format), (p1), (p2), (p3), (p4), (p5), (p6))
#define	DebugAssert7(cond, format, p1, p2, p3, p4, p5, p6, p7)			if (!(cond)) DebugFailure7((format), (p1), (p2), (p3), (p4), (p5), (p6), (p7))
#define	DebugAssert8(cond, format, p1, p2, p3, p4, p5, p6, p7, p8)		if (!(cond)) DebugFailure8((format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8))
#define	DebugAssert9(cond, format, p1, p2, p3, p4, p5, p6, p7, p8, p9)	if (!(cond)) DebugFailure9((format), (p1), (p2), (p3), (p4), (p5), (p6), (p7), (p8), (p9))

// Timer functions

#if defined(DEBUG_REPORTING)

// takes nothing				returns start time
#define	TimerStart()			GetTickCount()
// takes start time				returns elapsed time
#define	TimerEnd(s)				(GetTickCount() - (s))
// takes text and elapsed time	returns nothing
#define	TimerDisplay(t, e)		DebugMessage2("%s took %.03f seconds\n", LPCTSTR(t), (double)(e) / MILLISECONDS_PER_SECOND)

#else

#define	TimerStart()			(0)
#define	TimerEnd(s)				(0)
#define	TimerDisplay(t, e)		(void)(NULL)

#endif

#endif // #ifndef Macros_h
