I suggest a little different approach within your C++.
This will only simplify your shell script needs slightly, but will result in much better C++ code.
In short, I suggest creating a Trace class and a set of macros to deploy it. This has a lot of advantages:
- Easy to add, remove, change, printouts.
- Automatically takes care of filename, function name, line number, and much more.
- Works no matter where the function exits (this is a big improvement over your approach)
Create a Trace class which accepts arguments such as function name, file name, line #, etc. - whatever you want to be able to print out. Whenever a Trace class is constructed it will print a function entry message. Whenever a Trace class goes out of scope and is destructed it will print a function exit message.
So here's the class declaration:
// File: Trace.h
class Trace
{
public:
// print function entry message
Trace(const char *name,
const char *file,
const int line,
int traceOn = -1, // used for enabling/disabling Trace printing
// within a particular call chain.
const void* thisPtr = 0);
// print function exit message
~Trace();
static bool active;
private:
std::string* theFunctionName;
std::string* theFileName;
int theLineNumber;
const void* theThisPtr;
static int layer; // used for printout indenting
static std::list<clock_t> startTimeList; // used for printing timing information
bool previouslyActive;
};
Now let's look at the corresponding macros (these also go in Trace.h
):
#ifdef TRACE_ENABLED // define the real macros
#undef TRACE_ENABLED // must be re #defined preceding each '#include "Trace.h" '
#define TRACE__ Trace tr_( __FUNCTION__ , __FILE__ , __LINE__, -1, this );
#define TRACE_OFF__ Trace tr_off_(__FUNCTION__ , __FILE__ , __LINE__, false);
#define TRACE_ON__ Trace tr_on_( __FUNCTION__ , __FILE__ , __LINE__, true);
#else // DUMMY MACROS: if TRACE_ENABLED is not defined.
#define TRACE__
#define TRACE_ON__
#define TRACE_OFF__
#endif
Now, to use the Trace class, you would do the following:
//SomeSrcFile.cpp
//Sample
#define TRACE_ENABLED // comment this out to disable tracing in this file.
#include "Trace.h"
ReturnType SomeClass::SomeFunc1(InputParameters)
{
TRACE__
......
}
ReturnType SomeClass::SomeFunc2(InputParameters) {
TRACE__
......
}
Now, a potential implementation of the Trace class:
// File: Trace.C
#include "Trace.h"
bool Trace::active = true;
int Trace::layer = 0;
std::list<clock_t> Trace::startTimeList;
Trace::Trace(const char *name,
const char *file,
const int line,
int traceOn, // default: -1
const void* thisPtr) // default: 0
: theFunctionName(0),
theFileName(0),
theLineNumber(0),
theThisPtr(thisPtr),
previouslyActive(active)
{
if (active)
{
theFunctionName = new std::string(name);
theFileName = new std::string(file);
theLineNumber = line;
std::cout<<"---> Trace: ";
for( int L = 0; L < layer; ++L )
{
std::cout<<" ";
}
std::cout
<<"{ Entered "
<< *theFileName << ":"
<< theLineNumber << " "
<< *theFunctionName << "()";
if(thisPtr > 0)
{
std::cout<<" this = "<< thisPtr;
}
std::cout<< std::endl;
layer++;
startTimeList.push_back(clock());
}
if(traceOn >= 0)
{
active = traceOn;
if (active && !previouslyActive)
{
std::cout<<"+++] Trace: Enabled"<<std::endl;
}
else if (previouslyActive && !active)
{
std::cout<<"+++[ Trace: Disabled"<<std::endl;
}
}
}
Trace::~Trace()
{
if (previouslyActive && !active)
{
std::cout<<"+++] Trace: Enabled"<<std::endl;
}
else if (active && !previouslyActive)
{
std::cout<<"+++[ Trace: Disabled"<<std::endl;
}
active = previouslyActive;
if (active || theFunctionName)
{
layer--;
double startTime = static_cast<double>(startTimeList.back());
startTimeList.pop_back();
double endTime = static_cast<double>(clock());
double elapsedTime = (endTime-startTime)/CLOCKS_PER_SEC;
std::cout<<"<--- Trace: ";
for( int L = 0; L < layer; ++L )
{
std::cout<<" ";
}
std::cout<<"} Leaving "
<< *theFileName << ":"
<< theLineNumber <<" "
<< *theFunctionName <<"()";
if(theThisPtr > 0)
{
std::cout<<" this = "<< theThisPtr;
}
std::cout<<" elapsedTime = "<<elapsedTime<<"s";
std::cout<< std::endl;
delete theFunctionName;
delete theFileName;
}
}