Main Page   Namespace List   Alphabetical List   Compound List   File List   Compound Members   File Members  

debug.h

Go to the documentation of this file.
00001 // $Id: Debug.h,v 1.16 2002/11/21 17:53:11 khtan Exp khtan $
00002 /* Reference : A Handy Debugger Class by Maurice Fox, C/C++ Users Journal Apr 2001
00003    Copyright (C) Maurice J. Fox 2000 - 2003 mauricef@ix.netcom.com
00004    Copyright (C) Kwee Heong Tan 2002 - 2003 tan.k.h@juno.com
00005    Permission is granted to use this code without restriction as
00006    long as this copyright notice appears in all source files.
00007 */
00008 /* ----------------  Original source documentation by Maurice J Fox -------
00009   Debug, a class for debugging : 
00010 
00011   This package is inspired by the similar DBUG package developed
00012   for C and UNIX by Fred Fish, but does not use any of its code.
00013   
00014   It provides for tracing, debugging, interval timing, and output 
00015   control that can be controlled at run time through option strings.  
00016   Additionally, it provides optional function timing in connection 
00017   with tracing.
00018 
00019   Tracing:
00020 
00021   Tracing is printing a line of data at entry to a function and at
00022   exit from the function.  To get tracing, simply construct a Debug
00023   object at or near entry to the function.  Pass the name of the 
00024   as an argument string to the constructor.  Tracing output will be
00025   printed if tracing is enabled and either of two conditions is true:
00026   The set of remembered function names is empty, or the string supplied
00027   matches a remembered function name supplied as a keyword to the T:
00028   option.
00029   
00030   Having tracing on causes tracing and debugging output indented by
00031   two spaces for each level of function call up to a fixed limit,
00032   currently 12.  Upon execution of the object constructor, a line of
00033   data goes to the output, looking something like this:
00034           => fred
00035   When you reach a return statement in the function, or fall
00036   off the end of the code, the destructor for the object just
00037   created runs, and inserts a line of data into the output,
00038   looking something like this:
00039           <= fred
00040   So, no special effort is needed for exit tracing.  The package 
00041   also takes care of tracking the level of function calls.
00042 
00043   Debugging:
00044   
00045   Debugging is printing a line of data to the specified output
00046   destination.  To get debugging, use the overloaded Dbg member
00047   function or the Dbx member function on a previously constructed Debug 
00048   object.  See the function prototypes below for the available choices.  
00049   In each variant of Dbg, the first argument is treated as the keyword 
00050   that controls debugging.  The line that is printed contains indentation 
00051   (if tracing is in effect), the keyword followed by a colon, then the 
00052   requested output.  The line is printed if debugging is enabled and either 
00053   of two conditions is true:  The set of remembered keywords is empty, or
00054   the keyword supplied matches a remembered keyword supplied through
00055   the D: option.
00056 
00057   The package provides a small set of generally useful Dbg functions.  If
00058   these don't meet your needs, you can use the given functions as a
00059   pattern to write your own.  Another alternative is to use a single
00060   output stream, as discussed below.
00061 
00062   Interval timing:
00063 
00064   Interval timing allows you to measure the elapsed time between
00065   any two points in the program.  The functions TimeStart and
00066   TimeEnd are non-member functions, which means that you need
00067   not create a Debug object to invoke them.  (You may invoke them 
00068   through a Debug object if you like, however.)  It also means that
00069   the start and end points of the time interval(s) being measured
00070   need not be in the same function.  Interval timing is controlled
00071   by keywords, much the same fashion as tracing or debugging.  
00072   Each keyword is timed independently, so the intervals being
00073   timed can overlap.  
00074   
00075   You can use one TimeStart call to mark a single point, then a
00076   number of TimeEnd calls with the same keyword to get a series
00077   of elapsed times from that single start point.  If you call 
00078   TimeEnd without a preceding call to TimeStart with the same
00079   keyword you will get the same result as if you had called
00080   TimeStart immediately followed by TimeEnd.  This won't break
00081   anything, and might even be useful.
00082 
00083   Function Timing:
00084   This is an optional capability associated with tracing.  You select 
00085   this at compile time by the choice of constructor used for the Debug 
00086   object at the beginning of the function.  If you use the one with 
00087   only one parameter, you don't get timing.  If you use the one with 
00088   two parameters you get timing.  The second parameter is a bool, 
00089   which you can think of as "raw timing."  If it is true, you get the 
00090   time since the Epoch (or whatever your OS uses) on entry, and the 
00091   elapsed time of the function on exit.  This time is purportedly in 
00092   seconds and milliseconds, but its precision depends upon the clock 
00093   tick rate on your system.  If the second parameter to the constructor 
00094   is false, you get user friendly time in the style of asctime(), 
00095   which is what we use.  
00096 
00097   So:  If you use Debug D("fred"); you get
00098         => fred
00099         <= fred
00100 
00101         If you use Debug D("fred", true); you get
00102         => fred 901238947.234
00103         <= fred         0.877
00104 
00105         If you use Debug D("fred", false); you get
00106         => fred Sat May 13 15:39:23 2000
00107         <= fred Sat May 13 15:39:24 2000
00108 
00109   Option strings:
00110 
00111   Option strings allow run-time control of the behavior of the 
00112   package.  If you want to see any output, you need at least one
00113   option string, because the run-time default behavior is to do
00114   nothing at all.
00115 
00116   An option string is a sequence of non-blank characters of the
00117   form [anything]Option[Option . . .].
00118   Option is a sequence of the form X:[keyword_list]
00119   X here represents a non-blank character other than comma or colon.
00120   keyword_list represents an optional sequence of "words" separated
00121   by commas.  Each "word" is a sequence of non-blank characters 
00122   other than comma or colon.  The first option can be preceded by
00123   a sequence of non-blank characters not containing a colon, which
00124   the package ignores.  The reason for doing this is given 
00125   under "Passing option strings to the package."
00126 
00127   For example, the following is a syntactically valid option string:
00128   D:fred,wilma,logT:O:debug.out
00129 
00130   So is this one:
00131   DEBUGD:fred,wilma,logT:O:debug.out
00132 
00133   The options are D: T: and O:  D: is followed by three keywords:
00134   fred wilma and log.  T: is followed by no keywords, and O: is 
00135   followed by one keyword: debug.out
00136 
00137   Options currently recognized:
00138 
00139   T:  Enables tracing.  Keywords that follow this option are
00140   saved and matched against the function names provided to object
00141   constructors.  If a match is found, the function is traced at
00142   entry and exit.  If no keywords are in effect, ALL functions are
00143   traced at entry and exit.  If you give this option with keywords
00144   several times, the keywords specified are added to the list of 
00145   keywords recognized.
00146 
00147   t:  Disables tracing.  This causes tracing to be turned off.  Also
00148   the list of remembered keywords is cleared.  Any keywords that 
00149   follow this option are ignored, but cause no error.  Since the 
00150   option string is scanned from left to right, you could give the 
00151   string T:main,f1 at one point in the program.  Only the 
00152   functions main and f1 would be traced.  Later on, if you gave 
00153   the string t:T:, it would first have the effect of disabling 
00154   tracing and clearing the keywords, then enabling tracing for 
00155   all functions.
00156 
00157   D:  Enables debugging.  Keywords that follow the option are saved
00158   and matched against the keywords provided to calls to the member
00159   function Dbg.  If a match is found, the line is printed to the
00160   output.  If no keywords are in effect, ALL calls to Dbg result in
00161   lines being printed.  As with T:, giving this option several times
00162   with keywords causes the keywords to accumulate.
00163 
00164   d:  Disables debugging.  This causes debugging to be turned off,
00165   and clears the list of remembered keywords.  The same logic described
00166   above for t: applies, only to debugging.
00167 
00168   M:  Enables interval timing.  Keywords that follow the option 
00169   are saved and matched against the keywords provided to calls 
00170   to the member functions TimeStart and TimeEnd.  If a match is 
00171   found, a line is printed to the output.  The function TimeStart
00172   starts timing the keyword and prints the raw time.  The function
00173   TimeEnd stops timing the keyword and prints the elapsed time 
00174   since the last call to TimeStart for that keyword.  If you call
00175   TimeStart for the same keyword several times without intervening
00176   calls to TimeEnd, the package uses the latest one called as the 
00177   start of the timing interval.  If no keywords are in effect, ALL
00178   calls to TimeStart and TimeEnd result in lines being printed.  
00179   As with T:, giving this option several times with keywords causes 
00180   the keywords to accumulate.
00181 
00182   m:  Disables interval timing.  This causes debugging to be turned off,
00183   and clears the list of remembered keywords.  The same logic described
00184   above for t: applies, only to interval timing.
00185 
00186   O:  Output control.  If there is no keyword following, this option
00187   has no effect.  A keyword that follows is treated as an output
00188   specifier, as follows:
00189   -  Specifies standard output (cout)
00190   -- Specifies buffered standard error (clog)
00191   Anything else is used as the filename for an open call.  The
00192   package does not report the success or failure of open calls, but
00193   hey, it's a debugging tool, not production software.  It opens the 
00194   file for appending, so you could switch from one file to another and
00195   back again without losing data.  This capability also allows you
00196   to do such things as limit the size of log files and the like.  If
00197   you specify several keywords (useless but harmless), only the last
00198   one seen actually has any effect.
00199 
00200   It is not necessary to supply an O: option to get output.  By default,
00201   the package is completely inactive, but its output is preset to clog.
00202   If you just choose one of D: T: or M: you will get output to clog.
00203   
00204   Passing option strings to the package:
00205 
00206   Debug gets its option strings through the non-member function
00207   Debug::specify(), which takes as an argument a pointer to a 
00208   C-style string.  The use envisioned is that one could put Debug
00209   objects all over the place, turn off tracing and debugging through
00210   the specify() function and scan the command line before creating
00211   the first Debug object.  It's up to you, but here's a skeleton
00212   example:
00213 
00214   int main(int argc, char *argv[]) {
00215       for(int i = 1;i < argc; i++) {
00216         . . .
00217         if(!strncmp("-DEBUG",argv[i],6)) Debug::specify(argv[i]);
00218         . . .
00219       }
00220       Debug D("main");
00221       . . .
00222       D.Dbg("A","Value of x is ",x);
00223       etc . . . 
00224 
00225   Now, while in development, you could run the program with a line
00226   like -DEBUGD:T: on the command line, which would trace and debug 
00227   everything.  By default, output goes to buffered standard error (clog).
00228   A line like -DEBUGD:A,B,CT:O:debug.out would trace everything, debug 
00229   only those lines with keywords A, B, or C, and put the data into the 
00230   file debug.out.
00231 
00232   Another possibility is to use the package for logging.  Look at this:
00233 
00234   int main(int argc, char *argv[]) {
00235       Debug::specify("D:logt:"); // No tracing, logging with keyword log
00236       for(int i = 1;i < argc; i++) {
00237         . . .
00238         if(!strncmp("-DEBUG",argv[i],6)) Debug::specify(argv[i]);
00239         . . .
00240       }
00241       Debug D("main");
00242       . . .
00243       D.Dbg("A","Value of x is ",x);
00244       D.Dbg("log","Blah blah blah ",x);
00245       etc . . . 
00246    
00247    One user suggested using an environment variable to pass in
00248    an option string.  That could be useful in a GUI development or
00249    other circumstance where getting data from the command line is
00250    not feasible.
00251 
00252    You can compile a standalone test/demo program by compiling
00253    Debug.cpp all alone with the symbol TESTING defined.  Feed it
00254    option strings on the command line and watch what happens.
00255 
00256    Normally, the presence of the debug code will have negligible
00257    effect on the performance of the application.  If you really
00258    feel a need to eliminate debugging in production code, you can 
00259    compile a new no-op version by defining the symbol DEBUG_OFF 
00260    both for Debug.cpp and your own code.  Usually you're just 
00261    kidding yourself when you do that, though.
00262 
00263    Concerning performance, this version no longer flushes its output
00264    after each line.  The endl; at the end of each output statement
00265    has been replaced with "\n";.  This improved the speed somewhat for 
00266    all output choices.  The big improvement over previous versions
00267    was replacing clog with cout.  This made a very noticeable speed
00268    improvement when writing lots of debugging data to a file and a 
00269    smaller improvement to the other two destinations.
00270    
00271    The non-member function Sync() allows you to flush the output stream
00272    at will.  This can be useful when several processes are writing to
00273    the same file, as can happen when a process forks a child in a UNIX
00274    environment.  It's true that multiple processes append to the same
00275    in the correct sequence, that's only true of the physical transfer
00276    of the buffer to the file.  The system process transfers the buffer
00277    when it gets full, which might not display what you want to see.  
00278    So, in a UNIX environment, you may want to do something like this:
00279 
00280    D.Sync();
00281    pid = fork();
00282 
00283    or
00284 
00285    Debug::Sync();
00286    pid = fork();
00287 
00288    OPTIONAL CAPABILITIES:
00289 
00290    Multiple keywords:  
00291    
00292    This allows you to specify several keywords, separated by commas,
00293    (no spaces!) for a Dbg, Dbx, TimeStart, or TimeEnd function call.
00294    Then, if any one of the keywords is in effect, (or no keywords,
00295    as usual) you get the requested effect.  It could have some 
00296    performance impact if you use a lot of keywords, so you select this
00297    when compiling the package.  Define the symbol DEBUG_MULT_KWDS when
00298    compiling Debug.cpp to get this behavior.  So, if you use this capability
00299    you can write something like this:
00300 
00301         D.Dbg("fork,cache,file","Value of x is",x);
00302 
00303    and get debugging output when any of the keywords fork, cache, or file
00304    has been specified, or when no keyword has been specified for 
00305    debugging.  If you write such a line when using the version that does
00306    not recognize multiple keywords, you won't get any output if any
00307    keyword is specified, because the code that parses option strings
00308    will not create a keyword with embedded commas, so that "keyword" 
00309    would never be matched.  (But you would have figured that out for 
00310    yourself!)
00311 
00312    Don't get cute and write multiple keywords with consecutive commas,
00313    leading commas, or trailing commas.  You'll probably crash your 
00314    program or get some other undesired behavior.  (Undesired, unless
00315    you get a kick out of seeing things blow up.)
00316 
00317    DOS Disk Drives
00318 
00319    If you want to use Debug in a DOS-like environment and need to name
00320    a disk drive for an output file, you have a problem because the colon
00321    used to identify options clashes with the use of the colon in the
00322    name of a disk drive.  To make a version that uses a semicolon to
00323    identify options instead of a colon, compile with the symbol
00324    DEBUG_DOS_FORMAT defined.  All of the foregoing documentation still
00325    applies, except that where it reads colon, mentally substitute
00326    semicolon.  Then you can use an option string like
00327 
00328         D;T;O;D:\test\debug.out
00329 
00330    and get the output to the DOS file D:\test\debug.out.  This would not
00331    work in a UNIX environment, where semicolons separate commands.
00332 
00333    Single Output Stream.
00334 
00335    You can send all output through the same stream if you wish.  To
00336    do this, compile with the symbol DEBUG_1STREAM defined.  
00337    Internally, this works by logically sending all output to the clog
00338    stream, changing the actual destination by using the rdbuf() member
00339    function.  Consequently, any clog calls made directly within your
00340    program will go wherever you have sent the output.
00341 
00342    Why would I want to do this? you ask.  The main reason is to put
00343    arbitrary data into the debugging output stream without writing your
00344    own Dbg calls.  You can write output to clog with a line like
00345 
00346    clog << "Checkpoint" << n << "reached, X is now " << x << 
00347     " Y is now " << Y << " Z is now " << z << endl;
00348 
00349    and it will go wherever you have selected using the O: option.  
00350    This could be a lot simpler than writing your own overloaded Dbg
00351    function as suggested above.
00352 
00353    Because output now goes through clog, you can write something else
00354    to cerr, and it will go to unbuffered standard error, not to the
00355    debugging output.  Of course, if you have chosen to have output
00356    go to clog, they will both go to the same destination.  If you do
00357    not use this option, whatever you write to clog or cerr will go to
00358    the same destination, intermingled with debugging output only if
00359    you have specified O:--.
00360 
00361    Except for the documented effects of these three options, they are
00362    all completely independent.  This has been extensively tested.
00363 */
00364 /* ----------------  Modifications by Kwee Heong Tan ----------------------
00365 1) Added support for very old STL, circa 1996 with preprocessor symbol STL96
00366 2) Added support for compiling between VC6 and Comeau with __COMO__
00367 3) Removed DEBUG_DOS_FORMAT, setting Debug::separator to '?'.
00368    This is so that usage is the same between Windows and Unix.
00369 4) Refactored output code by adding a pDebugStream that is set up once.
00370 5) Added support for emacs outline with preprocessor define EMACS_OUTLINE.
00371    This is turned on by default.
00372    I use emacs-outline mode a lot and prepending the Enter trace with
00373    the outline prefix allows flexible display of information.
00374    An example of a trace with EMACS_OUTLINE turned on.
00375       To show just headings 1 and 2 :
00376          | * => backtraceGraph      1: vertex label== = U3:nand ...
00377          | **  => discover_vertex        1: vertex label== = U3:nand ...
00378          | **  => discover_vertex        1: vertex label== = U2:nand ...
00379          | **  => discover_vertex        1: vertex label== = J:in ...
00380          | **  => discover_vertex        1: vertex label== = K:in ...
00381          | **  => discover_vertex        1: vertex label== = M:in ...
00382          | * => implicateVertex      1: vertex label== = J:in ...
00383          | **  => setAllVertexOutputs        1: vertex label== = J:in ...
00384          | **  => discover_vertex        1: vertex label== = J:in ...
00385          | **  => discover_vertex        1: vertex label== = U2:nand ...
00386       To show all text :
00387          | * => backtraceGraph      1: vertex label== = U3:nand
00388          | **  => discover_vertex        1: vertex label== = U3:nand
00389          |     <= discover_vertex
00390          | **  => discover_vertex        1: vertex label== = U2:nand
00391          |     <= discover_vertex
00392          | **  => discover_vertex        1: vertex label== = J:in
00393          | ***   => HasXs          1: vertex label== = J:in
00394          |           1: edgeLabel== = X
00395          |       <= HasXs
00396          | ***   => getEnablingSignal          1: dResult== = ONE
00397          |       <= getEnablingSignal
00398          |     <= discover_vertex
00399          | **  => discover_vertex        1: vertex label== = K:in
00400          | ***   => HasXs          1: vertex label== = K:in
00401          |           1: edgeLabel== = X
00402          |       <= HasXs
00403          | ***   => getEnablingSignal          1: dResult== = ONE
00404          |       <= getEnablingSignal
00405          |     <= discover_vertex
00406          | **  => discover_vertex        1: vertex label== = M:in
00407          | ***   => HasXs          1: vertex label== = M:in
00408          |           1: edgeLabel== = X
00409          |       <= HasXs
00410          | ***   => getEnablingSignal          1: dResult== = ONE
00411          |       <= getEnablingSignal
00412          |     <= discover_vertex
00413          |   <= backtraceGraph
00414          | * => implicateVertex      1: vertex label== = J:in
00415          | **  => setAllVertexOutputs        1: vertex label== = J:in
00416          |         1: dSignal== = ONE
00417          |         2: before : _e[]["label"]== = X
00418          |         2: after : _e[]["label"]== = ONE
00419          |     <= setAllVertexOutputs
00420          | **  => discover_vertex        1: vertex label== = J:in
00421          | ***   => EvaluateZeroInput          1: vertex label== = J:in
00422          |           1: signal== = ONE
00423          |           1: sResult== = ONE
00424          |       <= EvaluateZeroInput
00425          |         1: outSignal== = ONE
00426          |     <= discover_vertex
00427          | **  => discover_vertex        1: vertex label== = U2:nand
00428          | ***   => EvaluateMultipleInputs          1: func= = nand
00429          |           1: inputs== =  ONE , X ,
00430          |           1: result== = X
00431          |       <= EvaluateMultipleInputs
00432          | ***   => EvaluateZeroInput          1: vertex label== = U2:nand
00433          |           1: signal== = _D
00434          |           1: signal== = X
00435          |           1: sResult== = _D
00436          |       <= EvaluateZeroInput
00437          |         1: multi-inputs :  = _FirstInconsistentOutputFound set to true
00438          |     <= discover_vertex
00439          |       1: dfv return with :  = entire tree searched
00440          |       1: firstOutputFound== = 0
00441          |       1: firstNonDPassable== = 0
00442          |       1: firstInconsistentOutput== = 0
00443          |   <= implicateVertex
00444          | 
00445    EMACS_OUTLINE support consists of
00446       - changing the Debug constructor to accept a new boolean to allow CR/LF
00447         to be selectively written. This allows the first .Dbg to be appended
00448         to the Enter heading, assisting in reading the trace output.
00449       - writing out the EMACS OUTLINE prefix "*" appropriately.
00450 6) Removed various and sundry Dbg and Dbx calls, replacing with 2 Dbg member
00451    function templates. Dbx calls were removed because it required the user to
00452    remember which types use Dbx and which types use Dbg.
00453    Dbg member function template for T* automatically detects the NULL pointer.
00454    Added two specializations for char* case.
00455 7) By templating Debug code, added a Debug.hpp for ease of compilation, and 
00456    use on VC6 projects.
00457  */
00458 #ifndef DEBUG_CLASS_DEFINED
00459 #define DEBUG_CLASS_DEFINED 1
00460 #if defined(WIN32) && !defined(__COMO__)
00461    #pragma warning(disable:4002 4786)
00462 #endif
00463 #include <stdio.h>
00464 #include <time.h>
00465 #include <sys/types.h>
00466 #include <sys/timeb.h>
00467 #include <assert.h>
00468 
00469 #define EMACS_OUTLINE // turn on support for emacs outline headers in trace
00470 
00471    #include <utility> // STL96: includes function.h, must be before string
00472    #include <string>
00473    #include <vector>
00474 #ifdef STL96
00475    #include <iostream.h>
00476    #include <fstream.h>
00477    #define STD
00478 #else
00479    #include <iostream>
00480    #include <fstream>
00481    #define STD std::
00482 #endif
00483 
00484 #define DECLARE_DEBUG(name) Debug D(name)
00485 
00486 #ifdef DEBUG_OFF
00487 class Debug {
00488 public:
00489   Debug(const char* f,bool rawtimeMode=false,bool bEndLine=false){}
00490     ~Debug() {}
00491     template<class T> void Dbg(const STD string& keyword, const STD string& description, T* pT){}
00492     template<class T> void Dbg(const STD string& keyword, const STD string& description, const T& tValue){}
00493                       void Dbg(const STD string& keyword, const STD string& description, char* pC) {}
00494     template<class T> void Dbg(const STD string& keyword, const T* pT){}
00495     template<class T> void Dbg(const STD string& keyword, const T& tValue){}
00496                       void Dbg(const STD string& keyword, char* pC){}
00497     static void specify(const char *){}
00498     static void TimeStart(const char *, const char *){}
00499     static void TimeEnd(const char *, const char *){}
00500     static void Sync(){}
00501 
00502 private:
00503     Debug() {}
00504 };
00505 
00506 #else
00507 
00508 class Debug {
00509 public:
00510 #if defined(EMACS_OUTLINE)
00511     Debug(const char* f,bool rawtimeMode=false,bool bEndLine=false);
00512 #else
00513     Debug(const char* f,bool rawtimeMode=false,bool bEndLine=true);
00514 #endif
00515     ~Debug();
00516     void Dbg(const STD string& keyword, const STD string& description, char* pC);
00517     template<class T> void Dbg(const STD string& keyword, const STD string& description, const T* pT){
00518       if(!debugging(keyword)) return;
00519       indent();
00520       if(NULL==pT){
00521         (*pDebugStream) << keyword << ": "<< description << " = NULL\n";
00522       }else{
00523         (*pDebugStream) << keyword << ": "<< description << " = " << (*pT) << "\n";
00524       }
00525     }
00526     template<class T> void Dbg(const STD string& keyword, const STD string& description, const T& tValue){
00527       if(!debugging(keyword)) return;
00528       indent();
00529       (*pDebugStream) << keyword << ": "<< description << " = " << tValue << "\n";
00530     }
00531     void Dbg(const STD string& keyword, char* pC);
00532     template<class T> void Dbg(const STD string& keyword, const T* pT){
00533       // cout <<"-print T*\n";
00534       if(!debugging(keyword)) return;
00535       indent();
00536       if(NULL==pT){
00537         (*pDebugStream) << keyword << ": NULL\n";
00538       }else{
00539         (*pDebugStream) << keyword << ": " << (*pT) << "\n";
00540       }
00541     }
00542     template<class T> void Dbg(const STD string& keyword, const T& tValue){
00543       // cout <<"-print T&\n";
00544       if(!debugging(keyword)) return;
00545       indent();
00546       (*pDebugStream) << keyword << ": "<< (const T) tValue << "\n";
00547     }
00548     static void specify( const char * );
00549     static void TimeStart(const STD string &, const char *);
00550     static void TimeEnd(const STD string &, const char *);
00551     static void Sync();
00552 private:
00553     // Constants
00554     enum {limit = 12};// indentation limit for tracing
00555 
00556     // Static members
00557     static int level; // Counts the depth of function calling
00558     static bool Debugging; // Controls printing in Dbg calls
00559     static bool Tracing;   // Controls printing in ctor and dtor calls
00560     static bool Timing;    // Controls interval timing
00561 
00562     static char separator;
00563     static STD string filename;
00564     static STD ofstream* pFile;
00565     static STD ostream* pDebugStream;
00566     static bool use_cout;
00567     static bool use_clog;
00568 
00569     static STD vector<STD string> keywords;
00570     static STD vector<STD string> functions;
00571     static STD vector<STD string> timekeys;
00572     static STD vector<STD pair<STD string, struct timeb> > timers;
00573     static char mybuff[200];
00574 
00575     // Internal functions
00576     bool tracing(const STD string &); // Tells whether to do tracing or not
00577     bool debugging(const STD string &); // Tells whether to do debugging or not.
00578                     // Both of these look at the flag and at the vector.
00579     static void indent();  // Indents the output line
00580     void Enter(bool); // Gets us into a function with proper indents, printing the name of the function.
00581     void Exit();    // Gets us out of a function with proper indents.
00582     Debug();        // No default ctor
00583     char *time_stuff();
00584     Debug(const Debug &);   // No copy ctor
00585     static bool IntTiming(const STD string &);  // Tells whether to do interval timing
00586 
00587     // object data;
00588     STD string function_name;
00589     bool timing;
00590     bool raw_time;
00591     bool going_in;
00592     struct timeb Start;
00593 };
00594 
00595 #endif
00596 #endif
00597 
00598 

Generated on Mon Jan 20 11:54:25 2003 for ATPG by doxygen1.3-rc1