TraceFct.cc

00001 // --8<--8<--8<--8<--
00002 //
00003 // Copyright (C) 2006 Smithsonian Astrophysical Observatory
00004 //
00005 // This file is part of tracefctxx
00006 //
00007 // tracefctxx is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2
00010 // of the License, or (at your option) any later version.
00011 //
00012 // tracefctxx is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the 
00019 //       Free Software Foundation, Inc. 
00020 //       51 Franklin Street, Fifth Floor
00021 //       Boston, MA  02110-1301, USA
00022 //
00023 // -->8-->8-->8-->8--
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   // if the function stack is empty, we must be at the top level;
00141   // nothing to do.
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     // close the output stream
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 // doxygen braindamage; can't pull inlines from header file into
00343 // a member group
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 // doxygen braindamage; can't pull inlines from header file into a member group
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 // doxygen braindamage; can't pull inlines from header file into
00492 // a member group
00513 void
00514 TraceFct::message
00515 (
00516   const char *format,           /* a printf style string */
00517   ...                   /* objects to print */
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          /* objects to print */
00546 )
00547 {
00548   vprint( false, format, args );
00549 }
00550 
00551 
00552 // doxygen braindamage; can't pull inlines from header file into
00553 // a member group
00572 
00573 //====================================================================//
00574 
00575 
00579 
00597 void
00598 TraceFct::open(
00599   const string& file    /* the file to which messages are to be written */
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       // dunno what happend but it wasn't good!
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 //====================================================================//

Generated on Mon Oct 20 13:55:17 2008 for tracefctxx by  doxygen 1.5.6