00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <iostream>
00026 #include <fstream>
00027 #include <cstring>
00028 #include <unistd.h>
00029 using namespace std;
00030
00031 #include "TraceFct.h"
00032
00033 #define NUM_BLANK_SPACES " "
00034
00035 bool TraceFct::print_upon_enter_and_exit(false);
00036 int TraceFct::stack_level_to_print(-1);
00037 string TraceFct::progname("UNKNOWN PROGRAM");
00038 string TraceFct::prefix = TraceFct::init_prefix();
00039 char TraceFct::outbuf[8192];
00040 ostream* TraceFct::ostr = &cerr;
00041 list<string> TraceFct::function_stack;
00042
00043 char *
00044 TraceFct::init_prefix( void )
00045 {
00046 sprintf(outbuf, "# %d: %s: ", getpid(), progname.c_str() );
00047 return outbuf;
00048 }
00049
00050
00051
00052
00054
00080 TraceFct::TraceFct( string prog_name, bool print_it, int num_fct_to_print )
00081 {
00082
00083 progname = prog_name;
00084
00085 print_upon_enter_and_exit = print_it;
00086
00087 stack_level_to_print = num_fct_to_print;
00088
00089 function_stack.clear();
00090
00091 ostr = &cerr;
00092
00093 prefix = init_prefix( );
00094 }
00095
00097
00106 TraceFct::TraceFct(string& name)
00107 {
00108 function_stack.push_back( name );
00109
00110 if (print_upon_enter_and_exit)
00111 message( "[%2d] %s: entering\n", function_stack.size(),
00112 function_stack.back().c_str() );
00113 }
00114
00122 TraceFct::TraceFct(const char* name)
00123 {
00124 function_stack.push_back( name );
00125
00126 if (print_upon_enter_and_exit)
00127 message( "[%2d] %s: entering\n", function_stack.size(),
00128 function_stack.back().c_str() );
00129 }
00130
00132
00138 TraceFct::~TraceFct( )
00139 {
00140
00141
00142 if ( ! function_stack.empty() )
00143 {
00144 if (print_upon_enter_and_exit)
00145 {
00146 message( "[%2d] %s: leaving\n", function_stack.size(),
00147 function_stack.back().c_str() );
00148 }
00149
00150 function_stack.pop_back();
00151 }
00152
00153 else
00154 {
00155
00156 if ( &cerr != ostr )
00157 delete ostr;
00158 }
00159 }
00160
00161
00162
00163
00179 void
00180 TraceFct::vprint(
00181 bool print_nl,
00182 const char *format,
00183 va_list args
00184 )
00185 {
00186 char *start, *end;
00187
00188 vsprintf(outbuf, format, args);
00189
00190 for ( start = outbuf ; end = strchr( start, '\n' ) ; start = end )
00191 {
00192 char save;
00193 save = *++end;
00194 *end = '\0';
00195
00196 if ( ostr == &cerr )
00197 *ostr << prefix;
00198
00199 *ostr << start;
00200
00201 *end = save;
00202 }
00203
00204 if ( *start )
00205 {
00206 if ( ostr == &cerr )
00207 *ostr << prefix;
00208
00209 *ostr << start;
00210 }
00211
00212 if ( print_nl && '\n' != outbuf[strlen(outbuf)-1] )
00213 *ostr << '\n';
00214 }
00215
00216
00226 void
00227 TraceFct::print(
00228 bool print_nl,
00229 const char *format,
00230 ...
00231 )
00232 {
00233 va_list args;
00234 va_start( args, format );
00235 vprint( print_nl, format, args );
00236 va_end(args );
00237 }
00238
00248 void
00249 TraceFct::print(
00250 bool print_nl,
00251 Exception& ex
00252 )
00253 {
00254 deque<string>::const_iterator begin = ex.begin();
00255 deque<string>::const_iterator end = ex.end();
00256
00257 while( begin != end )
00258 print( print_nl, (*begin++).c_str() );
00259 }
00260
00261
00262
00263
00271 void
00272 TraceFct::dump_stack()
00273 {
00274
00275 message( "Stack:\n" );
00276
00277 unsigned max_level = stack_level_to_print > -1 ?
00278 stack_level_to_print : function_stack.size();
00279
00280 if ( function_stack.size() < max_level )
00281 max_level = function_stack.size();
00282
00283 list<string>::iterator begin = function_stack.begin();
00284 list<string>::iterator end = function_stack.end();
00285 advance( begin, function_stack.size() - max_level );
00286
00287 int depth = function_stack.size();
00288 while( begin != end )
00289 {
00290 end--;
00291 message( " [%2d] %s\n", depth, end->c_str() );
00292 depth--;
00293 }
00294
00295 if ( stack_level_to_print == -1 ||
00296 max_level > function_stack.size() )
00297 message( " [ 0] <TOP>\n");
00298 }
00299
00300
00301
00302
00313 void
00314 TraceFct::vexit_print(
00315 const char *format,
00316 va_list args
00317 )
00318 {
00319 vprint( true, format, args );
00320
00321 dump_stack( );
00322 }
00323
00324
00325
00326
00327
00341
00342
00343
00359 void
00360 TraceFct::exit
00361 (
00362 int exit_code,
00363 const char *format,
00364 ...
00365 )
00366 {
00367 va_list args;
00368
00369 if ( ostr != &cerr )
00370 {
00371 va_start(args, format);
00372 vexit_print( format, args );
00373 va_end(args);
00374 delete ostr;
00375 }
00376
00377 ostr = &cerr;
00378
00379 va_start(args, format);
00380 vexit_print( format, args );
00381 va_end(args);
00382
00383 std::exit(exit_code);
00384 }
00385
00396 void
00397 TraceFct::exit
00398 (
00399 int exit_code,
00400 Exception& ex
00401 )
00402 {
00403 deque<string>::const_iterator begin = ex.begin();
00404 deque<string>::const_iterator end = ex.end();
00405
00406 if ( ostr != &cerr ){
00407 print( true, ex );
00408 delete ostr;
00409 }
00410
00411 ostr = &cerr;
00412
00413 print( true, ex );
00414
00415 dump_stack();
00416 std::exit(exit_code);
00417
00418 }
00419
00420
00444 void
00445 TraceFct::die
00446 (
00447 const char *format,
00448 ...
00449 )
00450 {
00451 va_list args;
00452
00453 if ( ostr != &cerr )
00454 {
00455 va_start(args, format);
00456 vexit_print( format, args );
00457 va_end(args);
00458 delete ostr;
00459 }
00460
00461 ostr = &cerr;
00462
00463 va_start(args, format);
00464 vexit_print( format, args );
00465 va_end(args);
00466
00467 std::exit(EXIT_FAILURE);
00468 }
00469
00470
00472
00473
00474
00490
00491
00492
00513 void
00514 TraceFct::message
00515 (
00516 const char *format,
00517 ...
00518 )
00519 {
00520 va_list args;
00521
00522 va_start(args, format);
00523
00524 vprint( false, format, args );
00525
00526 va_end(args);
00527 }
00528
00529
00541 void
00542 TraceFct::vmessage
00543 (
00544 const char *format,
00545 va_list args
00546 )
00547 {
00548 vprint( false, format, args );
00549 }
00550
00551
00552
00553
00572
00573
00574
00575
00579
00597 void
00598 TraceFct::open(
00599 const string& file
00600 )
00601 {
00602 ostream* new_ostr;
00603
00604 if ( file != "stderr" )
00605 {
00606 try
00607 {
00608 new_ostr = new ofstream( file.c_str() );
00609
00610 if ( ! *new_ostr )
00611 {
00612 cerr << prefix << "unable to open TraceFct output stream `"
00613 << file << '\'' << endl;
00614 std::exit(1);
00615 }
00616 }
00617 catch (...)
00618 {
00619
00620 cerr << prefix
00621 << "error creating TraceFct output stream object for `"
00622 << file << '\'' << endl;
00623 std::exit(1);
00624 }
00625
00626 }
00627 else
00628 new_ostr = &cerr;
00629
00630 if ( ostr != &cerr )
00631 delete ostr;
00632
00633 ostr = new_ostr;
00634 }
00635
00645 void
00646 TraceFct::close( void )
00647 {
00648 if ( &cerr != ostr )
00649 {
00650 delete ostr;
00651 ostr = &cerr;
00652 }
00653 }
00654
00655
00657
00658