304 lines
8.6 KiB
C++
304 lines
8.6 KiB
C++
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// cppdbg.hpp
|
||
|
//
|
||
|
// C++-only debugging support.
|
||
|
//
|
||
|
// Copyright (C) Microsoft Corporation, 1997.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#ifndef _CPPDBG_HPP_
|
||
|
#define _CPPDBG_HPP_
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
typedef unsigned int UINT;
|
||
|
|
||
|
//
|
||
|
// Mask bits common to all modules.
|
||
|
//
|
||
|
|
||
|
#define DBG_MASK_NO_PREFIX 0x80000000
|
||
|
#define DBG_MASK_FORCE 0x40000000
|
||
|
|
||
|
// Mask bits checked against output mask.
|
||
|
#define DBG_MASK_CHECK (~(DBG_MASK_NO_PREFIX | \
|
||
|
DBG_MASK_FORCE))
|
||
|
|
||
|
// Forced continuation mask.
|
||
|
#define DBG_MASK_FORCE_CONT (DBG_MASK_NO_PREFIX | DBG_MASK_FORCE)
|
||
|
|
||
|
//
|
||
|
// Failure control bits for assert and HRESULT failures.
|
||
|
//
|
||
|
|
||
|
#define DBG_FAILURE_BREAK 0x00000001
|
||
|
#define DBG_FAILURE_OUTPUT 0x00000002
|
||
|
#define DBG_FAILURE_PROMPT 0x00000004
|
||
|
#define DBG_FAILURE_FILENAME_ONLY 0x00000008
|
||
|
|
||
|
//
|
||
|
// Overall output control bits.
|
||
|
//
|
||
|
|
||
|
#define DBG_OUTPUT_SUPPRESS 0x00000001
|
||
|
#define DBG_OUTPUT_ALL_MATCH 0x00000002
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// DebugModule
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
struct DebugModuleFlags
|
||
|
{
|
||
|
UINT uFlag;
|
||
|
char *pName;
|
||
|
};
|
||
|
|
||
|
// Declares a DebugModuleFlags entry.
|
||
|
#define DBG_DECLARE_MODFLAG(Group, Name) \
|
||
|
Group ## _ ## Name, #Name
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
DBG_ASSERT_FLAGS,
|
||
|
DBG_HR_FLAGS,
|
||
|
DBG_OUTPUT_FLAGS,
|
||
|
DBG_OUTPUT_MASK,
|
||
|
DBG_USER_FLAGS,
|
||
|
DBG_FLAGS_COUNT
|
||
|
};
|
||
|
|
||
|
class DebugModule
|
||
|
{
|
||
|
public:
|
||
|
DebugModule(char *pModule, char *pPrefix,
|
||
|
DebugModuleFlags *pOutputMasks, UINT uOutputMask,
|
||
|
DebugModuleFlags *pUserFlags, UINT uUserFlags);
|
||
|
|
||
|
void Out(char *pFmt, ...);
|
||
|
|
||
|
void OutMask(UINT uMask, char *pFmt, ...)
|
||
|
{
|
||
|
if ((uMask & DBG_MASK_FORCE) ||
|
||
|
((m_uFlags[DBG_OUTPUT_FLAGS] & DBG_OUTPUT_ALL_MATCH) &&
|
||
|
(uMask & m_uFlags[DBG_OUTPUT_MASK] & DBG_MASK_CHECK) == uMask) ||
|
||
|
((m_uFlags[DBG_OUTPUT_FLAGS] & DBG_OUTPUT_ALL_MATCH) == 0 &&
|
||
|
(uMask & m_uFlags[DBG_OUTPUT_MASK] & DBG_MASK_CHECK) != 0))
|
||
|
{
|
||
|
va_list Args;
|
||
|
|
||
|
va_start(Args, pFmt);
|
||
|
OutVa(uMask, pFmt, Args);
|
||
|
va_end(Args);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void AssertFailed(char *pExp);
|
||
|
void AssertFailedMsg(char *pFmt, ...);
|
||
|
|
||
|
void HrStmtFailed(HRESULT hr);
|
||
|
HRESULT HrExpFailed(HRESULT hr);
|
||
|
|
||
|
void SetFileLine(char *pFile, int iLine)
|
||
|
{
|
||
|
m_pFile = pFile;
|
||
|
m_iLine = iLine;
|
||
|
}
|
||
|
|
||
|
void Prompt(char *pFmt, ...);
|
||
|
|
||
|
UINT GetFlags(int iIdx)
|
||
|
{
|
||
|
return m_uFlags[iIdx];
|
||
|
}
|
||
|
void SetFlags(int iIdx, UINT uValue)
|
||
|
{
|
||
|
m_uFlags[iIdx] = uValue;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void OutVa(UINT uMask, char *pFmt, va_list Args);
|
||
|
void AssertFailedVa(char *pFmt, va_list Args, BOOL bNewLine);
|
||
|
|
||
|
HKEY OpenDebugKey(void);
|
||
|
UINT GetRegUint(HKEY hKey, char *pValue, UINT uDefault);
|
||
|
BOOL SetRegUint(HKEY hKey, char *pValue, UINT uValue);
|
||
|
void ReadReg(void);
|
||
|
void WriteReg(void);
|
||
|
|
||
|
UINT ParseUint(char *pString, DebugModuleFlags *pFlags);
|
||
|
void OutUint(char *pName, DebugModuleFlags *pFlags, UINT uValue);
|
||
|
|
||
|
void AdvanceCols(int iCols);
|
||
|
|
||
|
void ShowFlags(char *pName, DebugModuleFlags *pFlags);
|
||
|
|
||
|
char *PathFile(char *pPath);
|
||
|
BOOL OutPathFile(char *pPrefix, UINT uFailureFlags);
|
||
|
|
||
|
void HrFailure(HRESULT hr, char *pPrefix);
|
||
|
char *HrString(HRESULT hr);
|
||
|
|
||
|
// Module information given.
|
||
|
char *m_pModule;
|
||
|
char *m_pPrefix;
|
||
|
|
||
|
// Flag descriptions and values.
|
||
|
DebugModuleFlags *m_pModFlags[DBG_FLAGS_COUNT];
|
||
|
UINT m_uFlags[DBG_FLAGS_COUNT];
|
||
|
|
||
|
// Temporary file and line number storage.
|
||
|
char *m_pFile;
|
||
|
int m_iLine;
|
||
|
|
||
|
// Output column during multiline display.
|
||
|
int m_iModuleStartCol;
|
||
|
int m_iCol;
|
||
|
int m_iStartCol;
|
||
|
};
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Support macros.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
#define DBG_MODULE(Prefix) Prefix ## _Debug
|
||
|
|
||
|
// Put this in one source file.
|
||
|
#define DBG_DECLARE_ONCE(Module, Prefix, pOutputMasks, uOutputMask, \
|
||
|
pUserFlags, uUserFlags) \
|
||
|
DebugModule DBG_MODULE(Prefix)(#Module, #Prefix, \
|
||
|
pOutputMasks, uOutputMask, \
|
||
|
pUserFlags, uUserFlags)
|
||
|
|
||
|
// Put this in your derived debugging header.
|
||
|
#define DBG_DECLARE_HEADER(Prefix) \
|
||
|
extern DebugModule DBG_MODULE(Prefix)
|
||
|
|
||
|
// Put this in every file.
|
||
|
#define DBG_DECLARE_FILE() \
|
||
|
static char *g_pStaticDebugFile = __FILE__
|
||
|
|
||
|
#define DBG_DECLARE_DPF(Prefix, Args) \
|
||
|
DBG_MODULE(Prefix).Out Args
|
||
|
#define DBG_DECLARE_DPFM(Prefix, Args) \
|
||
|
DBG_MODULE(Prefix).OutMask Args
|
||
|
|
||
|
#define DBG_DECLARE_ASSERT(Prefix, Exp) \
|
||
|
if (!(Exp)) \
|
||
|
{ DBG_MODULE(Prefix).SetFileLine(g_pStaticDebugFile, __LINE__); \
|
||
|
DBG_MODULE(Prefix).AssertFailed(#Exp); } \
|
||
|
else 0
|
||
|
#define DBG_DECLARE_ASSERTMSG(Prefix, Exp, Args) \
|
||
|
if (!(Exp)) \
|
||
|
{ DBG_MODULE(Prefix).SetFileLine(g_pStaticDebugFile, __LINE__); \
|
||
|
DBG_MODULE(Prefix).AssertFailedMsg Args ; } \
|
||
|
else 0
|
||
|
#define DBG_DECLARE_VERIFY(Prefix, Exp) \
|
||
|
DBG_DECLARE_ASSERT(Prefix, Exp)
|
||
|
#define DBG_DECLARE_VERIFYMSG(Prefix, Exp, Args)\
|
||
|
DBG_DECLARE_ASSERTMSG(Prefix, Exp, Args)
|
||
|
|
||
|
#define DBG_DECLARE_PROMPT(Prefix, Args) \
|
||
|
DBG_MODULE(Prefix).Prompt Args
|
||
|
|
||
|
#define DBG_DECLARE_GETFLAGS(Prefix, Idx) \
|
||
|
DBG_MODULE(Prefix).GetFlags(Idx)
|
||
|
#define DBG_DECLARE_SETFLAGS(Prefix, Idx, Value) \
|
||
|
DBG_MODULE(Prefix).SetFlags(Idx, Value)
|
||
|
|
||
|
//
|
||
|
// These macros assume a variable 'hr' exists.
|
||
|
//
|
||
|
|
||
|
// HRESULT test in expression form.
|
||
|
#define DBG_DECLARE_HRCHK(Prefix, Exp) \
|
||
|
((hr = (Exp)) != S_OK ? \
|
||
|
(DBG_MODULE(Prefix).SetFileLine(g_pStaticDebugFile, __LINE__), \
|
||
|
DBG_MODULE(Prefix).HrExpFailed(hr)) : hr)
|
||
|
|
||
|
// HRESULT test in if/then form.
|
||
|
#define DBGI_DECLARE_HRIF(Prefix, Exp, DoFail) \
|
||
|
if ((hr = (Exp)) != S_OK) \
|
||
|
{ DBG_MODULE(Prefix).SetFileLine(g_pStaticDebugFile, __LINE__); \
|
||
|
DBG_MODULE(Prefix).HrStmtFailed(hr); \
|
||
|
DoFail; } \
|
||
|
else hr
|
||
|
|
||
|
#define DBG_DECLARE_HRGO(Prefix, Exp, Label) \
|
||
|
DBGI_DECLARE_HRIF(Prefix, Exp, goto Label)
|
||
|
#define DBG_DECLARE_HRERR(Prefix, Exp) \
|
||
|
DBG_DECLARE_HRGO(Prefix, Exp, HR_Err)
|
||
|
#define DBG_DECLARE_HRRET(Prefix, Exp) \
|
||
|
DBGI_DECLARE_HRIF(Prefix, Exp, return hr)
|
||
|
|
||
|
#else // #if DBG
|
||
|
|
||
|
//
|
||
|
// Empty macros for free builds.
|
||
|
//
|
||
|
|
||
|
#define DBG_MODULE(Prefix) 0
|
||
|
#define DBG_DECLARE_ONCE(Module, Prefix, pOutputMasks, uOutputMask, \
|
||
|
pUserFlags, uUserFlags)
|
||
|
#define DBG_DECLARE_HEADER(Prefix)
|
||
|
#define DBG_DECLARE_FILE()
|
||
|
|
||
|
#define DBG_DECLARE_DPF(Prefix, Args)
|
||
|
#define DBG_DECLARE_DPFM(Prefix, Args)
|
||
|
#define DBG_DECLARE_ASSERT(Prefix, Exp)
|
||
|
#define DBG_DECLARE_ASSERTMSG(Prefix, Exp, Args)
|
||
|
#define DBG_DECLARE_PROMPT(Prefix, Args)
|
||
|
#define DBG_DECLARE_GETFLAGS(Prefix, Idx) 0
|
||
|
#define DBG_DECLARE_SETFLAGS(Prefix, Idx, Value)
|
||
|
|
||
|
//
|
||
|
// Macros which evaluate to code on free builds.
|
||
|
//
|
||
|
|
||
|
#define DBG_DECLARE_VERIFY(Prefix, Exp) (Exp)
|
||
|
#define DBG_DECLARE_VERIFYMSG(Prefix, Exp, Args) (Exp)
|
||
|
|
||
|
#define DBG_DECLARE_HRCHK(Prefix, Exp) \
|
||
|
(hr = (Exp))
|
||
|
#define DBGI_DECLARE_HRIF(Prefix, Exp, DoFail) \
|
||
|
if ((hr = (Exp)) != S_OK) DoFail; else hr
|
||
|
#define DBG_DECLARE_HRGO(Prefix, Exp, Label) \
|
||
|
DBGI_DECLARE_HRIF(Prefix, Exp, goto Label)
|
||
|
#define DBG_DECLARE_HRERR(Prefix, Exp) \
|
||
|
DBG_DECLARE_HRGO(Prefix, Exp, HR_Err)
|
||
|
#define DBG_DECLARE_HRRET(Prefix, Exp) \
|
||
|
DBGI_DECLARE_HRIF(Prefix, Exp, return hr)
|
||
|
|
||
|
#endif // #if DBG
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Global debug module.
|
||
|
//
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
DBG_DECLARE_HEADER(G);
|
||
|
|
||
|
#define GDPF(Args) DBG_DECLARE_DPF(G, Args)
|
||
|
#define GDPFM(Args) DBG_DECLARE_DPFM(G, Args)
|
||
|
#define GASSERT(Exp) DBG_DECLARE_ASSERT(G, Exp)
|
||
|
#define GASSERTMSG(Exp, Args) DBG_DECLARE_ASSERTMSG(G, Exp, Args)
|
||
|
#define GVERIFY(Exp) DBG_DECLARE_VERIFY(G, Exp)
|
||
|
#define GVERIFYMSG(Exp) DBG_DECLARE_VERIFYMSG(G, Exp, Args)
|
||
|
#define GPROMPT(Args) DBG_DECLARE_PROMPT(G, Args)
|
||
|
#define GGETFLAGS(Idx) DBG_DECLARE_GETFLAGS(G, Idx)
|
||
|
#define GSETFLAGS(Idx, Value) DBG_DECLARE_SETFLAGS(G, Idx, Value)
|
||
|
#define GHRCHK(Exp) DBG_DECLARE_HRCHK(G, Exp)
|
||
|
#define GHRGO(Exp, Label) DBG_DECLARE_HRGO(G, Exp, Label)
|
||
|
#define GHRERR(Exp) DBG_DECLARE_HRERR(G, Exp)
|
||
|
#define GHRRET(Exp) DBG_DECLARE_HRRET(G, Exp)
|
||
|
|
||
|
#endif // #ifndef _CPPDBG_HPP_
|