You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
9.6 KiB
383 lines
9.6 KiB
#include "precomp.h"
|
|
#include "logitem.h"
|
|
|
|
// utility APIs declarations
|
|
// these two are identical to _strdate and _strtime respectively
|
|
LPCTSTR StrGetDate(LPTSTR pszDate);
|
|
LPCTSTR StrGetTime(LPTSTR pszTime);
|
|
|
|
// string constants
|
|
const TCHAR c_szCRLF[] = TEXT("\r\n");
|
|
const TCHAR c_szSpace[] = TEXT(" ");
|
|
const TCHAR c_szCommaSpace[] = TEXT(", ");
|
|
const TCHAR c_szColonColon[] = TEXT("::");
|
|
const TCHAR c_szColonSpace[] = TEXT(": ");
|
|
const TCHAR c_szLine[] = TEXT("line %i");
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLogItem
|
|
|
|
TCHAR CLogItem::m_szModule[MAX_PATH];
|
|
BYTE CLogItem::m_bStep = 4;
|
|
|
|
CLogItem::CLogItem(DWORD dwFlags /*= LIF_DEFAULT*/, LPBOOL pfLogLevels /*= NULL*/, UINT cLogLevels /*= 0*/)
|
|
{
|
|
if (m_szModule[0] == TEXT('\0')) {
|
|
GetModuleFileName(GetModuleHandle(g_szModule), m_szModule, countof(m_szModule));
|
|
CharLower(m_szModule);
|
|
}
|
|
|
|
m_nAbsOffset = 0;
|
|
m_iRelOffset = 0;
|
|
m_nLine = 0;
|
|
|
|
m_rgfLogLevels = NULL;
|
|
m_cLogLevels = cLogLevels;
|
|
if (pfLogLevels != NULL) {
|
|
ASSERT(cLogLevels > 0);
|
|
|
|
m_rgfLogLevels = new BOOL[m_cLogLevels];
|
|
memcpy(m_rgfLogLevels, pfLogLevels, m_cLogLevels * sizeof(BOOL));
|
|
}
|
|
else
|
|
ASSERT(cLogLevels == 0);
|
|
|
|
m_nLevel = 0;
|
|
|
|
SetFlags(dwFlags);
|
|
}
|
|
|
|
CLogItem::~CLogItem()
|
|
{
|
|
delete[] m_rgfLogLevels;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLogItem operations
|
|
|
|
LPCTSTR WINAPIV CLogItem::Log(int iLine, LPCTSTR pszFormat ...)
|
|
{
|
|
TCHAR szFormat[3 * MAX_PATH],
|
|
szBuffer[MAX_PATH];
|
|
LPCTSTR pszAux;
|
|
UINT nLen, nAuxLen,
|
|
cchCRLF;
|
|
BOOL fPreviousToken;
|
|
|
|
szFormat[0] = TEXT('\0');
|
|
nLen = 0;
|
|
|
|
if (hasFlag(LIF_NONE))
|
|
return NULL;
|
|
|
|
if (m_rgfLogLevels != NULL && m_nLevel < m_cLogLevels) {
|
|
ASSERT((int)m_nLevel >= 0);
|
|
|
|
if (!m_rgfLogLevels[m_nLevel])
|
|
return NULL;
|
|
}
|
|
|
|
// prepend any CRLF at the beginning
|
|
cchCRLF = StrSpn(pszFormat, c_szCRLF);
|
|
if (cchCRLF > 0) {
|
|
// special case
|
|
if (cchCRLF >= (UINT)StrLen(pszFormat)) {
|
|
StrCpy(m_szMessage, pszFormat);
|
|
|
|
if (hasFlag(LIF_DUPLICATEINODS))
|
|
OutputDebugString(m_szMessage);
|
|
|
|
return m_szMessage;
|
|
}
|
|
|
|
StrCpyN(&szFormat[nLen], pszFormat, cchCRLF + 1);
|
|
nLen += cchCRLF;
|
|
|
|
pszFormat += cchCRLF;
|
|
}
|
|
|
|
fPreviousToken = FALSE;
|
|
if (hasFlag(LIF_DATE)) {
|
|
StrGetDate(szBuffer);
|
|
StrCpy(&szFormat[nLen], szBuffer);
|
|
nLen += StrLen(szBuffer);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (hasFlag(LIF_TIME)) {
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szSpace);
|
|
nLen += countof(c_szSpace)-1;
|
|
}
|
|
|
|
StrGetTime(szBuffer);
|
|
StrCpy(&szFormat[nLen], szBuffer);
|
|
nLen += StrLen(szBuffer);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szSpace);
|
|
nLen += countof(c_szSpace)-1;
|
|
}
|
|
if ((m_nAbsOffset-1 + m_iRelOffset) > 0) {
|
|
ASSERT((m_nAbsOffset-1 + m_iRelOffset) * m_bStep < countof(szBuffer));
|
|
for (UINT i = 0; i < (m_nAbsOffset-1 + m_iRelOffset) * m_bStep; i++)
|
|
szBuffer[i] = TEXT(' ');
|
|
|
|
StrCpy(&szFormat[nLen], szBuffer);
|
|
nLen += i-1;
|
|
}
|
|
|
|
fPreviousToken = FALSE;
|
|
if (hasFlag(LIF_MODULE_ALL)) {
|
|
pszAux = szBuffer;
|
|
if (!hasFlag(LIF_MODULEPATH))
|
|
makeRawFileName(m_szModule, szBuffer, countof(szBuffer));
|
|
else
|
|
pszAux = m_szModule; // should be lowercase already
|
|
|
|
StrCpy(&szFormat[nLen], pszAux);
|
|
nLen += StrLen(pszAux);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (hasFlag(LIF_FILE_ALL)) {
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szCommaSpace);
|
|
nLen += countof(c_szCommaSpace)-1;
|
|
}
|
|
|
|
if (!hasFlag(LIF_FILEPATH))
|
|
makeRawFileName(m_szFile, szBuffer, countof(szBuffer));
|
|
else {
|
|
StrCpy(szBuffer, m_szFile);
|
|
CharLower(szBuffer);
|
|
}
|
|
|
|
StrCpy(&szFormat[nLen], szBuffer);
|
|
nLen += StrLen(szBuffer);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (hasFlag(LIF_CLASS) && hasFlag(LIF_CLASS2)) {
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szCommaSpace);
|
|
nLen += countof(c_szCommaSpace)-1;
|
|
}
|
|
|
|
StrCpy(&szFormat[nLen], m_szClass);
|
|
nLen += StrLen(m_szClass);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (hasFlag(LIF_FUNCTION)) {
|
|
if (fPreviousToken) {
|
|
pszAux = (hasFlag(LIF_CLASS) && hasFlag(LIF_CLASS2)) ?
|
|
c_szColonColon : c_szCommaSpace;
|
|
|
|
StrCpy(&szFormat[nLen], pszAux);
|
|
nLen += StrLen(pszAux);
|
|
}
|
|
|
|
StrCpy(&szFormat[nLen], m_szFunction);
|
|
nLen += StrLen(m_szFunction);
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (hasFlag(LIF_LINE) && iLine > 0) {
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szCommaSpace);
|
|
nLen += countof(c_szCommaSpace)-1;
|
|
}
|
|
|
|
nAuxLen = wnsprintf(szBuffer, countof(szBuffer), c_szLine, iLine);
|
|
StrCpy(&szFormat[nLen], szBuffer);
|
|
nLen += nAuxLen;
|
|
|
|
fPreviousToken = TRUE;
|
|
}
|
|
|
|
if (pszFormat == NULL)
|
|
StrCpy(m_szMessage, szFormat);
|
|
// nLen stays the same
|
|
else {
|
|
if (fPreviousToken) {
|
|
StrCpy(&szFormat[nLen], c_szColonSpace);
|
|
nLen += countof(c_szColonSpace)-1;
|
|
}
|
|
|
|
StrCpy(&szFormat[nLen], pszFormat);
|
|
|
|
va_list arglist;
|
|
va_start(arglist, pszFormat);
|
|
nAuxLen = wvnsprintf(m_szMessage, countof(m_szMessage), szFormat, arglist);
|
|
va_end(arglist);
|
|
|
|
nLen = nAuxLen;
|
|
}
|
|
|
|
if (hasFlag(LIF_APPENDCRLF))
|
|
StrCpy(&m_szMessage[nLen], c_szCRLF);
|
|
|
|
if (hasFlag(LIF_DUPLICATEINODS))
|
|
OutputDebugString(m_szMessage);
|
|
|
|
return m_szMessage;
|
|
}
|
|
|
|
CLogItem::operator LPCTSTR() const
|
|
{
|
|
return m_szMessage;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLogItem implementation helper routines
|
|
|
|
LPCTSTR CLogItem::makeRawFileName(LPCTSTR pszPath, LPTSTR pszFile, UINT cchFile)
|
|
{
|
|
TCHAR szBuffer[MAX_PATH];
|
|
LPCTSTR pszRawName;
|
|
|
|
if (pszFile == NULL || cchFile == 0)
|
|
return NULL;
|
|
*pszFile = TEXT('\0');
|
|
|
|
if (pszPath == NULL || StrLen(pszPath) == 0)
|
|
return NULL;
|
|
|
|
pszRawName = PathFindFileName(pszPath);
|
|
ASSERT(StrLen(pszRawName) > 0);
|
|
StrCpy(szBuffer, pszRawName);
|
|
CharLower(szBuffer);
|
|
|
|
if (cchFile <= (UINT)StrLen(szBuffer))
|
|
return NULL;
|
|
|
|
StrCpy(pszFile, szBuffer);
|
|
return pszFile;
|
|
}
|
|
|
|
BOOL CLogItem::setFlag(DWORD dwMask, BOOL fSet /*= TRUE*/)
|
|
{
|
|
BOOL fIsFlag = ((m_dwFlags & dwMask) != 0L);
|
|
|
|
if (fIsFlag == fSet)
|
|
return FALSE;
|
|
|
|
if (!fIsFlag && fSet)
|
|
m_dwFlags |= dwMask;
|
|
|
|
else {
|
|
ASSERT(fIsFlag && !fSet);
|
|
m_dwFlags &= ~dwMask;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Utility functions
|
|
|
|
// Note. pszDate must point to the buffer of at least 11 characters.
|
|
LPCTSTR StrGetDate(LPTSTR pszDate)
|
|
{
|
|
SYSTEMTIME dt;
|
|
UINT nMonth, nDay, nYear;
|
|
|
|
GetLocalTime(&dt);
|
|
nMonth = dt.wMonth;
|
|
nDay = dt.wDay;
|
|
nYear = dt.wYear;
|
|
|
|
*(pszDate + 2) = *(pszDate + 5) = TEXT('/');
|
|
*(pszDate + 10) = TEXT('\0');
|
|
|
|
*(pszDate + 0) = (TCHAR)(nMonth / 10 + TEXT('0'));
|
|
*(pszDate + 1) = (TCHAR)(nMonth % 10 + TEXT('0'));
|
|
|
|
*(pszDate + 3) = (TCHAR)(nDay / 10 + TEXT('0'));
|
|
*(pszDate + 4) = (TCHAR)(nDay % 10 + TEXT('0'));
|
|
|
|
*(pszDate + 6) = (TCHAR)(((nYear / 1000) % 10) + TEXT('0'));
|
|
*(pszDate + 7) = (TCHAR)(((nYear / 100) % 10) + TEXT('0'));
|
|
*(pszDate + 8) = (TCHAR)(((nYear / 10) % 10) + TEXT('0'));
|
|
*(pszDate + 9) = (TCHAR)(((nYear / 1) % 10) + TEXT('0'));
|
|
|
|
return pszDate;
|
|
}
|
|
|
|
// Note. pszTime must point to the buffer of at least 9 characters.
|
|
LPCTSTR StrGetTime(LPTSTR pszTime)
|
|
{
|
|
SYSTEMTIME dt;
|
|
int nHours, nMinutes, nSeconds;
|
|
|
|
GetLocalTime(&dt);
|
|
nHours = dt.wHour;
|
|
nMinutes = dt.wMinute;
|
|
nSeconds = dt.wSecond;
|
|
|
|
*(pszTime + 2) = *(pszTime + 5) = TEXT(':');
|
|
*(pszTime + 8) = TEXT('\0');
|
|
|
|
*(pszTime + 0) = (TCHAR)(nHours / 10 + TEXT('0'));
|
|
*(pszTime + 1) = (TCHAR)(nHours % 10 + TEXT('0'));
|
|
|
|
*(pszTime + 3) = (TCHAR)(nMinutes / 10 + TEXT('0'));
|
|
*(pszTime + 4) = (TCHAR)(nMinutes % 10 + TEXT('0'));
|
|
|
|
*(pszTime + 6) = (TCHAR)(nSeconds / 10 + TEXT('0'));
|
|
*(pszTime + 7) = (TCHAR)(nSeconds % 10 + TEXT('0'));
|
|
|
|
return pszTime;
|
|
}
|
|
|
|
//----- Testing the stuff -----
|
|
/*
|
|
struct Test
|
|
{
|
|
Test();
|
|
void foo();
|
|
void bar();
|
|
};
|
|
|
|
static Test t;
|
|
|
|
Test::Test()
|
|
{ MACRO_LI_Prolog(Test, Test)
|
|
MACRO_LI_SetFlags(MACRO_LI_GetFlags() | LIF_DUPLICATEINODS);
|
|
|
|
LI0("Calling foo and then bar");
|
|
foo();
|
|
LI0("foo returned");
|
|
bar();
|
|
LI0("bar returned");
|
|
}
|
|
|
|
void Test::foo()
|
|
{ MACRO_LI_Prolog(Test, foo);
|
|
|
|
LI0("Calling bar");
|
|
bar();
|
|
LI0("bar returned");
|
|
}
|
|
|
|
void Test::bar()
|
|
{ MACRO_LI_Prolog(Test, bar);
|
|
|
|
LI0("No arguments");
|
|
LI1("One argument: %d", 2*2);
|
|
LI2("Two arguments: %i, %s", 15, TEXT("nyah"));
|
|
LI3("Three arguments: %d, %s, %x", 5, TEXT("the bar it is"), 0x80FF);
|
|
}
|
|
*/
|