Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

xtl_trace.h

Go to the documentation of this file.
00001 
00002 // Common Text Transformation Library
00003 // Copyright (C) 1997-2006 by Igor Kholodov. 
00004 //
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the
00017 // Free Software Foundation, Inc.,
00018 // 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 //
00020 // mailto:cttl@users.sourceforge.net
00021 // http://sourceforge.net/projects/cttl/
00023 
00042 // xtl_trace.h
00043 
00044 #ifndef _CTTL_XTL_TRACE_H_INCLUDED_
00045 #define _CTTL_XTL_TRACE_H_INCLUDED_
00046 
00047 #include <iostream>
00048 #include <string>
00049 
00050 #define CTTL_QUOTED_EXPRESSION_HELPER( x ) #x
00051 #define CTTL_QUOTED_EXPRESSION( x ) CTTL_QUOTED_EXPRESSION_HELPER( x )
00052 // usage:
00053 // std::cout << CTTL_QUOTED_EXPRESSION( __LINE__ )
00054 
00055 #define CTTL_TRACE_VARIABLE_2( xprefix, xsuffix ) xprefix ## xsuffix
00056 #define CTTL_TRACE_VARIABLE_1( xprefix, xsuffix ) CTTL_TRACE_VARIABLE_2( xprefix, xsuffix )
00057 #define CTTL_TRACE_VARIABLE( xprefix ) CTTL_TRACE_VARIABLE_1( xprefix, __LINE__ )
00058 
00059 
00060 #ifdef CTTL_TRACE_EVERYTHING
00061 
00062 #   ifdef CTTL_TRACE_EXPRESSION_TYPEID
00063 #       define CTTL_TRACE_TYPEID( p ) ( typeid( *p ).name() )
00064 #   else
00065 #       ifdef CTTL_TRACE_EXPRESSION_IMPL
00066 #           define CTTL_TRACE_TYPEID( p ) __FILE__ ";" CTTL_QUOTED_EXPRESSION( __LINE__ )
00067 #       else
00068 #           define CTTL_TRACE_TYPEID( p ) ""
00069 #       endif // CTTL_TRACE_EXPRESSION_IMPL
00070 #   endif // CTTL_TRACE_EXPRESSION_TYPEID
00071 
00072 #   define CTTL_TRACE_LEVEL_MATCH( xchar ) xtl_trace_grammar tlv( CTTL_TRACE_TYPEID( this ), edge_, xchar, xtl_trace_grammar::trace_grammar_mode_match )
00073 #   define CTTL_TRACE_LEVEL_FIND( xchar ) xtl_trace_grammar tlv( CTTL_TRACE_TYPEID( this ), edge_, xchar, xtl_trace_grammar::trace_grammar_mode_find )
00074 #   define CTTL_TRACE_LEVEL_BANG( xchar ) xtl_trace_grammar tlv( CTTL_TRACE_TYPEID( this ), edge_, xchar, xtl_trace_grammar::trace_grammar_mode_bang )
00075 
00076 #   define CTTL_TRACE_STATIC_LEVEL_MATCH( xchar, callbackid ) xtl_trace_grammar tlv( callbackid, edge_, xchar, xtl_trace_grammar::trace_grammar_mode_match )
00077 #   define CTTL_TRACE_STATIC_LEVEL_FIND( xchar, callbackid ) xtl_trace_grammar tlv( callbackid, edge_, xchar, xtl_trace_grammar::trace_grammar_mode_find )
00078 #   define CTTL_TRACE_STATIC_LEVEL_BANG( xchar, callbackid ) xtl_trace_grammar tlv( callbackid, edge_, xchar, xtl_trace_grammar::trace_grammar_mode_bang )
00079 
00080 #   define CTTL_TRACE_RESULT( RESULT_, xchar ) xtl_trace_grammar::trace_fragment< RESULT_ >( CTTL_TRACE_TYPEID( this ), edge_, xchar, NULL, -1 )
00081 #   define CTTL_TRACE_STATIC_RESULT( RESULT_, xchar, xtext ) xtl_trace_grammar::trace_fragment< RESULT_ >( xtext, edge_, xchar, NULL, -1 )
00082 
00083 #   define CTTL_TRACE_EDGE_RESULT_TRUE( xchar ) xtl_trace_grammar::trace_edge< true >( CTTL_TRACE_TYPEID( this ), m_edge, xchar, NULL )
00084 #   define CTTL_TRACE_NODE_RESULT_TRUE( xchar, xedge ) xtl_trace_grammar::trace_edge< true >( CTTL_TRACE_TYPEID( this ), xedge, xchar, NULL )
00085 
00086 #   define CTTL_TRACE_EDGE_RESULT_FALSE( xchar, xidentity )  xtl_trace_grammar::trace_fragment< false >( CTTL_TRACE_TYPEID( this ), edge_, xchar, NULL, xidentity )
00087 #   define CTTL_TRACE_NODE_RESULT_FALSE( xchar, xidentity )  CTTL_TRACE_EDGE_RESULT_FALSE( xchar, xidentity )
00088 
00089 #   define CTTL_TRACE_TEXT_RESULT( RESULT_, xchar, xtext ) xtl_trace_grammar::trace_fragment< RESULT_ >( CTTL_TRACE_TYPEID( this ), edge_, xchar, xtext, -1 )
00090 #   define CTTL_TRACE_TEXT( xchar, xtext ) xtl_trace_grammar::trace_fragment< true >( xtext, edge_, xchar, NULL, -1 )
00091 #   define CTTL_TRACE_MESSAGE( xtext ) xtl_trace_grammar::trace_message( xtext )
00092 #   define CTTL_TRACE_JUSTIFY() xtl_trace_grammar::trace_justify()
00093 #   define CTTL_RULE( xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), *this, &xrule )
00094 #   define CTTL_MEMBER_RULE( xobject, xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), xobject, xrule )
00095 #   define CTTL_STATIC_RULE( xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), xrule )
00096 #   define CTTL_TRACE_SILENT( xbool )     xtl_trace_silencer< xbool > CTTL_TRACE_VARIABLE( xtl_trace_silencer_ ); if ( sizeof( CTTL_TRACE_VARIABLE( xtl_trace_silencer_ ) ) ){}
00097 
00098 #else
00099 
00100 #   define CTTL_TRACE_TYPEID( p )
00101 
00102 #   define CTTL_TRACE_LEVEL_MATCH( xchar )
00103 #   define CTTL_TRACE_LEVEL_FIND( xchar )
00104 #   define CTTL_TRACE_LEVEL_BANG( xchar )
00105 
00106 #   define CTTL_TRACE_STATIC_LEVEL_MATCH( xchar, callbackid )
00107 #   define CTTL_TRACE_STATIC_LEVEL_FIND( xchar, callbackid )
00108 #   define CTTL_TRACE_STATIC_LEVEL_BANG( xchar, callbackid )
00109 
00110 #   define CTTL_TRACE_RESULT( RESULT_, xchar )
00111 #   define CTTL_TRACE_STATIC_RESULT( RESULT_, xchar, xtext )
00112 #   define CTTL_TRACE_EDGE_RESULT_TRUE( xchar )
00113 #   define CTTL_TRACE_NODE_RESULT_TRUE( xchar, xedge )
00114 #   define CTTL_TRACE_EDGE_RESULT_FALSE( xchar, xidentity ) 
00115 #   define CTTL_TRACE_NODE_RESULT_FALSE( xchar, xidentity )
00116 #   define CTTL_TRACE_TEXT_RESULT( RESULT_, xchar, xtext )
00117 #   define CTTL_TRACE_TEXT( xchar, xtext )
00118 #   define CTTL_TRACE_JUSTIFY()
00119 #   ifdef CTTL_TRACE_RULES
00120 #       define CTTL_TRACE_MESSAGE( xtext ) xtl_trace_grammar::trace_message( xtext )
00121 #       define CTTL_RULE( xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), *this, &xrule )
00122 #       define CTTL_MEMBER_RULE( xobject, xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), xobject, xrule )
00123 #       define CTTL_STATIC_RULE( xrule ) xtl_traced_rule( __LINE__, CTTL_QUOTED_EXPRESSION( xrule ), xrule )
00124 #       define CTTL_TRACE_SILENT( xbool )     xtl_trace_silencer< xbool > CTTL_TRACE_VARIABLE( xtl_trace_silencer_ ); if ( sizeof( CTTL_TRACE_VARIABLE( xtl_trace_silencer_ ) ) ){}
00125 #   else
00126 #       ifdef CTTL_TRACE_TRIVIAL
00127 #           define CTTL_TRACE_MESSAGE( xtext ) xtl_trace_grammar::trace_message( xtext )
00128 #       else
00129 #           define CTTL_TRACE_MESSAGE( xtext )
00130 #       endif // CTTL_TRACE_TRIVIAL
00131 #       define CTTL_RULE( xrule ) rule( *this, &xrule )
00132 #       define CTTL_MEMBER_RULE( xobject, xrule ) rule( xobject, xrule )
00133 #       define CTTL_STATIC_RULE( xrule ) rule( xrule )
00134 #       define CTTL_TRACE_SILENT( xbool )
00135 #   endif // CTTL_TRACE_RULES
00136 
00137 #endif // CTTL_TRACE_EVERYTHING
00138 
00139 
00140 namespace cttl_impl {
00141 
00142 struct xtl_trace_grammar {
00143 
00144     static const size_t fragment_length = 25;
00145 
00146     enum trace_grammar_mode {
00147         trace_grammar_mode_match,
00148         trace_grammar_mode_find,
00149         trace_grammar_mode_bang
00150     };
00151 
00152     template< typename EdgeT >
00153     xtl_trace_grammar( CTTL_STD_CHAR const* object_name_, EdgeT const& edge_, CTTL_STD_CHAR char_, trace_grammar_mode mode_ )
00154     {
00155         std::cout
00156             << exact_edge2text( edge_, true ).c_str()
00157             << '?'
00158             ;
00159 
00160         build_skyline();
00161 
00162         std::cout
00163             << '{'
00164             << char_
00165             << ( mode_ == trace_grammar_mode_match ? "" : ( mode_ == trace_grammar_mode_find ? "!" : "!!" ) )
00166             << "\t\t"
00167             << edge_.first.offset()
00168             << '-'
00169             << edge_.second.offset()
00170 //          << edge_.first.line()
00171             << '\t'
00172             << object_name_
00173             << std::endl
00174             ;
00175 
00176         depth( 1 );
00177     }
00178 
00179     template< typename EdgeT >
00180     xtl_trace_grammar( int object_callback_id_, EdgeT const& edge_, CTTL_STD_CHAR char_, trace_grammar_mode mode_ )
00181     {
00182         std::cout
00183             << exact_edge2text( edge_, true )
00184             << '?'
00185             ;
00186 
00187         build_skyline();
00188 
00189         std::cout
00190             << '{'
00191             << char_
00192             << object_callback_id_
00193             << ( mode_ == trace_grammar_mode_match ? "" : ( mode_ == trace_grammar_mode_find ? "!" : "!!" ) )
00194             << "\t\t"
00195             << edge_.first.offset()
00196             << '-'
00197             << edge_.second.offset()
00198 //          << edge_.first.line()
00199             << std::endl
00200             ;
00201 
00202         depth( 1 );
00203     }
00204 
00205     ~xtl_trace_grammar()
00206     {
00207         depth( -1 );
00208         trace_message( "}" );
00209     }
00210 
00211     static int depth( int change_ )
00212     {
00213         static int depth_ = 0;
00214         depth_ += change_;
00215         return depth_;
00216     }
00217 
00218     template< typename EdgeT >
00219     static typename EdgeT::string_T edge2text( EdgeT const& edge_, bool result_ )
00220     {
00221         // show text located in front of the specified edge_
00222         std::string text_extract;
00223 
00224         if ( edge_.length() < 0 ) {
00225             text_extract = "***INVALID***";
00226             padtext( text_extract, result_ );
00227             return text_extract;
00228         }
00229 
00230         size_t end_offset = edge_.first.offset();
00231         int begin_offset = end_offset - fragment_length + 1;    // +1 accounts for the '@' added at the end
00232         if ( begin_offset < 0 )
00233             begin_offset = 0;
00234         text_extract = edge_.parent().container().text_absolute_substring( begin_offset, end_offset ).c_str();
00235         text_extract += '@';
00236 
00237         padtext( text_extract, result_ );
00238         return text_extract;
00239     }
00240 
00241     template< typename EdgeT >
00242     static typename EdgeT::string_T exact_edge2text( EdgeT const& edge_, bool result_ )
00243     {
00244         // show text at the beginning of the fragment
00245 
00246         std::string text_extract;
00247 
00248         if ( edge_.length() < 0 ) {
00249             text_extract = "***INVALID***";
00250             padtext( text_extract, result_ );
00251             return text_extract;
00252         }
00253 
00254         size_t begin_offset = edge_.first.offset();
00255         size_t end_offset = edge_.second.offset();
00256         if ( ( end_offset - begin_offset ) > fragment_length - 1 )
00257             end_offset = begin_offset + fragment_length - 1;    // -1 accounts for the '@' added in front.
00258 
00259         text_extract = '@';
00260         text_extract += edge_.parent().container().text_absolute_substring( begin_offset, end_offset ).c_str();
00261 
00262         padtext( text_extract, result_ );
00263         return text_extract;
00264     }
00265 
00266     static std::string& whitespace2monospace( std::string& text_extract_ )
00267     {
00268         std::string::size_type pos = text_extract_.length();
00269         while ( pos )
00270             if ( text_extract_[ --pos ] < ' ' )
00271                 text_extract_[ pos ] = '.';
00272 
00273         return text_extract_;
00274     }
00275 
00276     static void padtext( std::string& text_extract_, bool result_  )
00277     {
00278         whitespace2monospace( text_extract_ );
00279 
00280         if ( text_extract_.length() < fragment_length )
00281             if ( result_ )
00282                 for ( size_t pad = 0; pad < fragment_length - text_extract_.length(); ++ pad )
00283                     std::cout << '-';
00284 
00285             else
00286                 for ( size_t pad = 0; pad < fragment_length - text_extract_.length(); ++ pad )
00287                     std::cout << '~';
00288         
00289     }
00290 
00291     static void output_monospace_text( CTTL_STD_CHAR const* text_ )
00292     {
00293         while( *text_ ) {
00294             std::cout << ( isprint( *text_ ) ? *text_ : '.' );
00295             text_++;
00296         }       
00297     }
00298 
00299     template< bool result_, typename EdgeT >
00300     static void trace_fragment( CTTL_STD_CHAR const* object_name_, EdgeT const& edge_, CTTL_STD_CHAR char_, CTTL_STD_CHAR const* text_, int identity_ )
00301     {
00302         // please note that text_ can be NULL;
00303         // identity_ can be minus one
00304         std::cout
00305             << edge2text( edge_, result_ ).c_str()
00306             << ( result_ ? '|' : '~' )
00307             ;
00308 
00309         build_skyline();
00310 
00311         std::cout
00312             << char_;
00313 
00314         if ( identity_ != -1 )
00315             std::cout << identity_;
00316 
00317         std::cout
00318             << '\t'
00319             << '\t'
00320             << edge_.first.offset()
00321             << '-'
00322             << edge_.second.offset()
00323 //          << edge_.first.line()
00324             << '\t'
00325             << ( result_ ? "" : "FAIL " )
00326             ;
00327         if ( text_ )
00328             output_monospace_text( text_ );
00329         else
00330             std::cout << object_name_;
00331 
00332         std::cout << std::endl;
00333     }
00334 
00335     template< bool result_, typename EdgeT >
00336     static void trace_edge( CTTL_STD_CHAR const* object_name_, EdgeT const& edge_, CTTL_STD_CHAR char_, CTTL_STD_CHAR const* text_ )
00337     {
00338         // please note that text_ can be NULL
00339         std::cout
00340             << exact_edge2text( edge_, result_ ).c_str()
00341             << ( result_ ? '|' : '~' )
00342             ;
00343 
00344         build_skyline();
00345 
00346         std::cout
00347             << char_
00348             << edge_.first.identity()
00349             << "\t\t"
00350             << edge_.first.offset()
00351             << '-'
00352             << edge_.second.offset()
00353 //          << edge_.first.line()
00354             << '\t'
00355             ;
00356         if ( text_ )
00357             output_monospace_text( text_ );
00358         else
00359             std::cout << object_name_;
00360 
00361         std::cout << std::endl;
00362     }
00363 
00364     static void trace_message( CTTL_STD_CHAR const* text_ )
00365     {
00366         trace_justify();
00367         std::cout << text_ << std::endl;
00368     }
00369 
00370     static void trace_message( std::string const& text_ )
00371     {
00372         trace_justify();
00373         std::cout << text_ << std::endl;
00374     }
00375 
00376     static void trace_justify( CTTL_STD_CHAR pad_char_ = ' ' )
00377     {
00378         for ( size_t pad = 0; pad <= fragment_length; ++pad )
00379             std::cout << pad_char_;
00380 
00381         build_skyline( pad_char_ );
00382     }
00383 
00384     static void build_skyline( CTTL_STD_CHAR pad_char_ = ' ' )
00385     {
00386         for ( int dp = 0; dp < depth( 0 ); ++dp )
00387             std::cout << pad_char_;
00388     }
00389 
00390 };  // struct xtl_trace_grammar
00391 
00392 template< bool MakeSilentT >
00393 struct xtl_trace_silencer {
00394     xtl_trace_silencer()
00395         :
00396     m_badbit( ( std::cout.rdstate() & std::ios_base::badbit ) != 0 )
00397     {
00398         if ( !m_badbit ) {
00399             // silence output
00400             std::cout.flush();
00401             std::cout.setstate( std::ios_base::badbit );
00402         }
00403     }
00404     ~xtl_trace_silencer()
00405     {
00406         if ( !m_badbit ) {
00407             // vocalize output
00408             std::cout.clear();
00409         }
00410     }
00411 private:
00412     // records original badbit state of the environment
00413     bool m_badbit;
00414 
00415 };  // struct xtl_trace_silencer
00416 
00417 // full specializaton for 
00418 template<>
00419 struct xtl_trace_silencer< false > {
00420     xtl_trace_silencer()
00421         :
00422     m_badbit( ( std::cout.rdstate() & std::ios_base::badbit ) != 0 )
00423     {
00424         if ( m_badbit ) {
00425             // vocalize output
00426             std::cout.clear();
00427         }
00428     }
00429     ~xtl_trace_silencer()
00430     {
00431         if ( m_badbit ) {
00432             // silence output
00433             std::cout.flush();
00434             std::cout.setstate( std::ios_base::badbit );
00435         }
00436     }
00437 private:
00438     // records original badbit state of the environment
00439     bool m_badbit;
00440 
00441 };  // struct xtl_trace_silencer
00442 
00443 }   // namespace cttl_impl
00444 
00445 
00446 #endif // _CTTL_XTL_TRACE_H_INCLUDED_

Generated on Thu Nov 2 17:44:08 2006 for Common Text Transformation Library by  doxygen 1.3.9.1