1 //===-- DNBLog.cpp ----------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Created by Greg Clayton on 6/18/07. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "DNBLog.h" 15 16 static int g_debug = 0; 17 static int g_verbose = 0; 18 19 #if defined (DNBLOG_ENABLED) 20 21 #include <stdio.h> 22 #include <stdarg.h> 23 #include <stdlib.h> 24 #include <sys/time.h> 25 #include <unistd.h> 26 #include <mach/mach.h> 27 #include <pthread.h> 28 #include "PThreadMutex.h" 29 30 uint32_t g_log_bits = 0; 31 static DNBCallbackLog g_log_callback = NULL; 32 static void *g_log_baton = NULL; 33 34 35 int 36 DNBLogGetDebug () 37 { 38 return g_debug; 39 } 40 41 42 void 43 DNBLogSetDebug (int g) 44 { 45 g_debug = g; 46 } 47 48 int 49 DNBLogGetVerbose () 50 { 51 return g_verbose; 52 } 53 54 void 55 DNBLogSetVerbose (int v) 56 { 57 g_verbose = v; 58 } 59 60 bool 61 DNBLogCheckLogBit (uint32_t bit) 62 { 63 return (g_log_bits & bit) != 0; 64 } 65 66 uint32_t 67 DNBLogSetLogMask (uint32_t mask) 68 { 69 uint32_t old = g_log_bits; 70 g_log_bits = mask; 71 return old; 72 } 73 74 uint32_t 75 DNBLogGetLogMask () 76 { 77 return g_log_bits; 78 } 79 80 void 81 DNBLogSetLogCallback (DNBCallbackLog callback, void *baton) 82 { 83 g_log_callback = callback; 84 g_log_baton = baton; 85 } 86 87 bool 88 DNBLogEnabled () 89 { 90 return g_log_callback != NULL; 91 } 92 93 bool 94 DNBLogEnabledForAny (uint32_t mask) 95 { 96 if (g_log_callback) 97 return (g_log_bits & mask) != 0; 98 return false; 99 } 100 static inline void 101 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args) 102 { 103 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 104 PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); 105 106 if (g_log_callback) 107 g_log_callback(g_log_baton, flags, format, args); 108 } 109 110 void 111 _DNBLog(uint32_t flags, const char *format, ...) 112 { 113 va_list args; 114 va_start (args, format); 115 _DNBLogVAPrintf(flags, format, args); 116 va_end (args); 117 } 118 119 //---------------------------------------------------------------------- 120 // Print debug strings if and only if the global g_debug is set to 121 // a non-zero value. 122 //---------------------------------------------------------------------- 123 void 124 _DNBLogDebug (const char *format, ...) 125 { 126 if (DNBLogEnabled () && g_debug) 127 { 128 va_list args; 129 va_start (args, format); 130 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); 131 va_end (args); 132 } 133 } 134 135 136 //---------------------------------------------------------------------- 137 // Print debug strings if and only if the global g_debug is set to 138 // a non-zero value. 139 //---------------------------------------------------------------------- 140 void 141 _DNBLogDebugVerbose (const char *format, ...) 142 { 143 if (DNBLogEnabled () && g_debug && g_verbose) 144 { 145 va_list args; 146 va_start (args, format); 147 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); 148 va_end (args); 149 } 150 } 151 152 153 static uint32_t g_message_id = 0; 154 155 //---------------------------------------------------------------------- 156 // Prefix the formatted log string with process and thread IDs and 157 // suffix it with a newline. 158 //---------------------------------------------------------------------- 159 void 160 _DNBLogThreaded (const char *format, ...) 161 { 162 if (DNBLogEnabled ()) 163 { 164 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 165 166 char *arg_msg = NULL; 167 va_list args; 168 va_start (args, format); 169 ::vasprintf (&arg_msg, format, args); 170 va_end (args); 171 172 if (arg_msg != NULL) 173 { 174 static struct timeval g_timeval = { 0 , 0 }; 175 static struct timeval tv; 176 static struct timeval delta; 177 gettimeofday(&tv, NULL); 178 if (g_timeval.tv_sec == 0) 179 { 180 delta.tv_sec = 0; 181 delta.tv_usec = 0; 182 } 183 else 184 { 185 timersub (&tv, &g_timeval, &delta); 186 } 187 g_timeval = tv; 188 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s", 189 ++g_message_id, 190 delta.tv_sec, 191 delta.tv_usec, 192 getpid(), 193 mach_thread_self(), 194 arg_msg); 195 free (arg_msg); 196 } 197 } 198 } 199 200 //---------------------------------------------------------------------- 201 // Prefix the formatted log string with process and thread IDs and 202 // suffix it with a newline. 203 //---------------------------------------------------------------------- 204 void 205 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...) 206 { 207 if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit) 208 { 209 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 210 211 char *arg_msg = NULL; 212 va_list args; 213 va_start (args, format); 214 ::vasprintf (&arg_msg, format, args); 215 va_end (args); 216 217 if (arg_msg != NULL) 218 { 219 static struct timeval g_timeval = { 0 , 0 }; 220 static struct timeval tv; 221 static struct timeval delta; 222 gettimeofday(&tv, NULL); 223 if (g_timeval.tv_sec == 0) 224 { 225 delta.tv_sec = 0; 226 delta.tv_usec = 0; 227 } 228 else 229 { 230 timersub (&tv, &g_timeval, &delta); 231 } 232 g_timeval = tv; 233 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s", 234 ++g_message_id, 235 delta.tv_sec, 236 delta.tv_usec, 237 getpid(), 238 mach_thread_self(), 239 arg_msg); 240 free (arg_msg); 241 } 242 } 243 } 244 245 246 247 //---------------------------------------------------------------------- 248 // Printing of errors that are not fatal. 249 //---------------------------------------------------------------------- 250 void 251 _DNBLogError (const char *format, ...) 252 { 253 if (DNBLogEnabled ()) 254 { 255 char *arg_msg = NULL; 256 va_list args; 257 va_start (args, format); 258 ::vasprintf (&arg_msg, format, args); 259 va_end (args); 260 261 if (arg_msg != NULL) 262 { 263 _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg); 264 free (arg_msg); 265 } 266 } 267 } 268 269 //---------------------------------------------------------------------- 270 // Printing of errors that ARE fatal. Exit with ERR exit code 271 // immediately. 272 //---------------------------------------------------------------------- 273 void 274 _DNBLogFatalError (int err, const char *format, ...) 275 { 276 if (DNBLogEnabled ()) 277 { 278 char *arg_msg = NULL; 279 va_list args; 280 va_start (args, format); 281 ::vasprintf (&arg_msg, format, args); 282 va_end (args); 283 284 if (arg_msg != NULL) 285 { 286 _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); 287 free (arg_msg); 288 } 289 ::exit (err); 290 } 291 } 292 293 294 //---------------------------------------------------------------------- 295 // Printing of warnings that are not fatal only if verbose mode is 296 // enabled. 297 //---------------------------------------------------------------------- 298 void 299 _DNBLogVerbose (const char *format, ...) 300 { 301 if (DNBLogEnabled () && g_verbose) 302 { 303 va_list args; 304 va_start (args, format); 305 _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); 306 va_end (args); 307 } 308 } 309 310 //---------------------------------------------------------------------- 311 // Printing of warnings that are not fatal only if verbose mode is 312 // enabled. 313 //---------------------------------------------------------------------- 314 void 315 _DNBLogWarningVerbose (const char *format, ...) 316 { 317 if (DNBLogEnabled () && g_verbose) 318 { 319 char *arg_msg = NULL; 320 va_list args; 321 va_start (args, format); 322 ::vasprintf (&arg_msg, format, args); 323 va_end (args); 324 325 if (arg_msg != NULL) 326 { 327 _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg); 328 free (arg_msg); 329 } 330 } 331 } 332 //---------------------------------------------------------------------- 333 // Printing of warnings that are not fatal. 334 //---------------------------------------------------------------------- 335 void 336 _DNBLogWarning (const char *format, ...) 337 { 338 if (DNBLogEnabled ()) 339 { 340 char *arg_msg = NULL; 341 va_list args; 342 va_start (args, format); 343 ::vasprintf (&arg_msg, format, args); 344 va_end (args); 345 346 if (arg_msg != NULL) 347 { 348 _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); 349 free (arg_msg); 350 } 351 } 352 } 353 354 #endif 355