474 lines
13 KiB
C++
474 lines
13 KiB
C++
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// File: DAVEDBG.CPP
|
||
|
//
|
||
|
// Synopsis: TraceLog class for debugging
|
||
|
//
|
||
|
// Arguments:
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#include "headers.hxx"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
GROUPSET LEGroups = GS_CACHE; // Groups to display
|
||
|
VERBOSITY LEVerbosity = VB_MAXIMUM; // Verbosity level to display at
|
||
|
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: dprintf
|
||
|
//
|
||
|
// Synopsis: Dumps a printf style string to the debugger.
|
||
|
//
|
||
|
// Arguments: [szFormat] THIS pointer of caller
|
||
|
// [...] Arguments
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 05-Sep-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
int dprintf(LPCSTR szFormat, ...)
|
||
|
{
|
||
|
char szBuffer[MAX_BUF];
|
||
|
|
||
|
va_list vaList;
|
||
|
va_start(vaList, szFormat);
|
||
|
|
||
|
int retval = vsprintf(szBuffer, szFormat, vaList);
|
||
|
|
||
|
OutputDebugStringA(szBuffer);
|
||
|
|
||
|
va_end (vaList);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: mprintf
|
||
|
//
|
||
|
// Synopsis: Dumps a printf style string to a message box.
|
||
|
//
|
||
|
// Arguments: [szFormat] THIS pointer of caller
|
||
|
// [...] Arguments
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 05-Sep-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
int mprintf(LPCSTR szFormat, ...)
|
||
|
{
|
||
|
char szBuffer[MAX_BUF];
|
||
|
|
||
|
va_list vaList;
|
||
|
va_start(vaList, szFormat);
|
||
|
|
||
|
int retval = vsprintf(szBuffer, szFormat, vaList);
|
||
|
|
||
|
extern CCacheTestApp ctest;
|
||
|
|
||
|
MessageBox(ctest.Window(),
|
||
|
szBuffer,
|
||
|
"CACHE UNIT TEST INFO",
|
||
|
MB_ICONINFORMATION | MB_APPLMODAL | MB_OK);
|
||
|
|
||
|
va_end (vaList);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: TraceLog::TraceLog
|
||
|
//
|
||
|
// Synopsis: Records the THIS ptr and function name of the caller,
|
||
|
// and determines whether or not the caller meets the
|
||
|
// group and verbosity criteria for debug output
|
||
|
//
|
||
|
// Arguments: [pvThat] THIS pointer of caller
|
||
|
// [pszFuntion] name of caller
|
||
|
// [gsGroups] groups to which caller belongs
|
||
|
// [vbVerbosity] verbosity level need to display debug
|
||
|
// info for this function
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
TraceLog::TraceLog (void * pvThat,
|
||
|
char * pszFunction,
|
||
|
GROUPSET gsGroups,
|
||
|
VERBOSITY vbVerbosity)
|
||
|
{
|
||
|
//
|
||
|
// Determine whether or not the trace logging should be displayed
|
||
|
// for this function. Iff it is, we need to track some information
|
||
|
// about the function (ie: this ptr, func name)
|
||
|
//
|
||
|
// In order to be displayed, the function must belong to a group
|
||
|
// which has been set in the group display mask, and the function
|
||
|
// must be in an equal or lesser verbosity class.
|
||
|
//
|
||
|
|
||
|
if ( (gsGroups & LEGroups) && (LEVerbosity >= vbVerbosity) )
|
||
|
{
|
||
|
m_fShouldDisplay = TRUE;
|
||
|
m_pvThat = pvThat;
|
||
|
strncpy(m_pszFunction, pszFunction, MAX_BUF - 1);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_fShouldDisplay = FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: TraceLog::OnEntry()
|
||
|
//
|
||
|
// Synopsis: Default entry output, which simply displays the _IN
|
||
|
// trace with the function name and THIS pointer
|
||
|
//
|
||
|
// Returns: HRESULT
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void TraceLog::OnEntry()
|
||
|
{
|
||
|
if (m_fShouldDisplay)
|
||
|
{
|
||
|
dprintf("[%p] _IN %s\n", m_pvThat, m_pszFunction);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: TraceLog::OnEntry
|
||
|
//
|
||
|
// Synopsis: Displays standard entry debug info, plus a printf
|
||
|
// style trailer string as supplied by the caller
|
||
|
//
|
||
|
// Arguments: [pszFormat ...] printf style output string
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void TraceLog::OnEntry(char * pszFormat, ...)
|
||
|
{
|
||
|
//
|
||
|
// Only display if we have already matched the correct criteria
|
||
|
//
|
||
|
|
||
|
if (m_fShouldDisplay)
|
||
|
{
|
||
|
char szBuffer[MAX_BUF];
|
||
|
|
||
|
//
|
||
|
// print the standard trace output, then the custom information as
|
||
|
// received from the caller
|
||
|
//
|
||
|
|
||
|
dprintf("[%p] _IN %s ", m_pvThat, m_pszFunction);
|
||
|
|
||
|
va_list vaList;
|
||
|
va_start(vaList, pszFormat);
|
||
|
vsprintf(szBuffer, pszFormat, vaList);
|
||
|
dprintf(szBuffer);
|
||
|
va_end(vaList);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: TraceLog::OnExit
|
||
|
//
|
||
|
// Synopsis: Sets the debug info that should be displayed when
|
||
|
// the TraceLog object is destroyed
|
||
|
//
|
||
|
// Arguments: [pszFormat ...] printf style custom info
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Notes: Since it would make no sense to pass variables by
|
||
|
// value into this function (which would snapshot them
|
||
|
// at the time this was called), variables in the arg
|
||
|
// list must be passed by REFERENCE
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
void TraceLog::OnExit(const char * pszFormat, ...)
|
||
|
{
|
||
|
if (m_fShouldDisplay)
|
||
|
{
|
||
|
const char * pch; // ptr to walk format string
|
||
|
BOOL fBreak; // set when past fmt specifier
|
||
|
|
||
|
//
|
||
|
// Start processing the argument list
|
||
|
//
|
||
|
|
||
|
va_list arg;
|
||
|
va_start (arg, pszFormat);
|
||
|
|
||
|
//
|
||
|
// Save the format string for use in the destructor
|
||
|
//
|
||
|
|
||
|
strcpy (m_pszFormat, pszFormat);
|
||
|
m_cArgs = 0;
|
||
|
|
||
|
//
|
||
|
// Walk the format string looking for % modifiers
|
||
|
//
|
||
|
|
||
|
for (pch = pszFormat; *pch; pch++)
|
||
|
{
|
||
|
if (*pch != '%')
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// We can stop looking until EOL or end of specifier
|
||
|
|
||
|
fBreak = FALSE;
|
||
|
|
||
|
while (!fBreak)
|
||
|
{
|
||
|
if (!* (++pch)) // Hit EOL
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (*pch)
|
||
|
{
|
||
|
//
|
||
|
// These are all valid format specifiers and
|
||
|
// modifers which may be combined to reference
|
||
|
// a single argument in the argument list
|
||
|
//
|
||
|
|
||
|
case 'F':
|
||
|
case 'l':
|
||
|
case 'h':
|
||
|
case 'X':
|
||
|
case 'x':
|
||
|
case 'O':
|
||
|
case 'o':
|
||
|
case 'd':
|
||
|
case 'u':
|
||
|
case 'c':
|
||
|
case 's':
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
|
||
|
//
|
||
|
// We have hit a character which is not a valid specifier,
|
||
|
// so we stop searching in order to pull the argument
|
||
|
// which corresponds with it from the arg list
|
||
|
//
|
||
|
fBreak = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we have already hit the maximum number of args, we can't do
|
||
|
// any more
|
||
|
//
|
||
|
|
||
|
if (m_cArgs == MAX_ARGS)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Grab the argument as a NULL ptr. We will save it away and figure
|
||
|
// out what kind of argument it was when it comes time to display it,
|
||
|
// based on the format string
|
||
|
//
|
||
|
|
||
|
m_aPtr[m_cArgs] = va_arg (arg, void *);
|
||
|
m_cArgs++;
|
||
|
|
||
|
if (! *pch)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//+----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Member: TraceLog::~TraceLog
|
||
|
//
|
||
|
// Synopsis: On destruction, the TraceLog class displays its debug
|
||
|
// output as set by the OnExit() method.
|
||
|
//
|
||
|
// Returns: void
|
||
|
//
|
||
|
// Notes:
|
||
|
//
|
||
|
// History: 23-Aug-94 Davepl Created
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
TraceLog::~TraceLog()
|
||
|
{
|
||
|
char szTmpFmt[ MAX_BUF ];
|
||
|
char szOutStr[ MAX_BUF ];
|
||
|
char *pszOut;
|
||
|
char *pszszTmpFmt;
|
||
|
const char * pszFmt;
|
||
|
void *pv;
|
||
|
BYTE i = 0;
|
||
|
VARTYPE vtVarType;
|
||
|
BOOL fBreak;
|
||
|
|
||
|
pszOut = szOutStr;
|
||
|
|
||
|
//
|
||
|
// Walk the format string looking for format specifiers
|
||
|
//
|
||
|
|
||
|
for (pszFmt = m_pszFormat; *pszFmt; pszFmt++)
|
||
|
{
|
||
|
if (*pszFmt != '%')
|
||
|
{
|
||
|
*pszOut++ = *pszFmt;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Found the start of a specifier. Reset the expected argument type,
|
||
|
// then walk to the end of the specifier
|
||
|
//
|
||
|
|
||
|
vtVarType = NO_TYPE;
|
||
|
fBreak = FALSE;
|
||
|
|
||
|
//
|
||
|
// Start recording the specifier for a single call to sprintf later
|
||
|
//
|
||
|
|
||
|
for (pszszTmpFmt = szTmpFmt; !fBreak; )
|
||
|
{
|
||
|
*pszszTmpFmt++ = *pszFmt;
|
||
|
|
||
|
//
|
||
|
// Guard against a terminator that doesn't comlete before EOL
|
||
|
//
|
||
|
|
||
|
if (!* (++pszFmt))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// These are all valid format specifiers. Skip over them and
|
||
|
// update the vtVarType. It's end value will be our heuristic
|
||
|
// which indicates what type of variable was really intended
|
||
|
//
|
||
|
|
||
|
switch (*pszFmt)
|
||
|
{
|
||
|
case 'l': vtVarType |= LONG_TYPE; break;
|
||
|
case 'h': vtVarType |= SHORT_TYPE; break;
|
||
|
case 'X': vtVarType |= INT_TYPE; break;
|
||
|
case 'x': vtVarType |= INT_TYPE; break;
|
||
|
case 'O': vtVarType |= INT_TYPE; break;
|
||
|
case 'o': vtVarType |= INT_TYPE; break;
|
||
|
case 'd': vtVarType |= INT_TYPE; break;
|
||
|
case 'u': vtVarType |= INT_TYPE; break;
|
||
|
case 'c': vtVarType |= CHAR_TYPE; break;
|
||
|
case 's': vtVarType |= STRING_TYPE; break;
|
||
|
case 'p': vtVarType |= PTR_TYPE; break;
|
||
|
default: fBreak = TRUE; break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NUL-terminate the end of the temporary format string
|
||
|
|
||
|
*pszszTmpFmt = 0;
|
||
|
|
||
|
// Grab the argument pointer which corresponds to this argument
|
||
|
|
||
|
pv = m_aPtr[ i ];
|
||
|
i++;
|
||
|
|
||
|
//
|
||
|
// Using the appropriate cast, spew the argument into our
|
||
|
// local output buffer using the original format specifier.
|
||
|
//
|
||
|
|
||
|
if (vtVarType & STRING_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, (char *)pv);
|
||
|
}
|
||
|
else if (vtVarType & LONG_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, *(long *)pv);
|
||
|
}
|
||
|
else if (vtVarType & SHORT_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, *(short *)pv);
|
||
|
}
|
||
|
else if (vtVarType & INT_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, *(int *)pv);
|
||
|
}
|
||
|
else if (vtVarType & CHAR_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, (char)*(char *)pv);
|
||
|
}
|
||
|
else if (vtVarType & PTR_TYPE)
|
||
|
{
|
||
|
sprintf (pszOut, szTmpFmt, (void *)pv);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pszOut = 0;
|
||
|
}
|
||
|
|
||
|
// Advance the output buffer pointer to the end of the
|
||
|
// current buffer
|
||
|
|
||
|
pszOut = &pszOut[ strlen(pszOut) ];
|
||
|
|
||
|
if (! *pszFmt)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// NUL-terminate the buffer
|
||
|
|
||
|
*pszOut = 0;
|
||
|
|
||
|
//
|
||
|
// Dump the resultant buffer to the output
|
||
|
//
|
||
|
|
||
|
dprintf("[%p] OUT %s %s", m_pvThat, m_pszFunction, szOutStr);
|
||
|
}
|