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 static inline void 94 _DNBLogVAPrintf(uint32_t flags, const char *format, va_list args) 95 { 96 static PThreadMutex g_LogThreadedMutex(PTHREAD_MUTEX_RECURSIVE); 97 PTHREAD_MUTEX_LOCKER(locker, g_LogThreadedMutex); 98 99 if (g_log_callback) 100 g_log_callback(g_log_baton, flags, format, args); 101 } 102 103 void 104 _DNBLog(uint32_t flags, const char *format, ...) 105 { 106 va_list args; 107 va_start (args, format); 108 _DNBLogVAPrintf(flags, format, args); 109 va_end (args); 110 } 111 112 //---------------------------------------------------------------------- 113 // Print debug strings if and only if the global g_debug is set to 114 // a non-zero value. 115 //---------------------------------------------------------------------- 116 void 117 _DNBLogDebug (const char *format, ...) 118 { 119 if (DNBLogEnabled () && g_debug) 120 { 121 va_list args; 122 va_start (args, format); 123 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG, format, args); 124 va_end (args); 125 } 126 } 127 128 129 //---------------------------------------------------------------------- 130 // Print debug strings if and only if the global g_debug is set to 131 // a non-zero value. 132 //---------------------------------------------------------------------- 133 void 134 _DNBLogDebugVerbose (const char *format, ...) 135 { 136 if (DNBLogEnabled () && g_debug && g_verbose) 137 { 138 va_list args; 139 va_start (args, format); 140 _DNBLogVAPrintf(DNBLOG_FLAG_DEBUG | DNBLOG_FLAG_VERBOSE, format, args); 141 va_end (args); 142 } 143 } 144 145 146 static uint32_t g_message_id = 0; 147 148 //---------------------------------------------------------------------- 149 // Prefix the formatted log string with process and thread IDs and 150 // suffix it with a newline. 151 //---------------------------------------------------------------------- 152 void 153 _DNBLogThreaded (const char *format, ...) 154 { 155 if (DNBLogEnabled ()) 156 { 157 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 158 159 char *arg_msg = NULL; 160 va_list args; 161 va_start (args, format); 162 ::vasprintf (&arg_msg, format, args); 163 va_end (args); 164 165 if (arg_msg != NULL) 166 { 167 static struct timeval g_timeval = { 0 , 0 }; 168 static struct timeval tv; 169 static struct timeval delta; 170 gettimeofday(&tv, NULL); 171 if (g_timeval.tv_sec == 0) 172 { 173 delta.tv_sec = 0; 174 delta.tv_usec = 0; 175 } 176 else 177 { 178 timersub (&tv, &g_timeval, &delta); 179 } 180 g_timeval = tv; 181 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s", 182 ++g_message_id, 183 delta.tv_sec, 184 delta.tv_usec, 185 getpid(), 186 mach_thread_self(), 187 arg_msg); 188 free (arg_msg); 189 } 190 } 191 } 192 193 //---------------------------------------------------------------------- 194 // Prefix the formatted log string with process and thread IDs and 195 // suffix it with a newline. 196 //---------------------------------------------------------------------- 197 void 198 _DNBLogThreadedIf (uint32_t log_bit, const char *format, ...) 199 { 200 if (DNBLogEnabled () && (log_bit & g_log_bits) == log_bit) 201 { 202 //PTHREAD_MUTEX_LOCKER(locker, GetLogThreadedMutex()); 203 204 char *arg_msg = NULL; 205 va_list args; 206 va_start (args, format); 207 ::vasprintf (&arg_msg, format, args); 208 va_end (args); 209 210 if (arg_msg != NULL) 211 { 212 static struct timeval g_timeval = { 0 , 0 }; 213 static struct timeval tv; 214 static struct timeval delta; 215 gettimeofday(&tv, NULL); 216 if (g_timeval.tv_sec == 0) 217 { 218 delta.tv_sec = 0; 219 delta.tv_usec = 0; 220 } 221 else 222 { 223 timersub (&tv, &g_timeval, &delta); 224 } 225 g_timeval = tv; 226 _DNBLog (DNBLOG_FLAG_THREADED, "%u +%u.%06u sec [%4.4x/%4.4x]: %s", 227 ++g_message_id, 228 delta.tv_sec, 229 delta.tv_usec, 230 getpid(), 231 mach_thread_self(), 232 arg_msg); 233 free (arg_msg); 234 } 235 } 236 } 237 238 239 240 //---------------------------------------------------------------------- 241 // Printing of errors that are not fatal. 242 //---------------------------------------------------------------------- 243 void 244 _DNBLogError (const char *format, ...) 245 { 246 if (DNBLogEnabled ()) 247 { 248 char *arg_msg = NULL; 249 va_list args; 250 va_start (args, format); 251 ::vasprintf (&arg_msg, format, args); 252 va_end (args); 253 254 if (arg_msg != NULL) 255 { 256 _DNBLog (DNBLOG_FLAG_ERROR, "error: %s", arg_msg); 257 free (arg_msg); 258 } 259 } 260 } 261 262 //---------------------------------------------------------------------- 263 // Printing of errors that ARE fatal. Exit with ERR exit code 264 // immediately. 265 //---------------------------------------------------------------------- 266 void 267 _DNBLogFatalError (int err, const char *format, ...) 268 { 269 if (DNBLogEnabled ()) 270 { 271 char *arg_msg = NULL; 272 va_list args; 273 va_start (args, format); 274 ::vasprintf (&arg_msg, format, args); 275 va_end (args); 276 277 if (arg_msg != NULL) 278 { 279 _DNBLog (DNBLOG_FLAG_ERROR | DNBLOG_FLAG_FATAL, "error: %s", arg_msg); 280 free (arg_msg); 281 } 282 ::exit (err); 283 } 284 } 285 286 287 //---------------------------------------------------------------------- 288 // Printing of warnings that are not fatal only if verbose mode is 289 // enabled. 290 //---------------------------------------------------------------------- 291 void 292 _DNBLogVerbose (const char *format, ...) 293 { 294 if (DNBLogEnabled () && g_verbose) 295 { 296 va_list args; 297 va_start (args, format); 298 _DNBLogVAPrintf(DNBLOG_FLAG_VERBOSE, format, args); 299 va_end (args); 300 } 301 } 302 303 //---------------------------------------------------------------------- 304 // Printing of warnings that are not fatal only if verbose mode is 305 // enabled. 306 //---------------------------------------------------------------------- 307 void 308 _DNBLogWarningVerbose (const char *format, ...) 309 { 310 if (DNBLogEnabled () && g_verbose) 311 { 312 char *arg_msg = NULL; 313 va_list args; 314 va_start (args, format); 315 ::vasprintf (&arg_msg, format, args); 316 va_end (args); 317 318 if (arg_msg != NULL) 319 { 320 _DNBLog (DNBLOG_FLAG_WARNING | DNBLOG_FLAG_VERBOSE, "warning: %s", arg_msg); 321 free (arg_msg); 322 } 323 } 324 } 325 //---------------------------------------------------------------------- 326 // Printing of warnings that are not fatal. 327 //---------------------------------------------------------------------- 328 void 329 _DNBLogWarning (const char *format, ...) 330 { 331 if (DNBLogEnabled ()) 332 { 333 char *arg_msg = NULL; 334 va_list args; 335 va_start (args, format); 336 ::vasprintf (&arg_msg, format, args); 337 va_end (args); 338 339 if (arg_msg != NULL) 340 { 341 _DNBLog (DNBLOG_FLAG_WARNING, "warning: %s", arg_msg); 342 free (arg_msg); 343 } 344 } 345 } 346 347 #endif 348