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