00001
00002
00003
00004
00005
00006
00007
00008 #include "Debug.h"
00009 #include <algorithm>
00010
00011
00012 #ifdef STL96
00013 #define CLEAR(name) name.erase(name.begin(),name.end());
00014 extern "C" {
00015 int ftime(struct timeb *timeptr);
00016 }
00017 #else
00018 using namespace std;
00019 #define CLEAR(name) name.clear()
00020 #endif
00021
00022 #ifdef TESTING
00023 static void f1(void);
00024 static void f2(void);
00025 int main( int argc, char * argv[] ) {
00026 Debug D("main");
00027 float pi = (float)3.14;
00028 int i = 1999;
00029 char String[] = "This is a testing string ";
00030
00031 for(int j = 1; j < argc; j++) {
00032 Debug::specify(argv[j]);
00033 D.Dbg("argv[j]",argv[j]);
00034 D.Dbg("float", pi);
00035 D.Dbg("integer", i);
00036 D.Dbg("string", String, i);
00037 f1();
00038 }
00039 return 0;
00040 }
00041
00042 static void f1() {
00043 Debug D("f1");
00044 D.Dbg("string","f1's string");
00045 D.Sync();
00046 D.Dbg("string","string one ", "string two");
00047 f2();
00048 }
00049
00050 static void f2() {
00051 Debug D("f2");
00052 D.Dbg("string","f2's string");
00053 D.Dbg("integer","This is an unsigned hex one ", static_cast<unsigned long>(0XDEADBEEF));
00054 D.Dbg("integer","This is a regular integer ", static_cast<int>(0XDEADBEEF));
00055
00056
00057 D.Dbg("bogus,fred,fork,a,string,integer","a string");
00058 Debug::Sync();
00059
00060 }
00061 #endif // TESTING
00062
00063 #ifndef DEBUG_OFF
00064
00065 int Debug::level = 0;
00066 bool Debug::Debugging = false;
00067 bool Debug::Tracing = false;
00068 bool Debug::Timing = false;
00069 STD ofstream* Debug::pFile=NULL;
00070 STD ostream* Debug::pDebugStream=&clog;
00071
00072 char Debug::separator = '?';
00073
00074 char Debug::mybuff[200];
00075 string Debug::filename;
00076
00077 vector<string> Debug::keywords;
00078 vector<string> Debug::functions;
00079 vector<string> Debug::timekeys;
00080 vector<pair<string, struct timeb> > Debug::timers;
00081
00082 Debug::Debug(const char* f,bool rawtimeMode,bool bEndLine) :
00083 function_name(f), timing(rawtimeMode),raw_time(rawtimeMode),going_in(rawtimeMode)
00084 {
00085 level++;
00086 if(tracing(function_name))
00087 Enter(bEndLine);
00088 going_in=false;
00089 }
00090 Debug::~Debug() {
00091 if(tracing(function_name)) Exit();
00092 level--;
00093 }
00094
00095 bool Debug::tracing(const string & f) {
00096 if(!Tracing) return false;
00097
00098 return (functions.empty() ||
00099 find(functions.begin(),functions.end(),f) != functions.end());
00100 }
00101
00102 bool Debug::debugging(const string & k) {
00103 if(!Debugging) return false;
00104
00105 #if defined DEBUG_MULT_KWDS
00106 if( keywords.empty()) return true;
00107 string::size_type start, end;
00108 string kw;
00109 start = 0;
00110 do {
00111
00112
00113
00114 end = k.find(',', start);
00115 if( end == string::npos ) {
00116
00117
00118 kw = k.substr(start);
00119 } else {
00120
00121 kw = k.substr(start,end-start);
00122 start = end + 1;
00123 }
00124 if(find(keywords.begin(),keywords.end(),kw) != keywords.end()) {
00125 return true;
00126 }
00127 } while( end != string::npos );
00128 return false;
00129 #else
00130 return (keywords.empty() ||
00131 find(keywords.begin(),keywords.end(),k) != keywords.end());
00132 #endif
00133 }
00134
00135 bool Debug::IntTiming(const string & t) {
00136 if(!Timing) return false;
00137
00138 #if defined DEBUG_MULT_KWDS
00139 if( timekeys.empty()) return true;
00140 string::size_type start, end;
00141 string kw;
00142 start = 0;
00143 do {
00144
00145
00146
00147 end = t.find(',', start);
00148 if( end == string::npos ) {
00149
00150
00151 kw = t.substr(start);
00152 } else {
00153
00154 kw = t.substr(start,end-start);
00155 start = end + 1;
00156 }
00157 if(find(timekeys.begin(),timekeys.end(),kw) != timekeys.end()) {
00158 return true;
00159 }
00160 } while( end != string::npos );
00161 return false;
00162 #else
00163 return(timekeys.empty() ||
00164 find(timekeys.begin(),timekeys.end(),t) != timekeys.end());
00165 #endif
00166 }
00167 void Debug::Enter(bool bEndLine){
00168 string sBuffer;
00169 for(int i = 1; i < (level < limit ? level : limit) ; i++ ){
00170 sBuffer+=" ";
00171 }
00172 #if defined(EMACS_OUTLINE) // not handling level > limit case
00173 sBuffer.replace(0,level-1,level-1,'*');
00174 #endif//EMACS_OUTLINE
00175
00176 (*pDebugStream) << sBuffer;
00177 (*pDebugStream) << "=> " << function_name << time_stuff();
00178 if(bEndLine) (*pDebugStream) << "\n";
00179 }
00180 void Debug::Exit(){
00181 for(int i = 1; i < (level < limit ? level : limit) ; i++ )
00182 (*pDebugStream) << " ";
00183
00184 (*pDebugStream) << "<= " << function_name << time_stuff() << "\n";
00185 }
00186 char * Debug::time_stuff() {
00187 if(!timing) return "";
00188
00189 if(raw_time) {
00190 struct timeb Tb;
00191 ftime(&Tb);
00192 if(going_in) {
00193 sprintf(mybuff, " %ld.%03d",Tb.time, Tb.millitm);
00194 Start = Tb;
00195 } else {
00196 long int secs, millis;
00197 millis = Tb.millitm - Start.millitm;
00198 secs = Tb.time - Start.time;
00199 if(millis < 0) {
00200 millis += 1000;
00201 -- secs;
00202 }
00203 sprintf(mybuff, " %ld.%03ld", secs, millis);
00204 }
00205
00206 } else {
00207 time_t Clock;
00208 time(&Clock);
00209 sprintf(mybuff," %s", asctime(localtime(&Clock)));
00210 mybuff[strlen(mybuff)-1] = '\0';
00211 }
00212 return mybuff;
00213 }
00214
00215 void Debug::indent() {
00216 if( Tracing ) {
00217 for( int i = 0; i <= (level < (limit + 1) ? level : (limit + 1)); i++ )
00218 (*pDebugStream) << " ";
00219 }
00220 }
00221 void Debug::Dbg(const std::string& keyword, const std::string& description, char* pC){
00222
00223 if(!debugging(keyword)) return;
00224 indent();
00225 if(NULL==pC){
00226 (*pDebugStream) << keyword << ": "<< description << " = NULL\n";
00227 }else{
00228 (*pDebugStream) << keyword << ": "<< description << " = " << pC << "\n";
00229 }
00230 };
00231 void Debug::Dbg(const std::string& keyword, char* pC){
00232
00233 if(!debugging(keyword)) return;
00234 indent();
00235 if(NULL==pC){
00236 (*pDebugStream) << keyword << ": NULL\n";
00237 }else{
00238 (*pDebugStream) << keyword << ": "<< pC << "\n";
00239 }
00240 };
00241
00242 void Debug::TimeStart(const string &t, const char *s) {
00243 if(!IntTiming(t)) return;
00244
00245 unsigned int i = 0;
00246 for(i = 0; i < timers.size(); i++) {
00247 if(timers[i].first == t) break;
00248 }
00249 timeb tb;
00250 ftime(&tb);
00251 if( i == timers.size()) {
00252 timers.push_back(make_pair(t,tb));
00253 } else {
00254 timers[i].second = tb;
00255 }
00256 sprintf(mybuff," %ld.%03d", tb.time, tb.millitm);
00257
00258 indent();
00259 (*pDebugStream) << t << ": " << s << mybuff << "\n";
00260 }
00261
00262 void Debug::TimeEnd(const string &t, const char *s) {
00263 if(!IntTiming(t)) return;
00264
00265 unsigned int i = 0;
00266 for(i = 0; i < timers.size(); i++) {
00267 if(timers[i].first == t) break;
00268 }
00269 timeb tb;
00270 ftime(&tb);
00271 if( i == timers.size()) {
00272
00273
00274
00275 timers.push_back(make_pair(t,tb));
00276 }
00277
00278
00279 int secs, millis;
00280 millis = tb.millitm - timers[i].second.millitm;
00281 secs = tb.time - timers[i].second.time;
00282 if(millis < 0) {
00283 millis += 1000;
00284 --secs;
00285 }
00286 sprintf(mybuff, " %d.%03d", secs, millis);
00287
00288 indent();
00289 (*pDebugStream) << t << ": " << s << mybuff << "\n";
00290 }
00291
00292 void Debug::Sync() {
00293 pDebugStream->flush();
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void Debug::specify(const char * opt) {
00323 string s = opt;
00324
00325
00326 unsigned int j = s.find_first_of(separator,0);
00327 while(j < s.length()) {
00328
00329
00330 unsigned int k = s.find_first_of(separator,j+1);
00331
00332
00333
00334 string Option;
00335 if(j == 0) {
00336 Option = "0";
00337 Option += s[0];
00338 } else {
00339 Option = string(s,j-1,2);
00340 }
00341
00342
00343 unsigned int l = s.find_first_of(',',j+1);
00344
00345
00346
00347 if((l >= k) && (j < k-2)) {
00348 if( k > s.length() )
00349 l = s.length();
00350 else l = k-1;
00351 }
00352 while(l < k) {
00353 string kw;
00354 if(j+1 < l ) {
00355 kw = string(s,j+1,l-j-1);
00356 } else {
00357 kw = "";
00358 }
00359
00360 if( l < s.length() ) {
00361
00362 j = l;
00363 unsigned int m = s.find_first_of(',',l+1);
00364
00365
00366
00367
00368 if((m >= k) && (j < k-1)) {
00369 if( (m > s.length()) && ( k > s.length()))
00370 m = s.length();
00371 else m = k-1;
00372 }
00373 l = m;
00374 } else l = k;
00375
00376
00377 switch(Option[0]) {
00378 case 'D':
00379 if(kw.length()) keywords.push_back(kw);
00380 break;
00381
00382 case 'O':
00383 #ifdef STL96
00384 if(!( (! kw.length()) || kw==filename)) {
00385 #else
00386 if(kw.length() && kw != filename) {
00387 #endif
00388 filename = kw;
00389 if( kw == "-"){
00390 pDebugStream=&cout;
00391 }else{
00392 if(kw == "--") {
00393 pDebugStream=&clog;
00394 }else{
00395 if(NULL!=pFile){
00396 delete pFile;
00397 pFile=NULL;
00398 }
00399 pFile=new(ofstream);
00400 pFile->open(filename.c_str(),ios::app);
00401 pDebugStream=pFile;
00402 }
00403 }
00404 }
00405 break;
00406
00407 case 'T':
00408 if(kw.length()) functions.push_back(kw);
00409 break;
00410
00411 case 'M':
00412 if(kw.length()) timekeys.push_back(kw);
00413 break;
00414
00415 default:
00416 break;
00417 }
00418 }
00419
00420 switch(Option[0]) {
00421 case 'D':
00422 Debugging = true;
00423 break;
00424
00425 case 'd':
00426 CLEAR(keywords);
00427 Debugging = false;
00428 break;
00429
00430 case 'O':
00431 break;
00432
00433 case 'T':
00434 Tracing = true;
00435 break;
00436
00437 case 't':
00438 CLEAR(functions);
00439 Tracing = false;
00440 break;
00441
00442 case 'M':
00443 Timing = true;
00444 break;
00445
00446 case 'm':
00447 CLEAR(timekeys);
00448 CLEAR(timers);
00449 Timing = false;
00450 break;
00451
00452 default:
00453 break;
00454 }
00455 j = k;
00456 }
00457 }
00458 #endif // ndef DEBUG_OFF