PrettyDebug.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CERTI - HLA RunTime Infrastructure
00003 // Copyright (C) 2002, 2003  ONERA
00004 //
00005 // This file is part of CERTI-libCERTI
00006 //
00007 // CERTI-libCERTI is free software ; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License
00009 // as published by the Free Software Foundation ; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // CERTI-libCERTI is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY ; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015 // Lesser General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public
00018 // License along with this program ; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020 // USA
00021 //
00022 // $Id: PrettyDebug.cc,v 4.9 2008/05/27 12:26:54 jmm Exp $
00023 // ----------------------------------------------------------------------------
00024 
00025 
00026 #include "PrettyDebug.hh"
00027 #include "Message.hh"
00028 #include "NetworkMessage.hh"
00029 
00030 #include <stdlib.h>
00031 #include <stdarg.h>
00032 #include <iostream>
00033 #include <cstring>
00034 #ifdef _WIN32
00035     #include <time.h>
00036     #include <sys/timeb.h>
00037 #else
00038     #include <sys/types.h>
00039     #include <sys/time.h>
00040     #include <unistd.h>
00041     #include <string>
00042     #include <libgen.h>
00043 #endif
00044 
00045 using std::cout ;
00046 using std::cerr ;
00047 using std::endl ;
00048 
00049 DebugOStream DebugOStream::nullOutputStream(cout);
00050 DebugOStream PrettyDebug::defaultOutputStream(cerr);
00051 
00052 //Fix this pointer to the default initialisation of pointers for your compiler
00053 DebugOStream* PrettyDebug::nullOutputStreamPtr = 0 ; 
00054 DebugOStream& PrettyDebug::nullOutputStream = DebugOStream::nullOutputStream;
00055 
00056 #ifdef _WIN32       //Mutex switch ON
00057     HANDLE PrettyDebug::g_hMutex= CreateMutex(NULL,FALSE,"HLA");    
00058 #endif
00059 
00060 std::string PrettyDebug::federateName_ = "" ;
00061 
00062 // ----------------------------------------------------------------------------
00065 void
00066 PrettyDebug::Print(DebugOStream& theOutputStream,
00067                    const char* theHeaderMessage, const char * Message)
00068 {
00069 char buffer[256] ;
00070 
00071 #ifdef _WIN32
00072     if (WaitForSingleObject(g_hMutex,INFINITE) == WAIT_OBJECT_0)
00073         {//Wait for Mutex
00074         struct _timeb timebuffer;_ftime(&timebuffer );
00075         sprintf(buffer,"HLALOG - %I64d.%03hd s - %s", timebuffer.time,timebuffer.millitm,federateName_.c_str());
00076 
00077         if (Message != NULL)
00078             theOutputStream << buffer << " - " << theHeaderMessage << "> " << Message;
00079         else
00080             theOutputStream << buffer << " - " << theHeaderMessage << pdSEmptyMessage;
00081             
00082         theOutputStream.flush();
00083         ReleaseMutex(g_hMutex);
00084         }
00085 #else
00086     struct timeval tv;
00087     gettimeofday( &tv, NULL );
00088     sprintf( buffer, "HLALOG - %ld.%06ld - %s",tv.tv_sec,tv.tv_usec,federateName_.c_str() ) ;
00089 
00090     if (Message != NULL)
00091         theOutputStream << buffer << " - " << basename((char *)theHeaderMessage) << "> " << Message;
00092     else
00093         theOutputStream << buffer << " - " << basename((char *)theHeaderMessage) << pdSEmptyMessage;
00094     theOutputStream.flush();    
00095 #endif
00096 }
00097 
00098 // ----------------------------------------------------------------------------
00102 void
00103 PrettyDebug::ParseEnvString(const char *Name)
00104 {
00105 unsigned int i;
00106 char *Value = getenv(Name); // The value of the variable Name
00107 char  Key; // A character from the value compared to keys.
00108 char *Pos; // The position of Key in pdDebugKeys
00109 char *DebugKeys = (char *) pdDebugKeysString ; // needs a non const string
00110 
00111 for (i = pdUnused; i < pdLast + 1; i++) // Clear current level map
00112     Level_Map[i] = PrettyDebug::nullOutputStreamPtr;
00113 
00114 if (Value != 0) 
00115     { // Print Debug Init Message
00116     const char *pdInitMessage = " variable read, content = ";
00117     const char *pdTooLongInitMessage = "Env Var read(string too long).";
00118     
00119     int length = strlen(LEnvVar) + strlen(pdInitMessage) + strlen(Value);
00120     if (length < pdMaxMessageSize)
00121         cout << LEnvVar << pdInitMessage << Value << endl;
00122     else
00123         cout << LEnvVar << pdTooLongInitMessage << endl;
00124 
00125     // Compare each char of Value to content of the pgDebugKeys 
00126     // string, to enable matching debug levels.
00127     for (i = 0; i < strlen(Value); i++) 
00128         {
00129         Key = Value[i];
00130         Pos = strchr(DebugKeys, Key);
00131         if (Pos != 0)
00132              Level_Map[Pos - DebugKeys] = &(PrettyDebug::defaultOutputStream);
00133         }
00134     }
00135 return;
00136 }
00137 
00138 // ---------------------------------------------------------------------------- 
00143 PrettyDebug::PrettyDebug(const char *Name, const char *Header)
00144 {
00145 if (NULL == Name) 
00146     {
00147     PrettyDebug::Print(PrettyDebug::defaultOutputStream, "", 
00148     "Error in pgCDebug constructor, no Name specified.\n");
00149      Name = "NoName";
00150     }
00151 
00152 LEnvVar = strdup(Name);
00153 if (Header != 0)
00154     HeaderMessage = strdup(Header);
00155 else
00156     HeaderMessage = strdup("");
00157 
00158 //Initialisation de LMessage a 0. Il est alloue la premiere fois
00159 //dans la methode Out.
00160 LMessage = 0;
00161 
00162 if ((LEnvVar == 0) || (HeaderMessage == 0)) 
00163     {
00164     PrettyDebug::Print(PrettyDebug::defaultOutputStream, "", 
00165     "Error in pgCDebug constructor memory allocation.\n");
00166     exit(EXIT_FAILURE);
00167     }
00168 ParseEnvString(Name);
00169 }
00170 
00171 // ----------------------------------------------------------------------------
00173 PrettyDebug::~PrettyDebug()
00174 {
00175     free(LEnvVar);
00176     if (LMessage != 0) {
00177         free(LMessage);
00178     }
00179     if (HeaderMessage != 0) {
00180         free(HeaderMessage);
00181     }
00182 }
00183 
00184 // ----------------------------------------------------------------------------
00186 bool
00187 PrettyDebug::Mode(pdDebugLevel Level)
00188 {
00189     return (Level_Map[Level] != PrettyDebug::nullOutputStreamPtr);
00190 }
00191 
00192 // ----------------------------------------------------------------------------
00198 void
00199 PrettyDebug::enableDebugLevel(pdDebugLevel Level, DebugOStream& theOutputStream)
00200 {
00201     Level_Map[Level] = &(theOutputStream);
00202     return;
00203 }
00204 
00205 // ----------------------------------------------------------------------------
00207 void
00208 PrettyDebug::disableDebugLevel(pdDebugLevel Level)
00209 {
00210     Level_Map[Level] = PrettyDebug::nullOutputStreamPtr;
00211     return;
00212 }
00213      
00214 // ----------------------------------------------------------------------------
00215 #ifndef NDEBUG
00216 
00224 void
00225 PrettyDebug::Out(pdDebugLevel Level, const char * Format, ...)
00226 {
00227 DebugOStream* theOutputStreamPtr = Level_Map[Level];
00228 
00229 //Warnings messages
00230 //if (LEnvVar == 0) cout << endl << "ENV VAR NULL CALLING OUT METHOD ";
00231 //if (HeaderMessage == 0) cout << "HEADER NULL CALLING OUT METHOD" << endl;
00232 
00233 if (theOutputStreamPtr != PrettyDebug::nullOutputStreamPtr) 
00234     {
00235     if (Format != 0) 
00236         { // Cat Header and Message strings 
00237         if (LMessage == 0) 
00238             { // A final printed message is
00239                         // Header+Message+\n(+\0) 
00240             //Optimisation, on pourrait peut-etre mettre LMessage
00241             //en static.  Mais il ne faudra pas que dans un D.Out
00242             //qu'on appelle un autre D.Out car autrement, seul un
00243             //message serait affiche.
00244 
00245             LMessage = (char *) malloc((pdMaxMessageSize+2) * sizeof(char));
00246 
00247             if (LMessage == 0)
00248                 { 
00249                 PrettyDebug::Print(PrettyDebug::defaultOutputStream,
00250                                 HeaderMessage, 
00251                                 "Error in pgCDebug Out method while "
00252                                 "allocating initial memory for messages\n");
00253                 exit(EXIT_FAILURE);
00254                 }
00255         //                else
00256         //                    PrettyDebug::Print(PrettyDebug::defaultOutputStream, 
00257         //                                    HeaderMessage, "Allocated initial memory "
00258         //                                    "for Message buffer.\n");
00259             }
00260         va_list argptr; // Variable Argument list, see stdarg.h
00261         va_start(argptr, Format);
00262         //Probleme, rien ne garantit qu'on ne depassera pas le
00263         //nombre max de char dans le vsprintf.
00264         vsprintf(LMessage, Format, argptr); 
00265         va_end(argptr);
00266         }
00267     else
00268         strcpy(LMessage, "Pretty Debug received an empty Message.");
00269         
00270     strcat(LMessage, "\n"); // Add trailing \n
00271     PrettyDebug::Print(*theOutputStreamPtr, HeaderMessage, LMessage);
00272     }
00273 return;
00274 }
00275 
00276 #endif // NDEBUG
00277 
00278 // $Id: PrettyDebug.cc,v 4.9 2008/05/27 12:26:54 jmm Exp $

Generated on Thu Apr 30 15:53:49 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5