/* * This file is part of rasdaman community. * * Rasdaman community is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rasdaman community is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with rasdaman community. If not, see . * * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / rasdaman GmbH. * * For more information please see * or contact Peter Baumann via . / /** * INCLUDE: rmdebug.hh * * PURPOSE: * Contains debug stuff. * * COMMENTS: * */ #ifndef _RMDEBUG_ #define _RMDEBUG_ #ifdef __VISUALC__ #include #else #include #endif #include "raslib/rminit.hh" #include "raslib/rm.hh" extern int RManDebug; extern int RManBenchmark; #ifdef RMANDEBUG #define RMDBGIF( levell, module, cls, text ) \ if (RMDebug::debugOutput( levell, module, cls )) { text } #define RMDBGENTER( levell, module, cls, text ) \ RMCounter rmCounter(levell, module, cls); \ if (RMDebug::debugOutput( levell, module, cls )) { \ RMInit::dbgOut << "ENTER "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ } #define RMDBGMIDDLE( levell, module, cls, text ) \ if (RMDebug::debugOutput( levell, module, cls )) { \ RMInit::dbgOut << "MIDDLE "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ } #define RMDBGONCE( levell, module, cls, text ) \ RMCounter rmCounter(levell, module, cls); \ if (RMDebug::debugOutput(levell, module, cls)) \ { \ RMInit::dbgOut << "ONCE "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; \ RMDebug::indentLine(); \ RMInit::dbgOut << text << endl << std::flush; \ } #define RMDBGEXIT( levell, module, cls, text ) \ if (RMDebug::debugOutput( levell, module, cls )) { \ RMInit::dbgOut << "EXIT "; RMInit::dbgOut.width(18); RMInit::dbgOut.setf(ios::left, ios::adjustfield); RMInit::dbgOut << cls << " "; RMDebug::indentLine(); RMInit::dbgOut << text << endl << std::flush; \ } #define RMDBCLASS( t1, t2, t3, t4, t5 ) RMDebug localRMDebug = RMDebug( t1, t2, t3, t4, t5 ); #else // Note: some parts of the code rely on these to be terminated by a ';'! #define RMDBGENTER( level, module, cls, text ) ; #define RMDBGMIDDLE( level, module, cls, text ) ; #define RMDBGONCE( level, module, cls, text ) ; #define RMDBGEXIT( level, module, cls, text ) ; #define RMDBGIF( level, module, cls, text) ; #define RMDBCLASS( t1, t2, t3, t4, t5 ) ; #endif // generate benchmark code only when RMANBENCHMARK is set #ifdef RMANBENCHMARK #define RMTIMER(class, func) RMTimer localRMTimer = RMTimer(class, func); #else #define RMTIMER(class, func) #endif //@ManMemo: Module: {\bf raslib}. /*@Doc: RMDebug is not strictly part of RasLib. It is a class used for generating debug output if compiling with RMANDEBUG defined. One way of using it is to put the following at the beginning of a function: {\tt RMDebug localRMDebug = RMDebug("className", "functionName", "moduleName", __FILE__, __LINE__");} This can be patched in automatically by a modified funchead.pl script. {\bf Functionality} Debug output printing class name, function name, module name, file name and line number given as parameters to the constructor is created, whenever the constructor is called. The destructor outputs class name and function name. If the static members {\tt debugModules} or {\tt debugClasses} are set, then only modules which are mentioned in the array of strings {\tt debugModules} or classes which are mentioned {\tt debugClasses} give debug output. {\tt debugModules} and {\tt debugClasses} can either be read from files named "rmdbmodules" and "rmdbclasses" or from the environment variables RMDBGMODULES and RMDBGCLASSES. The environment variables override the files. The contents of the files / variables are the names of the modules / classes separated by whitespace (space, newlines, ...). In the case of the modules each modulename may be followed by "," to set the debug level for that module explizitly, otherwise the default is used. {\bf Interdependencies} If only certain modules or classes are to be debugged, RMDebug has to be initialized in {\Ref RMInit}. This is done by reading the files {\tt rmdbmodules} and {\tt rmdbclasses}. The files should contain names of modules resp. classes to be debugged, each (including the last one!) followed by end of line. */ /** * \defgroup RMs RM Classes */ /** * \ingroup RMs */ class RMDebug : public RM_Class { public: /// constructor, initializes members and prints message. RMDebug(const char* newClass, const char* newFunc, const char* newModule, const char* newFile, int newLine); /// constructor taking an identifier to the module for more efficiency RMDebug(int newLevel, const char* newClass, const char* newFun, int newModuleNum, const char* newFile, int newLine); /// destructor, prints message. ~RMDebug(void); /// for initializing modules and classes to debug. static int initRMDebug(void); /// get the debug level of a module by its number static inline int getModuleDebugLevel(int modNum) { return allModuleLevels[modNum]; } /// get the name of a module by its number static inline const char* getModuleName(int modNum) { return allModuleNames[modNum]; } /// indent by the amount specified by level static inline void indentLine(void) { for (int i=0; i