|
|
//+----------------------------------------------------------------------------
//
// 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); }
|