Inferno
0.2
|
00001 #include "trace.hpp" 00002 #include <boost/assert.hpp> 00003 #include <stdarg.h> 00004 #include <string.h> 00005 #include <malloc.h> 00006 #include <unistd.h> 00007 00008 bool Tracer::continuation = false; 00009 bool Tracer::enable = false; ///< call Tracer::Enable(true) to begin tracing 00010 string Tracer::Descend::pre; 00011 string Tracer::Descend::last_traced_pre, Tracer::Descend::leftmost_pre; 00012 00013 void Tracer::Descend::Indent() 00014 { 00015 // Detect cases where the indent level dropped and then went up again, without 00016 // any actual traces at the lower indent level. Put a "<" in at the level it 00017 // dropped to. 00018 if( leftmost_pre.size() < last_traced_pre.size() && leftmost_pre.size() < pre.size() ) 00019 fprintf(stderr, "%s<\n", leftmost_pre.c_str()); 00020 last_traced_pre = leftmost_pre = pre; 00021 fprintf(stderr, "%s", pre.c_str()); 00022 } 00023 00024 inline void InfernoAbort() 00025 { 00026 fflush( stderr ); 00027 00028 // The C library provides abort(), but I'm not getting a stack dump under cygwin 00029 (*(int*)-1)++; 00030 } 00031 00032 Tracer::Tracer( const char *f, int l, const char *fu, Flags fl, char const *c ) : 00033 file( f ), 00034 line( l ), 00035 function( fu ), 00036 flags( fl ) 00037 { 00038 // If we're going to abort, get this out first, then usual trace message if required as a continuation 00039 if( flags & ABORT ) 00040 { 00041 EndContinuation(); 00042 fprintf( stderr, "\n"); 00043 Descend::Indent(); 00044 fprintf( stderr, "----Assertion failed: %s\n", c); 00045 Descend::Indent(); 00046 fprintf( stderr, "----%s:%d in %s()\n", file, line, function); 00047 continuation = true; 00048 } 00049 } 00050 00051 Tracer::~Tracer() 00052 { 00053 if( flags & ABORT ) 00054 { 00055 EndContinuation(); 00056 InfernoAbort(); 00057 } 00058 } 00059 00060 Tracer &Tracer::operator()() 00061 { 00062 if( (flags & DISABLE) || !(enable || (flags & FORCE)) ) 00063 return *this; 00064 00065 EndContinuation(); 00066 Descend::Indent(); 00067 fprintf( stderr, "----%s:%d in %s()\n", file, line, function); 00068 00069 return *this; 00070 } 00071 00072 Tracer &Tracer::operator()(const char *fmt, ...) 00073 { 00074 if( (flags & DISABLE) || !(enable || (flags & FORCE)) ) 00075 return *this; 00076 00077 va_list vl; 00078 va_start( vl, fmt ); 00079 if( !continuation ) 00080 { 00081 Descend::Indent(); 00082 fprintf( stderr, "----%s:%d in %s()\n", file, line, function); 00083 Descend::Indent(); 00084 } 00085 vfprintf( stderr, fmt, vl ); 00086 va_end( vl ); 00087 00088 continuation = (fmt[strlen(fmt)-1]!='\n'); 00089 return *this; 00090 } 00091 00092 Tracer &Tracer::operator()(const string &s) 00093 { 00094 return operator()("%s", s.c_str()); 00095 } 00096 00097 void Tracer::EndContinuation() 00098 { 00099 if( continuation ) 00100 { 00101 fprintf(stderr, "\n"); 00102 continuation = false; 00103 } 00104 } 00105 00106 void Tracer::Enable( bool e ) 00107 { 00108 enable = e; 00109 } 00110 00111 00112 // Make BOOST_ASSERT work (we don't use them but other code might) 00113 void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) 00114 { 00115 Tracer::EndContinuation(); 00116 Tracer( file, line, function, Tracer::FORCE )( "Assertion failed: %s\n\n", expr ); 00117 InfernoAbort(); 00118 } 00119 00120