Main Page | Class Hierarchy | Class List | Directories | File List | Class Members

doc.h

00001 //----------------------------------------------
00002 // traceString documentation static const char* myName = "Foo::Bar(int a)"; TRACER(t,myName,"Foo"); /* %TRACE% */
00072          // rest of routine
00073        }\endverbatim
00074 
00075     Here the idea is that TRACER is a developer supplied macro that,
00076     when turned on, will print the name of routine to aid debugging.
00077 
00078     A code instrumented by traceString can be re-instrumented repeatly.  In
00079     this way it can be used as development continues so that when 
00080     "int Foo::Bar(int a)" becomes  "int Foo::Bar(int* a)" the tool can
00081     make the changes to the variable "myName" rather than the developer.
00082 
00083     A developer has control over what traceString places in the source
00084     code via a pattern file.  This file describes how the function name
00085     should be expanded.  The above pattern was:
00086 
00087        \verbatim
00088        static const char* myName = "$(FQNAME)"; TRACER(t,myName,"$(CLASS)");
00089        \endverbatim
00090 
00091     Where "\$(FQNAME)" is the "fully qualified" name of the routine, that is
00092     the name of the routine and its arguments.  The name of the routine
00093     with out is arguements is available (\$(NAME): "Foo::bar") as well the
00094     class name ($(CLASS): "Foo").  If the pattern line was 
00095 
00096        \verbatim
00097        FUNC_TRACE("$(NAME)");
00098        \endverbatim
00099 
00100     then the expansion would be:
00101             
00102        \verbatim
00103        int Foo::bar(int a)
00104        { /* %TRACE% */ FUNC_TRACE("Foo::bar"); /* %TRACE% */
00105          // rest of routine
00106        }\endverbatim
00107 
00108     There can be more than one pattern line in the pattern file.  There is
00109     a default pattern and other named patterns.  So the pattern file might
00110     look like:
00111 
00112        \verbatim
00113        default: static const char* myName = "$(FQNAME)";TRACER(t,myName,"$(CLASS)");
00114        ifdef  : \n#ifdef DEBUG\nstatic const char* myName = "$(FQNAME)";\n#endif\n
00115        FT     : FUNC_TRACE("$(NAME)");
00116        FC     : FT_wClass("$(FQNAME)","$(CLASS)");
00117        None   :
00118        \endverbatim
00119 
00120     If the source code originally looked like this:
00121 
00122        \verbatim
00123        int Foo::bar(int a)
00124        {
00125          // rest of routine
00126        }
00127        int Foo::baz(double b)
00128        { /* %TRACE[FT]% */ /* %TRACE% */
00129          // rest of routine
00130        }
00131        int Foo::biz(string b)
00132        { /* %TRACE[FC]% */ /* %TRACE% */
00133          // rest of routine
00134        }
00135        int Foo::getSomething()
00136        { /* %TRACE[None]% */ /* %TRACE% */
00137          // rest of routine
00138        }
00139        int Foo::foo()
00140        { 
00141          /* %TRACE[ifdef]% */ /* %TRACE% */
00142          // rest of routine
00143        }
00144 
00145        \endverbatim
00146 
00147     It would be converted to this:
00148 
00149        \verbatim
00150        int Foo::bar(int a)
00151        { /* %TRACE% */ static const char* myName = "Foo::Bar(int a)"; TRACER(t,myName,"$(CLASS)"); /* %TRACE% */
00152          // rest of routine
00153        }
00154        int Foo::baz(double b)
00155        { /* %TRACE[FT]% */ FUNC_TRACE("Foo::baz"); /* %TRACE% */ 
00156          // rest of routine
00157        }
00158        int Foo::biz(string b)
00159        { /* %TRACE[FC]% */ FT_wCLASS("Foo::biz(string b)","Foo"); /* %TRACE% */
00160          // rest of routine
00161        }
00162        int Foo::getSomething()
00163        { /* %TRACE[None]% */ /* %TRACE% */
00164          // rest of routine
00165        }
00166        int Foo::foo()
00167        { 
00168          /* %TRACE[ifdef]% */ 
00169          #ifdef DEBUG
00170          static const char* myName = "Foo::foo()";
00171          #endif
00172          /* %TRACE% */
00173          // rest of routine
00174        }
00175        \endverbatim
00176 
00177     Thus, if there is no trace string already in the function, the default pattern is
00178     used.  A named pattern is specified with:
00179 
00180       \verbatim
00181       /* %TRACE[FT]% */ /* %TRACE% */
00182       \endverbatim
00183 
00184     where the string in the square brackets controls which pattern is
00185     used.  The "Foo::getSomething()" shows the use of the "None" pattern
00186     where no extra code was placed that function.
00187 
00188     traceString will also expand `\n' in the pattern file.  In this
00189     way a single line pattern can expand to multi-line code. In this
00190     way C-preprocessor directives like #ifdef can be used.
00191 
00192     The tool "traceString" is fast.  It is written in C++ and flex.  On a Pentium 4
00193     it converted  23000 lines of code in 61 files in 0.1 seconds.
00194     
00195 
00196     \subsection example Tracer Example
00197 
00198     This package also contains a tracer package to control tracing.
00199     Applications can freely include this if they choose to help will
00200     tracing the applications tracing program execution.
00201 
00202     "tracer" depends on C++ ability to have user code construct objects
00203     that are automatically deleted at their end of scope.  So we
00204     construct a tracer object at the beginning of a routine and at the
00205     end of the tracer object's lifetime the destructor is called and
00206     we print a message that we are leaving the routine.
00207 
00208     We may wish to have a finer control on which routines that print
00209     out.  There are four tests that must be true in order that a
00210     routine prints an entering/leaving message.  (ignoring watch
00211     lists, see watch list discussion that follows)
00212 
00213     a) The static member variable must be turned on.  Printing will only
00214        occur if it is true.
00215 
00216     b) The routine name must not be in the always_excluded list
00217 
00218     c) There is a routine list which is either an include or an
00219        exclude list.  To be printed the routine name must be on
00220        include list or not on the exclude list.  This list of routines
00221        can only be either an include list or an exclude list not both.
00222        If there is no list then this is ignored.
00223 
00224     d) There is a class list which is either an include or an
00225        exclude list.  To be printed the class name must be on
00226        include list or not on the exclude list.  This list of classes
00227        can only be either an include list or an exclude list not both.
00228        If there is no list then this is ignored.
00229 
00230 
00231     Watch list rules:  
00232 
00233     The purpose of the watch list to print out the call tree execution
00234     starting at watched routine.  That is a routine or class listed in
00235     a watch list will print out the routine and all routines called
00236     until the execution returns back to that routine.    To print
00237     following has to be true.
00238 
00239     a) Tracing must be turned on
00240 
00241     b) A routine or class must be on the appropriate watch list
00242        (FUNCTION_WATCH for functions and KLASS_WATCH for classes)
00243 
00244        OR
00245 
00246        called by a watched routine
00247 
00248     c) the regular class and function include/exclude lists are
00249        ignored.
00250 
00251     d) The always exclude list is obeyed.
00252 
00253       \verbatim
00254       \#include <iostream>
00255       \#include "tracer.h"
00256 
00257       void c(int i)
00258       {
00259         /* %TRACE% */ static const char* myName = "c(int i)";  TRACER(tr, myName,""); /* %TRACE% */
00260         std::cout << "In middle of c " << i << "\n";
00261       }
00262 
00263       void b(int i)
00264       {
00265         /* %TRACE% */ static const char* myName = "b(int i)";  TRACER(tr, myName,""); /* %TRACE% */ 
00266         std::cout << "In middle of b " << i << "\n";
00267         c(i+1);
00268       }
00269 
00270       void a(int i)
00271       {
00272         /* %TRACE% */ static const char* myName = "a(int i)";  TRACER(tr, myName,""); /* %TRACE% */ 
00273         std::cout << "In middle of a " << i << "\n";
00274         b(i+1);
00275       }
00276 
00277 
00278       int main()
00279       {
00280         /* %TRACE% */ static const char* myName = "main()";  TRACER(tr, myName,""); /* %TRACE% */ 
00281         NamesList nl;
00282 
00283         nl.push_back("e(int i)");
00284         nl.push_back("d(int i)");
00285         nl.push_back("c(int i)");
00286         nl.push_back("f(int i)");
00287 
00288         Tracer::turnOnEnv(&std::cout);
00289 
00290         std::cout << "\nTesting Function exclude list\n";
00291         Tracer::applyList(nl,Tracer::FUNCTION, Tracer::EXCLUDE);
00292         a(1);
00293 
00294         std::cout << "\nTesting Function watch list\n";
00295         watchList.push_back("b(int i)");
00296         Tracer::applyList(watchList,Tracer::FUNCTION_WATCH, Tracer::INCLUDE);
00297         a(1);
00298       }
00299       \endverbatim
00300 
00301       The above code shows the general behavior.  The main routine
00302       builts a list of routines to ignore then it calls
00303       "Tracer::turnOnEnv(&std::cout);" to check to see if the
00304       environment variable TRACER_ON is defined with some value.  If
00305       so then program execution is printed.  In the above execution
00306       when traceing is on is:
00307         
00308       \verbatim
00309       Testing Function exclude list
00310 
00311       > a(int i)
00312       In middle of a 1
00313 
00314         > b(int i)
00315       In middle of b 2
00316       In middle of c 3
00317 
00318         < b(int i)
00319 
00320       < a(int i)
00321 
00322       Testing Function watch list
00323       In middle of a 1
00324 
00325       > b(int i)
00326       In middle of b 2
00327 
00328         > c(int i)
00329       In middle of c 3
00330 
00331         < c(int i)
00332 
00333       < b(int i)
00334       \endverbatim
00335 
00336       Note that the entering and leaving messages are indented and
00337       that the "c(int i)" routine did not print because it was on the
00338       exclude list for the first call to a(1).
00339 
00340       In the watch list execution, a is ignored because it is not on
00341       the watch list  but "b(int i)" is.   Note that "c(int i)" is
00342       printed because it is called by "b(int i)" and a watch list
00343       ignores the "FUNCTION" and "KLASS" include/exclude lists.
00344 
00345  */
00346 
00347 // Local Variables:
00348 // mode: html
00349 // End:



Project Hosted By:
SourceForge.net Logo