00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <iostream>
00023 #include <fstream>
00024 #include <cstring>
00025 #include <unistd.h>
00026 using namespace std;
00027
00028 #include "TraceFct.h"
00029
00030 #define NUM_BLANK_SPACES " "
00031
00032 bool TraceFct::print_upon_enter_and_exit(false);
00033 int TraceFct::stack_level_to_print(-1);
00034 string TraceFct::progname("UNKNOWN PROGRAM");
00035 string TraceFct::prefix = TraceFct::init_prefix();
00036 char TraceFct::outbuf[8192];
00037 ostream* TraceFct::ostr = &cerr;
00038 list<string> TraceFct::function_stack;
00039
00040 char *
00041 TraceFct::init_prefix( void )
00042 {
00043 sprintf(outbuf, "# %d: %s: ", getpid(), progname.c_str() );
00044 return outbuf;
00045 }
00046
00047
00048
00049
00051
00077 TraceFct::TraceFct( string prog_name, bool print_it, int num_fct_to_print )
00078 {
00079
00080 progname = prog_name;
00081
00082 print_upon_enter_and_exit = print_it;
00083
00084 stack_level_to_print = num_fct_to_print;
00085
00086 function_stack.clear();
00087
00088 ostr = &cerr;
00089
00090 prefix = init_prefix( );
00091 }
00092
00094
00103 TraceFct::TraceFct(string& name)
00104 {
00105 function_stack.push_back( name );
00106
00107 if (print_upon_enter_and_exit)
00108 message( "[%2d] %s: entering\n", function_stack.size(),
00109 function_stack.back().c_str() );
00110 }
00111
00119 TraceFct::TraceFct(const char* name)
00120 {
00121 function_stack.push_back( name );
00122
00123 if (print_upon_enter_and_exit)
00124 message( "[%2d] %s: entering\n", function_stack.size(),
00125 function_stack.back().c_str() );
00126 }
00127
00129
00135 TraceFct::~TraceFct( )
00136 {
00137
00138
00139 if ( ! function_stack.empty() )
00140 {
00141 if (print_upon_enter_and_exit)
00142 {
00143 message( "[%2d] %s: leaving\n", function_stack.size(),
00144 function_stack.back().c_str() );
00145 }
00146
00147 function_stack.pop_back();
00148 }
00149
00150 else
00151 {
00152
00153 if ( &cerr != ostr )
00154 delete ostr;
00155 }
00156 }
00157
00158
00159
00160
00176 void
00177 TraceFct::vprint(
00178 bool print_nl,
00179 const char *format,
00180 va_list args
00181 )
00182 {
00183 char *start, *end;
00184
00185 vsprintf(outbuf, format, args);
00186
00187
00188
00189 (*ostr).seekp(0, std::ios::end);
00190 if ( (*ostr).fail() )
00191 (*ostr).clear( (*ostr).rdstate() & ~std::ios::failbit );
00192
00193 for ( start = outbuf ; end = strchr( start, '\n' ) ; start = end )
00194 {
00195 char save;
00196 save = *++end;
00197 *end = '\0';
00198
00199 if ( ostr == &cerr )
00200 *ostr << prefix;
00201
00202 *ostr << start;
00203
00204 *end = save;
00205 }
00206
00207 if ( *start )
00208 {
00209 if ( ostr == &cerr )
00210 *ostr << prefix;
00211
00212 *ostr << start;
00213 }
00214
00215 if ( print_nl && '\n' != outbuf[strlen(outbuf)-1] )
00216 *ostr << '\n';
00217
00218 (*ostr).flush();
00219
00220 }
00221
00222
00232 void
00233 TraceFct::print(
00234 bool print_nl,
00235 const char *format,
00236 ...
00237 )
00238 {
00239 va_list args;
00240 va_start( args, format );
00241 vprint( print_nl, format, args );
00242 va_end(args );
00243 }
00244
00254 void
00255 TraceFct::print(
00256 bool print_nl,
00257 Exception& ex
00258 )
00259 {
00260 deque<string>::const_iterator begin = ex.begin();
00261 deque<string>::const_iterator end = ex.end();
00262
00263 while( begin != end )
00264 print( print_nl, (*begin++).c_str() );
00265 }
00266
00267
00268
00269
00277 void
00278 TraceFct::dump_stack()
00279 {
00280
00281 message( "Stack:\n" );
00282
00283 unsigned max_level = stack_level_to_print > -1 ?
00284 stack_level_to_print : function_stack.size();
00285
00286 if ( function_stack.size() < max_level )
00287 max_level = function_stack.size();
00288
00289 list<string>::iterator begin = function_stack.begin();
00290 list<string>::iterator end = function_stack.end();
00291 advance( begin, function_stack.size() - max_level );
00292
00293 int depth = function_stack.size();
00294 while( begin != end )
00295 {
00296 end--;
00297 message( " [%2d] %s\n", depth, end->c_str() );
00298 depth--;
00299 }
00300
00301 if ( stack_level_to_print == -1 ||
00302 max_level > function_stack.size() )
00303 message( " [ 0] <TOP>\n");
00304 }
00305
00306
00307
00308
00319 void
00320 TraceFct::vexit_print(
00321 const char *format,
00322 va_list args
00323 )
00324 {
00325 vprint( true, format, args );
00326
00327 dump_stack( );
00328 }
00329
00330
00331
00332
00333
00347
00348
00349
00365 void
00366 TraceFct::exit
00367 (
00368 int exit_code,
00369 const char *format,
00370 ...
00371 )
00372 {
00373 va_list args;
00374
00375 if ( ostr != &cerr )
00376 {
00377 va_start(args, format);
00378 vexit_print( format, args );
00379 va_end(args);
00380 delete ostr;
00381 }
00382
00383 ostr = &cerr;
00384
00385 va_start(args, format);
00386 vexit_print( format, args );
00387 va_end(args);
00388
00389 std::exit(exit_code);
00390 }
00391
00402 void
00403 TraceFct::exit
00404 (
00405 int exit_code,
00406 Exception& ex
00407 )
00408 {
00409 deque<string>::const_iterator begin = ex.begin();
00410 deque<string>::const_iterator end = ex.end();
00411
00412 if ( ostr != &cerr ){
00413 print( true, ex );
00414 delete ostr;
00415 }
00416
00417 ostr = &cerr;
00418
00419 print( true, ex );
00420
00421 dump_stack();
00422 std::exit(exit_code);
00423
00424 }
00425
00426
00450 void
00451 TraceFct::die
00452 (
00453 const char *format,
00454 ...
00455 )
00456 {
00457 va_list args;
00458
00459 if ( ostr != &cerr )
00460 {
00461 va_start(args, format);
00462 vexit_print( format, args );
00463 va_end(args);
00464 delete ostr;
00465 }
00466
00467 ostr = &cerr;
00468
00469 va_start(args, format);
00470 vexit_print( format, args );
00471 va_end(args);
00472
00473 std::exit(EXIT_FAILURE);
00474 }
00475
00476
00478
00479
00480
00496
00497
00498
00519 void
00520 TraceFct::message
00521 (
00522 const char *format,
00523 ...
00524 )
00525 {
00526 va_list args;
00527
00528 va_start(args, format);
00529
00530 vprint( false, format, args );
00531
00532 va_end(args);
00533 }
00534
00535
00547 void
00548 TraceFct::vmessage
00549 (
00550 const char *format,
00551 va_list args
00552 )
00553 {
00554 vprint( false, format, args );
00555 }
00556
00557
00558
00559
00578
00579
00580
00581
00585
00603 void
00604 TraceFct::open(
00605 const string& file
00606 )
00607 {
00608 ostream* new_ostr;
00609
00610 if ( file != "stderr" )
00611 {
00612 try
00613 {
00614 new_ostr = new ofstream( file.c_str() );
00615
00616 if ( ! *new_ostr )
00617 {
00618 cerr << prefix << "unable to open TraceFct output stream `"
00619 << file << '\'' << endl;
00620 std::exit(1);
00621 }
00622 }
00623 catch (...)
00624 {
00625
00626 cerr << prefix
00627 << "error creating TraceFct output stream object for `"
00628 << file << '\'' << endl;
00629 std::exit(1);
00630 }
00631
00632 }
00633 else
00634 new_ostr = &cerr;
00635
00636 if ( ostr != &cerr )
00637 delete ostr;
00638
00639 ostr = new_ostr;
00640 }
00641
00651 void
00652 TraceFct::close( void )
00653 {
00654 if ( &cerr != ostr )
00655 {
00656 delete ostr;
00657 ostr = &cerr;
00658 }
00659 }
00660
00661
00663
00664