# 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 $