tripwire-open-source/src/core/debug.cpp

323 lines
9.1 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000-2018 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
// debug.cpp
#include "stdcore.h"
#include "debug.h"
#include "errorutil.h"
#ifdef DEBUG
# ifndef va_start
# include <cstdarg>
# endif
#include <cwchar>
#include <fstream>
#include <cstdio>
int cDebug::mDebugLevel(10);
uint32 cDebug::mOutMask(cDebug::OUT_TRACE);
std::ofstream cDebug::logfile;
//mDebugLevel default == 10, mOutMask default == OUT_TRACE.
///////////////////////////////////////////////////////////////////////////////
// Constructors and Destructor
cDebug::cDebug(const char* label)
{
int cnt = strlen(label);
if (cnt > cDebug::MAX_LABEL)
cnt = cDebug::MAX_LABEL - 1;
memcpy(mLabel, label, cnt);
mLabel[cnt] = '\0';
}
cDebug::cDebug(const cDebug& rhs)
{
strncpy(mLabel, rhs.mLabel, MAX_LABEL);
}
cDebug::~cDebug()
{
if (logfile)
logfile.close();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// Trace -- Outputs a format string only if the passed integer value is <=
// the "global debug level" (indicated by mDebugLevel).
///////////////////////////////////////////////////////////////////////////////
void cDebug::Trace(int levelNum, const char* format, ...)
{
if (levelNum > mDebugLevel)
return;
// create the output buffer
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
///////////////////////////////////////////////////////////////////////////////
// DoTrace()
// internal helper function -- does the actual printing to logfile,
// console, etc...
///////////////////////////////////////////////////////////////////////////////
void cDebug::DoTrace(const char* format, va_list& args)
{
size_t guard1 = 0xBABABABA;
char out[2048];
size_t guard2 = 0xBABABABA;
vsnprintf(out, 2048, format, args);
ASSERT(guard1 == 0xBABABABA && guard2 == 0xBABABABA); // string was too long
ASSERT(strlen(out) < 1024);
std::ostringstream ostr;
ostr.setf(std::ios::left);
ostr.width(40);
ostr << mLabel;
ostr.width(0);
ostr << out;
if ((mOutMask & OUT_STDOUT) != 0)
{
std::cout << ostr.str().c_str();
std::cout.flush();
}
//
//make it output to log file!
//
if ((mOutMask & OUT_FILE) != 0)
{
// the logfile is narrow chars only...
logfile.setf(std::ios::left);
logfile.width(40);
logfile << mLabel;
logfile.width(0);
logfile << out;
logfile.flush();
}
}
# ifdef DEBUG
//
// wrappers around Trace() that requires less typing
// TODO: this is quick and dirty, but lets me check in all these files right away. --ghk
//
void cDebug::TraceAlways(const char* format, ...)
{
if (D_ALWAYS > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceError(const char* format, ...)
{
if (D_ERROR > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceWarning(const char* format, ...)
{
if (D_WARNING > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceDebug(const char* format, ...)
{
if (D_DEBUG > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceDetail(const char* format, ...)
{
if (D_DETAIL > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceNever(const char* format, ...)
{
if (D_NEVER > mDebugLevel)
return;
// fill up arglist, and pass to printing routine
va_list args;
va_start(args, format);
DoTrace(format, args);
va_end(args);
}
void cDebug::TraceVaArgs(int iDebugLevel, const char* format, va_list& args)
{
if (iDebugLevel <= mDebugLevel)
DoTrace(format, args);
}
# endif // DEBUG
///////////////////////////////////////////////////////////////////////////////
// AddOutTarget -- Attempts to add a new target for trace/debug output.
// FAILS ONLY IF caller attempts to SET OUT_FILE via this function.
///////////////////////////////////////////////////////////////////////////////
bool cDebug::AddOutTarget(OutTarget target)
{
if (target == OUT_STDOUT)
mOutMask |= OUT_STDOUT;
if (target == OUT_TRACE)
mOutMask |= OUT_TRACE;
if (target == OUT_FILE)
{
mOutMask |= OUT_FILE;
return false;
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
// RemoveOutTarget -- Masks out from mOutMask the value passed.
///////////////////////////////////////////////////////////////////////////////
bool cDebug::RemoveOutTarget(OutTarget target)
{
if (!HasOutTarget(target))
return true;
if (target == OUT_STDOUT)
mOutMask ^= OUT_STDOUT;
if (target == OUT_TRACE)
mOutMask ^= OUT_TRACE;
if (target == OUT_FILE)
mOutMask ^= OUT_FILE;
return true;
}
///////////////////////////////////////////////////////////////////////////////
// HasOutTarget -- Takes target - target must represent a single flagged bit
///////////////////////////////////////////////////////////////////////////////
bool cDebug::HasOutTarget(OutTarget target)
{
if (target == OUT_STDOUT)
return ((mOutMask & OUT_STDOUT) != 0);
else if (target == OUT_TRACE)
return ((mOutMask & OUT_TRACE) != 0);
else if (target == OUT_FILE)
return ((mOutMask & OUT_FILE) != 0);
else //ambiguous input, or too many bits set in target
return false;
}
///////////////////////////////////////////////////////////////////////////////
// SetOutputFile -- Attempts to set the output file for Logfile member to
// the string passed in.
///////////////////////////////////////////////////////////////////////////////
bool cDebug::SetOutputFile(const char* filename)
{
// TODO -- make sure this does the right thing if a log file is
// already open!
// TODO -- make this work with wide chars
if (!logfile)
logfile.open(filename, std::ios_base::out | std::ios_base::ate | std::ios_base::app);
else
logfile.setf(std::ios_base::hex, std::ios_base::basefield);
//make sure info. will not be clobbered.
//Should be open now- if not, abort.
if (!logfile)
{
mOutMask ^= OUT_FILE;
return false;
}
else
mOutMask |= OUT_FILE;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// DebugOut -- Works just like TRACE. note: there is an internal buffer size
// of 1024; traces larger than that will have unpredictable results.
//////////////////////////////////////////////////////////////////////////////
void cDebug::DebugOut(const char* lpOutputString, ...)
{
char buf[2048];
// create the output buffer
va_list args;
va_start(args, lpOutputString);
vsnprintf(buf, 2048, lpOutputString, args);
va_end(args);
# ifdef DEBUG
TCERR << buf;
# endif //_DEBUG
TCOUT.flush();
}
#endif // DEBUG
//////////////////////////////////////////////////////////////////////////////////
// ASSERT macro support function
//////////////////////////////////////////////////////////////////////////////////