#ifndef INCLUDE_NAST_DEBUG_H #define INCLUDE_NAST_DEBUG_H //----------------------------------------------------------------------------- // NastDebug.h //----------------------------------------------------------------------------- // // Copyright (C) 1998 Technische Universitaet Muenchen, Germany // written by Bernhard Brueck // // This file is part of Nast++ // //----------------------------------------------------------------------------- // CNastDebug stellt Funktionen zur Verfuegung um das Programm zu verlassen // und um die Contexte fuer die Ausgaben zu liefern. // Ausserdem werden in NastDebug.h alle Macros definiert, // die fuer eine Unterstuetzung beim Debuggen notwendig sind. // Die Einstellungen was verwendet werden soll stehen in NastConfig.h. // // Macros: // NAST_ASSERT(expr) falls !expr Abbruch // NAST_ASSERT_DUMP(expr, msg) falls !expr Abbruch und Ausgabe von msg // NAST_ASSERT_VALID(obj) assertValid von obj aufrufen // // NAST_WARNING(msg) msg in den warningcontext ausgeben // NAST_ASSERT_WARNING(expr, msg) falls !expr Warnung ausgeben // // NAST_DUMP_POSITION() Position ins Logfile ausgeben // NAST_DUMP_MESSAGE(msg) msg in den Logcontext ausgeben // NAST_DUMP_VARIABLE(var) Variable in den Logcontext ausgeben // // NAST_FATAL_ERROR(msg) bricht das Programm mit einer Fehler- // meldung ab // // NAST_BREAK() auf Benutzereingabe warten // //----------------------------------------------------------------------------- // Bei msg muss es sich dabei nicht um einen reinen String handeln, // sondern es kann auch eine Folge von << Operatoren sein. Das ermoglicht // Angaben in der Form: // NAST_ASSERT_DUMP( x > 10, "x = " << x << " ist zu klein"); //----------------------------------------------------------------------------- // Aenderungen: // #include "NastConfig.h" #include "NastDumpContext.h" #include "NastVisualContext.h" #include "NastVisualContextGnuplot.h" //----------------------------------------------------------------------------- // CNastDebug hat die Aufgabe drei global verfuegbare DumpContexte zu // verwalten // // dumpErrors() liefert einen DumpContext um Fehler auszugeben, die auch // zum Programmabbruch fuehren koennen // z.B. Ausgaben von ASSERT // // dumpWarnings() ist fuer Ausgaben zustaendig die evtl kritisch sein // koennen, aber keinen Programmabruch erfordern // // dumpLogfile() ist fuer reine Statusinformationen // // und eine Routinen fuer einen Programmabbruch zu bieten // mit den entsprechenden Routinen zum setzen der Dumpcontexte // kann jederzeit die gesamte Ausgabe auf neue Dumpcontexte gestzt werden //----------------------------------------------------------------------------- class CNastDebug { public: CNastDebug(); ~CNastDebug(); void dumpContextErrors( CNastDumpContext *pDC ); void dumpContextWarnings( CNastDumpContext *pDC ); void dumpContextLogfile ( CNastDumpContext *pDC ); static CNastDumpContext& dumpContextErrors(); static CNastDumpContext& dumpContextWarnings(); static CNastDumpContext& dumpContextLogfile(); static void fatalError( const char *szAssertion, const char *szFileName, int nLine, const char *szFunction, const char *szMessage); static void fatalExit(); private: static CNastDumpContext *m_pNastDumpErrors; static CNastDumpContext *m_pNastDumpWarnings; static CNastDumpContext *m_pNastDumpLogfile; }; //---------------------------------------------------------------------------- // Tests zur Laufzeit //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // NAST_POSITION_IN_FILE liefert einen String mit der Position des Macros // im Projekt. Bei neueren GNU-Compilern kann auch die Funktion ermittelt // werden, in der sich das Macro befindet. In diesem Fall liefert // NAST_POSTITION_IN_FILE_PRETTY auch noch den Funktionsnamen. // anderen Macros benutzt. //----------------------------------------------------------------------------- // ab der Version gcc 2.4 kann die Funktion ermittelt werden in der // das NAST_ASSERT Macro expandiert wurde # define NAST_POSITION_IN_FILE __FILE__ << ":" << __LINE__ << ": " #if (!defined (__GNUC__) || __GNUC__ < 2 || __GNUC_MINOR__ < (defined (__cplusplus) ? 6 : 4)) # define NAST_PRETTY_FUNCTION 0 # define NAST_POSITION_IN_FILE_PRETTY NAST_POSITION_IN_FILE #else # define NAST_PRETTY_FUNCTION __PRETTY_FUNCTION__ # define NAST_POSITION_IN_FILE_PRETTY NAST_POSITION_IN_FILE << ":" << __PRETTY_FUNCTION__ << ": " #endif //----------------------------------------------------------------------------- // Fuer abgeschaltete Macros wird als Ersatz NAST_EMPTY verwendet //----------------------------------------------------------------------------- #define NAST_EMPTY (void(0)) //----------------------------------------------------------------------------- // Falls NAST_USE_ASSERT definiert ist werden die beiden // Macros NAST_ASSERT und NAST_ASSERT_DUMP definiert. //----------------------------------------------------------------------------- #ifdef NAST_USE_ASSERT # define NAST_ASSERT(expr) \ if(!(expr)) \ CNastDebug::fatalError( #expr, \ __FILE__, \ __LINE__, \ NAST_PRETTY_FUNCTION, \ 0 ); # define NAST_ASSERT_DUMP(expr, szMessage) \ if(!(expr)) \ { \ CNastDebug::dumpContextErrors() \ << "\n\nFolgendes Problem hat sich ergeben : \n" \ << "\n" << szMessage << "\n\n"; \ CNastDebug::fatalError( #expr, \ __FILE__, \ __LINE__, \ NAST_PRETTY_FUNCTION, \ 0); \ } #else # define NAST_ASSERT( expr ) NAST_EMPTY # define NAST_ASSERT_DUMP( expr, szMessage ) NAST_EMPTY #endif // NAST_USE_ASSERT //----------------------------------------------------------------------------- // Wenn NAST_USE_ASSERT_INDEX definiert ist wird NAST_ASSERT_INDEX definiert // ansonsten wird ein Dummy eingefuegt. // Die Funktionalitaet von NAST_ASSERT_INDEX entspricht einem nornmalen // NAST_ASSERT, es laesst sich aber davon getrennt an- und ausschalten. //----------------------------------------------------------------------------- #ifdef NAST_USE_ASSERT_INDEX # define NAST_ASSERT_INDEX(expr) \ if(!(expr)) CNastDebug::fatalError( #expr, \ __FILE__, \ __LINE__, \ NAST_PRETTY_FUNCTION, \ "fehlerhafter Indexzugriff !"); #else # define NAST_ASSERT_INDEX( expr ) NAST_EMPTY #endif // NAST_USE_ASSERT_INDEX //----------------------------------------------------------------------------- // Wenn NAST_USE_ASSERT_VALID definiert ist wird NAST_ASSERT_VALID definiert // ansonsten wird ein Dummy eingefuegt. // NAST_ASSERT_VALID(obj) ruft die assertValid Funktion von obj auf, // nachdem ueberprueft wurde ob es sich dabei nicht um einen Null-Pointer // handelt. //----------------------------------------------------------------------------- #ifdef NAST_USE_ASSERT_VALID # define NAST_ASSERT_VALID(x) \ if( (x) != 0 ) \ (x)->assertValid(); \ else \ CNastDebug::fatalError( "this == 0", \ __FILE__, \ __LINE__, \ NAST_PRETTY_FUNCTION, \ "Nullpointer !" ); #else # define NAST_ASSERT_VALID(x) NAST_EMPTY #endif // NAST_USE_ASSERT_VALID //----------------------------------------------------------------------------- // falls NAST_USE_WARNING definiert ist NAST_WARNING und // NAST_ASSERT_WARNING definieren //----------------------------------------------------------------------------- #ifdef NAST_USE_WARNING # define NAST_WARNING( szMessage ) \ CNastDebug::dumpContextWarnings() << NAST_POSITION_IN_FILE_PRETTY \ << " Warning: " \ << szMessage << "\n" # define NAST_ASSERT_WARNING( expr, szMessage) \ if( !(expr) ) \ { \ CNastDebug::dumpContextWarnings() << NAST_POSITION_IN_FILE_PRETTY \ << " warning: " \ << szMessage << "\n"; \ } #else # define NAST_WARNING( szMessage ) NAST_EMPTY # define NAST_ASSERT_WARNING( expr, szMessage) NAST_EMPTY #endif // NAST_USE_WARNINGS //----------------------------------------------------------------------------- // falls NAST_USE_DUMP_POSITION definiert ist NAST_DUMP_POSITION // definieren. Die Ausgabe der Meldungen erfolgt ins Logfile. //----------------------------------------------------------------------------- #ifdef NAST_USE_DUMP_POSITION # define NAST_DUMP_POSITION() \ CNastDebug::dumpContextLogfile() << NAST_POSITION_IN_FILE_PRETTY \ << "NAST_DUMP_POSITION() \n" #else # define NAST_DUMP_POSITION() NAST_EMPTY #endif // NAST_USE_DUMP_POSITION //----------------------------------------------------------------------------- // falls NAST_USE_DUMP_MESSAGE definiert ist NAST_DUMP_POSITION // definieren. Die Ausgabe der Meldungen erfolgt ins Logfile. //----------------------------------------------------------------------------- #ifdef NAST_USE_DUMP_MESSAGE # define NAST_DUMP_MESSAGE(msg) \ CNastDebug::dumpContextLogfile() << NAST_POSITION_IN_FILE_PRETTY \ << msg << "\n" #else # define NAST_DUMP_MESSAGE(msg) NAST_EMPTY #endif // NAST_USE_DUMP_MESSAGE //----------------------------------------------------------------------------- // falls NAST_USE_DUMP_VARIABLE definiert ist NAST_DUMP_VARIABLE // definieren. Die Ausgabe der Variablen erfolgt ins Logfile. //----------------------------------------------------------------------------- #ifdef NAST_USE_DUMP_VARIABLE # define NAST_DUMP_VARIABLE(var) \ CNastDebug::dumpContextLogfile() << NAST_POSITION_IN_FILE \ << #var << " = " << var << "\n" #else # define NAST_DUMP_VARIABLE(var) NAST_EMPTY #endif // NAST_USE_DUMP_VARIABLE //----------------------------------------------------------------------------- // falls NAST_USE_DUMP_VISUAL definiert ist // NAST_DUMP_VISUAL fuer CNastObjekte // NAST_DUMP_VISUAL_INTERVALL fuer doubles // definieren. Die Ausgabe erfolge in den aktuellen VisualContext //----------------------------------------------------------------------------- #ifdef NAST_USE_DUMP_VISUAL # define NAST_DUMP_VISUAL_INTERVALL( y, nSize ) \ { \ NAST_ASSERT( nSize > 0 ); \ static int nCalled = 0; \ static CNastArray arrX;\ static CNastArray arrY; \ static NAST_DUMP_VISUAL_CONTEXT visContext(#y); \ if( nCalled < nSize) \ { \ arrX.add(nCalled); \ arrY.add(y); \ } \ else \ { \ for( int i = 0; i < nSize-1; i++) \ { \ arrX[i] = arrX[i+1]; \ arrY[i] = arrY[i+1]; \ } \ arrX[nSize-1] = nCalled; \ arrY[nSize-1] = y; \ } \ visContext.show(arrX, arrY); \ nCalled++; \ } # define NAST_DUMP_VISUAL(obj) \ { \ static NAST_DUMP_VISUAL_CONTEXT visContext(__FILE__" "#obj); \ visContext.show(obj); \ } #else # define NAST_DUMP_VISUAL_INTERVALL( y, nCount ) NAST_EMPTY # define NAST_DUMP_VISUAL(obj) NAST_EMPTY #endif //----------------------------------------------------------------------------- // Programmabbruch mit Fehlermeldung //----------------------------------------------------------------------------- #define NAST_FATAL_ERROR(szString) \ CNastDebug::fatalError( 0, \ __FILE__, \ __LINE__, \ NAST_PRETTY_FUNCTION, \ szString ) //----------------------------------------------------------------------------- // Warten auf eine Eingabe durch den Benutzer //----------------------------------------------------------------------------- #ifdef NAST_USE_BREAK # include # include # define NAST_BREAK() \ { \ static int nCount = 1; \ if( --nCount == 0) \ { \ char szBuff[10]; \ cout << NAST_POSITION_IN_FILE << "(-2 BREAK, -1 RUN, n Steps)\n"; \ cout.flush(); \ cin.getline(szBuff,10); \ int i = atoi(szBuff); \ if( i == 0) i = 1; \ if( i == -2) NAST_FATAL_ERROR("Break" ); \ nCount = i; \ } \ } #else # define NAST_BREAK() NAST_EMPTY #endif #endif // INCLUDE_NAST_DEBUG_H